| Flutter Impeller |

render_pass_gles.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/renderer/backend/gles/render_pass_gles.h"
6
7 #include <cstdint>
8
9 #include "flutter/fml/trace_event.h"
10 #include "fml/closure.h"
11 #include "fml/logging.h"
12 #include "impeller/base/validation.h"
13 #include "impeller/core/buffer_view.h"
14 #include "impeller/core/formats.h"
15 #include "impeller/renderer/backend/gles/buffer_bindings_gles.h"
16 #include "impeller/renderer/backend/gles/context_gles.h"
17 #include "impeller/renderer/backend/gles/device_buffer_gles.h"
18 #include "impeller/renderer/backend/gles/formats_gles.h"
19 #include "impeller/renderer/backend/gles/gpu_tracer_gles.h"
20 #include "impeller/renderer/backend/gles/pipeline_gles.h"
21 #include "impeller/renderer/backend/gles/texture_gles.h"
22 #include "impeller/renderer/command.h"
23
24 namespace impeller {
25
26 RenderPassGLES::RenderPassGLES(std::shared_ptr<const Context> context,
27 const RenderTarget& target,
28 std::shared_ptr<ReactorGLES> reactor)
29 : RenderPass(std::move(context), target),
30 reactor_(std::move(reactor)),
31 is_valid_(reactor_ && reactor_->IsValid()) {}
32
33 // |RenderPass|
34 RenderPassGLES::~RenderPassGLES() = default;
35
36 // |RenderPass|
37 bool RenderPassGLES::IsValid() const {
38 return is_valid_;
39 }
40
41 // |RenderPass|
42 void RenderPassGLES::OnSetLabel(std::string_view label) {
43 label_ = label;
44 }
45
46 void ConfigureBlending(const ProcTableGLES& gl,
47 const ColorAttachmentDescriptor* color) {
48 if (color->blending_enabled) {
49 gl.Enable(GL_BLEND);
50 gl.BlendFuncSeparate(
51 ToBlendFactor(color->src_color_blend_factor), // src color
52 ToBlendFactor(color->dst_color_blend_factor), // dst color
53 ToBlendFactor(color->src_alpha_blend_factor), // src alpha
54 ToBlendFactor(color->dst_alpha_blend_factor) // dst alpha
55 );
56 gl.BlendEquationSeparate(
57 ToBlendOperation(color->color_blend_op), // mode color
58 ToBlendOperation(color->alpha_blend_op) // mode alpha
59 );
60 } else {
61 gl.Disable(GL_BLEND);
62 }
63
64 {
65 const auto is_set = [](ColorWriteMask mask,
66 ColorWriteMask check) -> GLboolean {
67 return (mask & check) ? GL_TRUE : GL_FALSE;
68 };
69
70 gl.ColorMask(
71 is_set(color->write_mask, ColorWriteMaskBits::kRed), // red
72 is_set(color->write_mask, ColorWriteMaskBits::kGreen), // green
73 is_set(color->write_mask, ColorWriteMaskBits::kBlue), // blue
74 is_set(color->write_mask, ColorWriteMaskBits::kAlpha) // alpha
75 );
76 }
77 }
78
79 void ConfigureStencil(GLenum face,
80 const ProcTableGLES& gl,
81 const StencilAttachmentDescriptor& stencil,
82 uint32_t stencil_reference) {
83 gl.StencilOpSeparate(
84 face, // face
85 ToStencilOp(stencil.stencil_failure), // stencil fail
86 ToStencilOp(stencil.depth_failure), // depth fail
87 ToStencilOp(stencil.depth_stencil_pass) // depth stencil pass
88 );
89 gl.StencilFuncSeparate(face, // face
90 ToCompareFunction(stencil.stencil_compare), // func
91 stencil_reference, // ref
92 stencil.read_mask // mask
93 );
94 gl.StencilMaskSeparate(face, stencil.write_mask);
95 }
96
97 void ConfigureStencil(const ProcTableGLES& gl,
98 const PipelineDescriptor& pipeline,
99 uint32_t stencil_reference) {
100 if (!pipeline.HasStencilAttachmentDescriptors()) {
101 gl.Disable(GL_STENCIL_TEST);
102 return;
103 }
104
105 gl.Enable(GL_STENCIL_TEST);
106 const auto& front = pipeline.GetFrontStencilAttachmentDescriptor();
107 const auto& back = pipeline.GetBackStencilAttachmentDescriptor();
108
109 if (front.has_value() && back.has_value() && front == back) {
110 ConfigureStencil(GL_FRONT_AND_BACK, gl, *front, stencil_reference);
111 return;
112 }
113 if (front.has_value()) {
114 ConfigureStencil(GL_FRONT, gl, *front, stencil_reference);
115 }
116 if (back.has_value()) {
117 ConfigureStencil(GL_BACK, gl, *back, stencil_reference);
118 }
119 }
120
121 //------------------------------------------------------------------------------
122 /// @brief Encapsulates data that will be needed in the reactor for the
123 /// encoding of commands for this render pass.
124 ///
125 struct RenderPassData {
126 Viewport viewport;
127
128 Color clear_color;
129 uint32_t clear_stencil = 0u;
130 Scalar clear_depth = 1.0;
131
132 std::shared_ptr<Texture> color_attachment;
133 std::shared_ptr<Texture> resolve_attachment;
134 std::shared_ptr<Texture> depth_attachment;
135 std::shared_ptr<Texture> stencil_attachment;
136
137 bool clear_color_attachment = true;
138 bool clear_depth_attachment = true;
139 bool clear_stencil_attachment = true;
140
141 bool discard_color_attachment = true;
142 bool discard_depth_attachment = true;
143 bool discard_stencil_attachment = true;
144
145 std::string label;
146 };
147
148 static bool BindVertexBuffer(const ProcTableGLES& gl,
149 BufferBindingsGLES* vertex_desc_gles,
150 const BufferView& vertex_buffer_view,
151 size_t buffer_index) {
152 if (!vertex_buffer_view) {
153 return false;
154 }
155
156 const DeviceBuffer* vertex_buffer = vertex_buffer_view.GetBuffer();
157
158 if (!vertex_buffer) {
159 return false;
160 }
161
162 const auto& vertex_buffer_gles = DeviceBufferGLES::Cast(*vertex_buffer);
163 if (!vertex_buffer_gles.BindAndUploadDataIfNecessary(
164 DeviceBufferGLES::BindingType::kArrayBuffer)) {
165 return false;
166 }
167
168 //--------------------------------------------------------------------------
169 /// Bind the vertex attributes associated with vertex buffer.
170 ///
171 if (!vertex_desc_gles->BindVertexAttributes(
172 gl, buffer_index, vertex_buffer_view.GetRange().offset)) {
173 return false;
174 }
175
176 return true;
177 }
178
179 void RenderPassGLES::ResetGLState(const ProcTableGLES& gl) {
180 gl.Disable(GL_SCISSOR_TEST);
181 gl.Disable(GL_DEPTH_TEST);
182 gl.Disable(GL_STENCIL_TEST);
183 gl.Disable(GL_CULL_FACE);
184 gl.Disable(GL_BLEND);
185 gl.Disable(GL_DITHER);
186 gl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
187 gl.DepthMask(GL_TRUE);
188 gl.StencilMaskSeparate(GL_FRONT, 0xFFFFFFFF);
189 gl.StencilMaskSeparate(GL_BACK, 0xFFFFFFFF);
190 }
191
192 [[nodiscard]] bool EncodeCommandsInReactor(
193 const RenderPassData& pass_data,
194 const ReactorGLES& reactor,
195 const std::vector<Command>& commands,
196 const std::vector<BufferView>& vertex_buffers,
197 const std::vector<TextureAndSampler>& bound_textures,
198 const std::vector<BufferResource>& bound_buffers,
199 const std::shared_ptr<GPUTracerGLES>& tracer,
200 const std::shared_ptr<const Context>& impeller_context) {
201 TRACE_EVENT0("impeller", "RenderPassGLES::EncodeCommandsInReactor");
202
203 const auto& gl = reactor.GetProcTable();
204 #ifdef IMPELLER_DEBUG
205 tracer->MarkFrameStart(gl);
206
207 fml::ScopedCleanupClosure pop_pass_debug_marker(
208 [&gl]() { gl.PopDebugGroup(); });
209 if (!pass_data.label.empty()) {
210 gl.PushDebugGroup(pass_data.label);
211 } else {
212 pop_pass_debug_marker.Release();
213 }
214 #endif // IMPELLER_DEBUG
215
216 TextureGLES& color_gles = TextureGLES::Cast(*pass_data.color_attachment);
217 const bool is_wrapped_fbo = color_gles.IsWrapped();
218
219 std::optional<GLuint> fbo = 0;
220 if (is_wrapped_fbo) {
221 if (color_gles.GetFBO().has_value()) {
222 // NOLINTNEXTLINE(bugprone-unchecked-optional-access)
223 gl.BindFramebuffer(GL_FRAMEBUFFER, *color_gles.GetFBO());
224 }
225 } else {
226 // Create and bind an offscreen FBO.
227 if (!color_gles.GetCachedFBO().IsDead()) {
228 fbo = reactor.GetGLHandle(color_gles.GetCachedFBO());
229 if (!fbo.has_value()) {
230 return false;
231 }
232 gl.BindFramebuffer(GL_FRAMEBUFFER, fbo.value());
233 } else {
234 HandleGLES cached_fbo =
235 reactor.CreateUntrackedHandle(HandleType::kFrameBuffer);
236 color_gles.SetCachedFBO(cached_fbo);
237 fbo = reactor.GetGLHandle(cached_fbo);
238 if (!fbo.has_value()) {
239 return false;
240 }
241 gl.BindFramebuffer(GL_FRAMEBUFFER, fbo.value());
242
243 if (!color_gles.SetAsFramebufferAttachment(
244 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kColor0)) {
245 return false;
246 }
247
248 if (auto depth = TextureGLES::Cast(pass_data.depth_attachment.get())) {
249 if (!depth->SetAsFramebufferAttachment(
250 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kDepth)) {
251 return false;
252 }
253 }
254 if (auto stencil =
255 TextureGLES::Cast(pass_data.stencil_attachment.get())) {
256 if (!stencil->SetAsFramebufferAttachment(
257 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kStencil)) {
258 return false;
259 }
260 }
261
262 auto status = gl.CheckFramebufferStatusDebug(GL_FRAMEBUFFER);
263 if (status != GL_FRAMEBUFFER_COMPLETE) {
264 VALIDATION_LOG << "Could not create a complete framebuffer: "
265 << DebugToFramebufferError(status);
266 return false;
267 }
268 }
269 }
270
271 gl.ClearColor(pass_data.clear_color.red, // red
272 pass_data.clear_color.green, // green
273 pass_data.clear_color.blue, // blue
274 pass_data.clear_color.alpha // alpha
275 );
276 if (pass_data.depth_attachment) {
277 if (gl.DepthRangef.IsAvailable()) {
278 gl.ClearDepthf(pass_data.clear_depth);
279 } else {
280 gl.ClearDepth(pass_data.clear_depth);
281 }
282 }
283 if (pass_data.stencil_attachment) {
284 gl.ClearStencil(pass_data.clear_stencil);
285 }
286
287 GLenum clear_bits = 0u;
288 if (pass_data.clear_color_attachment) {
289 clear_bits |= GL_COLOR_BUFFER_BIT;
290 }
291 if (pass_data.clear_depth_attachment) {
292 clear_bits |= GL_DEPTH_BUFFER_BIT;
293 }
294 if (pass_data.clear_stencil_attachment) {
295 clear_bits |= GL_STENCIL_BUFFER_BIT;
296 }
297
298 RenderPassGLES::ResetGLState(gl);
299
300 gl.Clear(clear_bits);
301
302 // Both the viewport and scissor are specified in framebuffer coordinates.
303 // Impeller's framebuffer coordinate system is top left origin, but OpenGL's
304 // is bottom left origin, so we convert the coordinates here.
305 ISize target_size = pass_data.color_attachment->GetSize();
306
307 //--------------------------------------------------------------------------
308 /// Setup the viewport.
309 ///
310 const auto& viewport = pass_data.viewport;
311 gl.Viewport(viewport.rect.GetX(), // x
312 target_size.height - viewport.rect.GetY() -
313 viewport.rect.GetHeight(), // y
314 viewport.rect.GetWidth(), // width
315 viewport.rect.GetHeight() // height
316 );
317 if (pass_data.depth_attachment) {
318 if (gl.DepthRangef.IsAvailable()) {
319 gl.DepthRangef(viewport.depth_range.z_near, viewport.depth_range.z_far);
320 } else {
321 gl.DepthRange(viewport.depth_range.z_near, viewport.depth_range.z_far);
322 }
323 }
324
325 CullMode current_cull_mode = CullMode::kNone;
326 WindingOrder current_winding_order = WindingOrder::kClockwise;
327 gl.FrontFace(GL_CW);
328
329 for (const auto& command : commands) {
330 #ifdef IMPELLER_DEBUG
331 fml::ScopedCleanupClosure pop_cmd_debug_marker(
332 [&gl]() { gl.PopDebugGroup(); });
333 if (!command.label.empty()) {
334 gl.PushDebugGroup(command.label);
335 } else {
336 pop_cmd_debug_marker.Release();
337 }
338 #endif // IMPELLER_DEBUG
339 const auto& pipeline = PipelineGLES::Cast(*command.pipeline);
340 impeller_context->GetPipelineLibrary()->LogPipelineUsage(
341 pipeline.GetDescriptor());
342 const auto* color_attachment =
343 pipeline.GetDescriptor().GetLegacyCompatibleColorAttachment();
344 if (!color_attachment) {
345 VALIDATION_LOG
346 << "Color attachment is too complicated for a legacy renderer.";
347 return false;
348 }
349
350 //--------------------------------------------------------------------------
351 /// Configure blending.
352 ///
353 ConfigureBlending(gl, color_attachment);
354
355 //--------------------------------------------------------------------------
356 /// Setup stencil.
357 ///
358 ConfigureStencil(gl, pipeline.GetDescriptor(), command.stencil_reference);
359
360 //--------------------------------------------------------------------------
361 /// Configure depth.
362 ///
363 if (auto depth =
364 pipeline.GetDescriptor().GetDepthStencilAttachmentDescriptor();
365 depth.has_value()) {
366 gl.Enable(GL_DEPTH_TEST);
367 gl.DepthFunc(ToCompareFunction(depth->depth_compare));
368 gl.DepthMask(depth->depth_write_enabled ? GL_TRUE : GL_FALSE);
369 } else {
370 gl.Disable(GL_DEPTH_TEST);
371 }
372
373 //--------------------------------------------------------------------------
374 /// Setup the viewport.
375 ///
376 if (command.viewport.has_value()) {
377 gl.Viewport(viewport.rect.GetX(), // x
378 target_size.height - viewport.rect.GetY() -
379 viewport.rect.GetHeight(), // y
380 viewport.rect.GetWidth(), // width
381 viewport.rect.GetHeight() // height
382 );
383 if (pass_data.depth_attachment) {
384 if (gl.DepthRangef.IsAvailable()) {
385 gl.DepthRangef(viewport.depth_range.z_near,
386 viewport.depth_range.z_far);
387 } else {
388 gl.DepthRange(viewport.depth_range.z_near,
389 viewport.depth_range.z_far);
390 }
391 }
392 }
393
394 //--------------------------------------------------------------------------
395 /// Setup the scissor rect.
396 ///
397 if (command.scissor.has_value()) {
398 const auto& scissor = command.scissor.value();
399 gl.Enable(GL_SCISSOR_TEST);
400 gl.Scissor(
401 scissor.GetX(), // x
402 target_size.height - scissor.GetY() - scissor.GetHeight(), // y
403 scissor.GetWidth(), // width
404 scissor.GetHeight() // height
405 );
406 }
407
408 //--------------------------------------------------------------------------
409 /// Setup culling.
410 ///
411 CullMode pipeline_cull_mode = pipeline.GetDescriptor().GetCullMode();
412 if (current_cull_mode != pipeline_cull_mode) {
413 switch (pipeline_cull_mode) {
414 case CullMode::kNone:
415 gl.Disable(GL_CULL_FACE);
416 break;
417 case CullMode::kFrontFace:
418 gl.Enable(GL_CULL_FACE);
419 gl.CullFace(GL_FRONT);
420 break;
421 case CullMode::kBackFace:
422 gl.Enable(GL_CULL_FACE);
423 gl.CullFace(GL_BACK);
424 break;
425 }
426 current_cull_mode = pipeline_cull_mode;
427 }
428
429 //--------------------------------------------------------------------------
430 /// Setup winding order.
431 ///
432 WindingOrder pipeline_winding_order =
433 pipeline.GetDescriptor().GetWindingOrder();
434 if (current_winding_order != pipeline_winding_order) {
435 switch (pipeline.GetDescriptor().GetWindingOrder()) {
436 case WindingOrder::kClockwise:
437 gl.FrontFace(GL_CW);
438 break;
439 case WindingOrder::kCounterClockwise:
440 gl.FrontFace(GL_CCW);
441 break;
442 }
443 current_winding_order = pipeline_winding_order;
444 }
445
446 BufferBindingsGLES* vertex_desc_gles = pipeline.GetBufferBindings();
447
448 //--------------------------------------------------------------------------
449 /// Bind vertex buffers.
450 ///
451 /// Note: There is no need to run `RenderPass::ValidateVertexBuffers` or
452 /// `RenderPass::ValidateIndexBuffer` here, as validation already runs
453 /// when the vertex/index buffers are set on the command.
454 ///
455 for (size_t i = 0; i < command.vertex_buffers.length; i++) {
456 if (!BindVertexBuffer(gl, vertex_desc_gles,
457 vertex_buffers[i + command.vertex_buffers.offset],
458 i)) {
459 return false;
460 }
461 }
462
463 //--------------------------------------------------------------------------
464 /// Bind the pipeline program.
465 ///
466 if (!pipeline.BindProgram()) {
467 return false;
468 }
469
470 //--------------------------------------------------------------------------
471 /// Bind uniform data.
472 ///
473 if (!vertex_desc_gles->BindUniformData(
474 gl, //
475 bound_textures, //
476 bound_buffers, //
477 /*texture_range=*/command.bound_textures, //
478 /*buffer_range=*/command.bound_buffers //
479 )) {
480 return false;
481 }
482
483 //--------------------------------------------------------------------------
484 /// Determine the primitive type.
485 ///
486 // GLES doesn't support setting the fill mode, so override the primitive
487 // with GL_LINE_STRIP to somewhat emulate PolygonMode::kLine. This isn't
488 // correct; full triangle outlines won't be drawn and disconnected
489 // geometry may appear connected. However this can still be useful for
490 // wireframe debug views.
491 GLenum mode =
492 pipeline.GetDescriptor().GetPolygonMode() == PolygonMode::kLine
493 ? GL_LINE_STRIP
494 : ToMode(pipeline.GetDescriptor().GetPrimitiveType());
495
496 //--------------------------------------------------------------------------
497 /// Finally! Invoke the draw call.
498 ///
499 if (command.index_type == IndexType::kNone) {
500 gl.DrawArrays(mode, command.base_vertex, command.element_count);
501 } else {
502 // Bind the index buffer if necessary.
503 auto index_buffer_view = command.index_buffer;
504 const DeviceBuffer* index_buffer = index_buffer_view.GetBuffer();
505 const auto& index_buffer_gles = DeviceBufferGLES::Cast(*index_buffer);
506 if (!index_buffer_gles.BindAndUploadDataIfNecessary(
507 DeviceBufferGLES::BindingType::kElementArrayBuffer)) {
508 return false;
509 }
510 gl.DrawElements(mode, // mode
511 command.element_count, // count
512 ToIndexType(command.index_type), // type
513 reinterpret_cast<const GLvoid*>(static_cast<GLsizei>(
514 index_buffer_view.GetRange().offset)) // indices
515 );
516 }
517
518 //--------------------------------------------------------------------------
519 /// Unbind vertex attribs.
520 ///
521 if (!vertex_desc_gles->UnbindVertexAttributes(gl)) {
522 return false;
523 }
524 }
525
526 if (pass_data.resolve_attachment &&
527 !gl.GetCapabilities()->SupportsImplicitResolvingMSAA() &&
528 !is_wrapped_fbo) {
529 FML_DCHECK(pass_data.resolve_attachment != pass_data.color_attachment);
530 // Perform multisample resolve via blit.
531 // Create and bind a resolve FBO.
532 GLuint resolve_fbo;
533 gl.GenFramebuffers(1u, &resolve_fbo);
534 gl.BindFramebuffer(GL_FRAMEBUFFER, resolve_fbo);
535
536 if (!TextureGLES::Cast(*pass_data.resolve_attachment)
537 .SetAsFramebufferAttachment(
538 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kColor0)) {
539 return false;
540 }
541
542 auto status = gl.CheckFramebufferStatusDebug(GL_FRAMEBUFFER);
543 if (status != GL_FRAMEBUFFER_COMPLETE) {
544 VALIDATION_LOG << "Could not create a complete frambuffer: "
545 << DebugToFramebufferError(status);
546 return false;
547 }
548
549 // Bind MSAA renderbuffer to read framebuffer.
550 gl.BindFramebuffer(GL_READ_FRAMEBUFFER, fbo.value());
551 gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo);
552
553 RenderPassGLES::ResetGLState(gl);
554 auto size = pass_data.color_attachment->GetSize();
555
556 gl.BlitFramebuffer(/*srcX0=*/0,
557 /*srcY0=*/0,
558 /*srcX1=*/size.width,
559 /*srcY1=*/size.height,
560 /*dstX0=*/0,
561 /*dstY0=*/0,
562 /*dstX1=*/size.width,
563 /*dstY1=*/size.height,
564 /*mask=*/GL_COLOR_BUFFER_BIT,
565 /*filter=*/GL_NEAREST);
566
567 gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, GL_NONE);
568 gl.BindFramebuffer(GL_READ_FRAMEBUFFER, GL_NONE);
569 gl.DeleteFramebuffers(1u, &resolve_fbo);
570 // Rebind the original FBO so that we can discard it below.
571 gl.BindFramebuffer(GL_FRAMEBUFFER, fbo.value());
572 }
573
574 GLint framebuffer_id = 0;
575 gl.GetIntegerv(GL_FRAMEBUFFER_BINDING, &framebuffer_id);
576 const bool is_default_fbo = framebuffer_id == 0;
577
578 if (gl.DiscardFramebufferEXT.IsAvailable()) {
579 std::array<GLenum, 3> attachments;
580 size_t attachment_count = 0;
581
582 // TODO(130048): discarding stencil or depth on the default fbo causes Angle
583 // to discard the entire render target. Until we know the reason, default to
584 // storing.
585 bool angle_safe = gl.GetCapabilities()->IsANGLE() ? !is_default_fbo : true;
586
587 if (pass_data.discard_color_attachment) {
588 attachments[attachment_count++] =
589 (is_default_fbo ? GL_COLOR_EXT : GL_COLOR_ATTACHMENT0);
590 }
591
592 if (pass_data.discard_depth_attachment && angle_safe) {
593 attachments[attachment_count++] =
594 (is_default_fbo ? GL_DEPTH_EXT : GL_DEPTH_ATTACHMENT);
595 }
596
597 if (pass_data.discard_stencil_attachment && angle_safe) {
598 attachments[attachment_count++] =
599 (is_default_fbo ? GL_STENCIL_EXT : GL_STENCIL_ATTACHMENT);
600 }
601 gl.DiscardFramebufferEXT(GL_FRAMEBUFFER, // target
602 attachment_count, // attachments to discard
603 attachments.data() // size
604 );
605 }
606
607 #ifdef IMPELLER_DEBUG
608 if (is_default_fbo) {
609 tracer->MarkFrameEnd(gl);
610 }
611 #endif // IMPELLER_DEBUG
612
613 return true;
614 }
615
616 // |RenderPass|
617 bool RenderPassGLES::OnEncodeCommands(const Context& context) const {
618 if (!IsValid()) {
619 return false;
620 }
621 const auto& render_target = GetRenderTarget();
622 if (!render_target.HasColorAttachment(0u)) {
623 return false;
624 }
625 const ColorAttachment& color0 = render_target.GetColorAttachment(0);
626 const std::optional<DepthAttachment>& depth0 =
627 render_target.GetDepthAttachment();
628 const std::optional<StencilAttachment>& stencil0 =
629 render_target.GetStencilAttachment();
630
631 auto pass_data = std::make_shared<RenderPassData>();
632 pass_data->label = label_;
633 pass_data->viewport.rect = Rect::MakeSize(GetRenderTargetSize());
634
635 //----------------------------------------------------------------------------
636 /// Setup color data.
637 ///
638 pass_data->color_attachment = color0.texture;
639 pass_data->resolve_attachment = color0.resolve_texture;
640 pass_data->clear_color = color0.clear_color;
641 pass_data->clear_color_attachment = CanClearAttachment(color0.load_action);
642 pass_data->discard_color_attachment =
643 CanDiscardAttachmentWhenDone(color0.store_action);
644
645 // When we are using EXT_multisampled_render_to_texture, it is implicitly
646 // resolved when we bind the texture to the framebuffer. We don't need to
647 // discard the attachment when we are done. If not using
648 // EXT_multisampled_render_to_texture but still using MSAA we discard the
649 // attachment as normal.
650 if (color0.resolve_texture) {
651 pass_data->discard_color_attachment =
652 pass_data->discard_color_attachment &&
653 !context.GetCapabilities()->SupportsImplicitResolvingMSAA();
654 }
655
656 //----------------------------------------------------------------------------
657 /// Setup depth data.
658 ///
659 if (depth0.has_value()) {
660 pass_data->depth_attachment = depth0->texture;
661 pass_data->clear_depth = depth0->clear_depth;
662 pass_data->clear_depth_attachment = CanClearAttachment(depth0->load_action);
663 pass_data->discard_depth_attachment =
664 CanDiscardAttachmentWhenDone(depth0->store_action);
665 }
666
667 //----------------------------------------------------------------------------
668 /// Setup stencil data.
669 ///
670 if (stencil0.has_value()) {
671 pass_data->stencil_attachment = stencil0->texture;
672 pass_data->clear_stencil = stencil0->clear_stencil;
673 pass_data->clear_stencil_attachment =
674 CanClearAttachment(stencil0->load_action);
675 pass_data->discard_stencil_attachment =
676 CanDiscardAttachmentWhenDone(stencil0->store_action);
677 }
678
679 return reactor_->AddOperation(
680 [pass_data = std::move(pass_data), render_pass = shared_from_this(),
681 tracer =
682 ContextGLES::Cast(context).GetGPUTracer()](const auto& reactor) {
683 auto result = EncodeCommandsInReactor(
684 /*pass_data=*/*pass_data, //
685 /*reactor=*/reactor, //
686 /*commands=*/render_pass->commands_, //
687 /*vertex_buffers=*/render_pass->vertex_buffers_, //
688 /*bound_textures=*/render_pass->bound_textures_, //
689 /*bound_buffers=*/render_pass->bound_buffers_, //
690 /*tracer=*/tracer, //
691 /*impeller_context=*/render_pass->context_);
692 FML_CHECK(result)
693 << "Must be able to encode GL commands without error.";
694 },
695 /*defer=*/true);
696 }
697
698 } // namespace impeller
buffer_bindings_gles.h
buffer_view.h
impeller::BufferBindingsGLES
Sets up stage bindings for single draw call in the OpenGLES backend.
Definition: buffer_bindings_gles.h:28
impeller::BufferBindingsGLES::BindVertexAttributes
bool BindVertexAttributes(const ProcTableGLES &gl, size_t binding, size_t vertex_offset)
Definition: buffer_bindings_gles.cc:194
impeller::BufferBindingsGLES::UnbindVertexAttributes
bool UnbindVertexAttributes(const ProcTableGLES &gl)
Definition: buffer_bindings_gles.cc:247
impeller::BufferBindingsGLES::BindUniformData
bool BindUniformData(const ProcTableGLES &gl, const std::vector< TextureAndSampler > &bound_textures, const std::vector< BufferResource > &bound_buffers, Range texture_range, Range buffer_range)
Definition: buffer_bindings_gles.cc:222
impeller::DeviceBuffer
Definition: device_buffer.h:18
impeller::HandleGLES
Represents a handle to an underlying OpenGL object. Unlike OpenGL object handles, these handles can b...
Definition: handle_gles.h:42
impeller::HandleGLES::IsDead
constexpr bool IsDead() const
Determines if the handle is dead.
Definition: handle_gles.h:58
impeller::PipelineDescriptor
Definition: pipeline_descriptor.h:24
impeller::PipelineDescriptor::GetBackStencilAttachmentDescriptor
std::optional< StencilAttachmentDescriptor > GetBackStencilAttachmentDescriptor() const
Definition: pipeline_descriptor.cc:244
impeller::PipelineDescriptor::GetFrontStencilAttachmentDescriptor
std::optional< StencilAttachmentDescriptor > GetFrontStencilAttachmentDescriptor() const
Definition: pipeline_descriptor.cc:203
impeller::PipelineDescriptor::HasStencilAttachmentDescriptors
bool HasStencilAttachmentDescriptors() const
Definition: pipeline_descriptor.cc:248
impeller::ProcTableGLES
Definition: proc_table_gles.h:283
impeller::ProcTableGLES::PushDebugGroup
void PushDebugGroup(const std::string &string) const
Definition: proc_table_gles.cc:399
impeller::ReactorGLES
The reactor attempts to make thread-safe usage of OpenGL ES easier to reason about.
Definition: reactor_gles.h:57
impeller::ReactorGLES::GetGLHandle
std::optional< GLuint > GetGLHandle(const HandleGLES &handle) const
Returns the OpenGL handle for a reactor handle if one is available. This is typically only safe to ca...
Definition: reactor_gles.cc:151
impeller::ReactorGLES::CreateUntrackedHandle
HandleGLES CreateUntrackedHandle(HandleType type) const
Create a handle that is not managed by ReactorGLES.
Definition: reactor_gles.cc:203
impeller::ReactorGLES::GetProcTable
const ProcTableGLES & GetProcTable() const
Get the OpenGL proc. table the reactor uses to manage handles.
Definition: reactor_gles.cc:122
impeller::TextureGLES
Definition: texture_gles.h:19
impeller::TextureGLES::GetCachedFBO
const HandleGLES & GetCachedFBO() const
Retrieve the cached FBO object, or a dead handle if there is no object.
Definition: texture_gles.cc:699
impeller::TextureGLES::SetCachedFBO
void SetCachedFBO(HandleGLES fbo)
Definition: texture_gles.cc:695
impeller::TextureGLES::SetAsFramebufferAttachment
bool SetAsFramebufferAttachment(GLenum target, AttachmentType attachment_type) const
Definition: texture_gles.cc:620
impeller::TextureGLES::GetFBO
std::optional< GLuint > GetFBO() const
Definition: texture_gles.cc:681
impeller::TextureGLES::IsWrapped
bool IsWrapped() const
Definition: texture_gles.cc:677
command.h
formats.h
device_buffer_gles.h
formats_gles.h
gpu_tracer_gles.h
impeller
Definition: allocation.cc:12
impeller::EncodeCommandsInReactor
bool EncodeCommandsInReactor(const RenderPassData &pass_data, const ReactorGLES &reactor, const std::vector< Command > &commands, const std::vector< BufferView > &vertex_buffers, const std::vector< TextureAndSampler > &bound_textures, const std::vector< BufferResource > &bound_buffers, const std::shared_ptr< GPUTracerGLES > &tracer, const std::shared_ptr< const Context > &impeller_context)
Definition: render_pass_gles.cc:192
impeller::CanClearAttachment
constexpr bool CanClearAttachment(LoadAction action)
Definition: formats.h:242
impeller::Scalar
float Scalar
Definition: scalar.h:19
impeller::ToIndexType
constexpr GLenum ToIndexType(IndexType type)
Definition: formats_gles.h:35
impeller::ToCompareFunction
constexpr GLenum ToCompareFunction(CompareFunction func)
Definition: formats_gles.h:70
impeller::DebugToFramebufferError
std::string DebugToFramebufferError(int status)
Definition: formats_gles.cc:9
impeller::CullMode
CullMode
Definition: formats.h:340
impeller::ToStencilOp
constexpr GLenum ToStencilOp(StencilOperation op)
Definition: formats_gles.h:48
impeller::ToMode
constexpr GLenum ToMode(PrimitiveType primitive_type)
Definition: formats_gles.h:17
impeller::WindingOrder
WindingOrder
Definition: formats.h:22
impeller::ConfigureBlending
void ConfigureBlending(const ProcTableGLES &gl, const ColorAttachmentDescriptor *color)
Definition: render_pass_gles.cc:46
impeller::ConfigureStencil
void ConfigureStencil(const ProcTableGLES &gl, const PipelineDescriptor &pipeline, uint32_t stencil_reference)
Definition: render_pass_gles.cc:97
impeller::BindVertexBuffer
static bool BindVertexBuffer(const ProcTableGLES &gl, BufferBindingsGLES *vertex_desc_gles, const BufferView &vertex_buffer_view, size_t buffer_index)
Definition: render_pass_gles.cc:148
impeller::ToBlendFactor
constexpr GLenum ToBlendFactor(BlendFactor factor)
Definition: formats_gles.h:92
impeller::ToBlendOperation
constexpr GLenum ToBlendOperation(BlendOperation op)
Definition: formats_gles.h:128
impeller::CanDiscardAttachmentWhenDone
constexpr bool CanDiscardAttachmentWhenDone(StoreAction action)
Definition: formats.h:253
std
Definition: comparable.h:95
pipeline_gles.h
render_pass_gles.h
context_gles.h
impeller::BufferView
Definition: buffer_view.h:19
impeller::BufferView::GetRange
Range GetRange() const
Definition: buffer_view.h:27
impeller::BufferView::GetBuffer
const DeviceBuffer * GetBuffer() const
Definition: buffer_view.cc:17
impeller::ColorAttachmentDescriptor
Describe the color attachment that will be used with this pipeline.
Definition: formats.h:522
impeller::ColorAttachmentDescriptor::blending_enabled
bool blending_enabled
Definition: formats.h:524
impeller::ColorAttachmentDescriptor::color_blend_op
BlendOperation color_blend_op
Definition: formats.h:527
impeller::ColorAttachmentDescriptor::dst_color_blend_factor
BlendFactor dst_color_blend_factor
Definition: formats.h:528
impeller::ColorAttachmentDescriptor::write_mask
ColorWriteMask write_mask
Definition: formats.h:534
impeller::ColorAttachmentDescriptor::src_alpha_blend_factor
BlendFactor src_alpha_blend_factor
Definition: formats.h:530
impeller::ColorAttachmentDescriptor::alpha_blend_op
BlendOperation alpha_blend_op
Definition: formats.h:531
impeller::ColorAttachmentDescriptor::src_color_blend_factor
BlendFactor src_color_blend_factor
Definition: formats.h:526
impeller::ColorAttachmentDescriptor::dst_alpha_blend_factor
BlendFactor dst_alpha_blend_factor
Definition: formats.h:532
impeller::Color
Definition: color.h:124
impeller::Color::blue
Scalar blue
Definition: color.h:138
impeller::Color::alpha
Scalar alpha
Definition: color.h:143
impeller::Color::red
Scalar red
Definition: color.h:128
impeller::Color::green
Scalar green
Definition: color.h:133
impeller::Mask< ColorWriteMaskBits >
impeller::Range::offset
size_t offset
Definition: range.h:14
impeller::RenderPassData
Encapsulates data that will be needed in the reactor for the encoding of commands for this render pas...
Definition: render_pass_gles.cc:125
impeller::RenderPassData::clear_color_attachment
bool clear_color_attachment
Definition: render_pass_gles.cc:137
impeller::RenderPassData::clear_depth
Scalar clear_depth
Definition: render_pass_gles.cc:130
impeller::RenderPassData::viewport
Viewport viewport
Definition: render_pass_gles.cc:126
impeller::RenderPassData::depth_attachment
std::shared_ptr< Texture > depth_attachment
Definition: render_pass_gles.cc:134
impeller::RenderPassData::label
std::string label
Definition: render_pass_gles.cc:145
impeller::RenderPassData::discard_color_attachment
bool discard_color_attachment
Definition: render_pass_gles.cc:141
impeller::RenderPassData::clear_color
Color clear_color
Definition: render_pass_gles.cc:128
impeller::RenderPassData::clear_stencil_attachment
bool clear_stencil_attachment
Definition: render_pass_gles.cc:139
impeller::RenderPassData::color_attachment
std::shared_ptr< Texture > color_attachment
Definition: render_pass_gles.cc:132
impeller::RenderPassData::discard_depth_attachment
bool discard_depth_attachment
Definition: render_pass_gles.cc:142
impeller::RenderPassData::stencil_attachment
std::shared_ptr< Texture > stencil_attachment
Definition: render_pass_gles.cc:135
impeller::RenderPassData::discard_stencil_attachment
bool discard_stencil_attachment
Definition: render_pass_gles.cc:143
impeller::RenderPassData::clear_stencil
uint32_t clear_stencil
Definition: render_pass_gles.cc:129
impeller::RenderPassData::resolve_attachment
std::shared_ptr< Texture > resolve_attachment
Definition: render_pass_gles.cc:133
impeller::RenderPassData::clear_depth_attachment
bool clear_depth_attachment
Definition: render_pass_gles.cc:138
impeller::StencilAttachmentDescriptor
Definition: formats.h:614
impeller::StencilAttachmentDescriptor::stencil_failure
StencilOperation stencil_failure
Definition: formats.h:624
impeller::StencilAttachmentDescriptor::write_mask
uint32_t write_mask
Definition: formats.h:644
impeller::StencilAttachmentDescriptor::stencil_compare
CompareFunction stencil_compare
Definition: formats.h:620
impeller::StencilAttachmentDescriptor::depth_failure
StencilOperation depth_failure
Definition: formats.h:629
impeller::StencilAttachmentDescriptor::depth_stencil_pass
StencilOperation depth_stencil_pass
Definition: formats.h:633
impeller::StencilAttachmentDescriptor::read_mask
uint32_t read_mask
Definition: formats.h:639
impeller::TSize
Definition: size.h:25
impeller::TSize::height
Type height
Definition: size.h:29
impeller::Viewport
Definition: formats.h:406
texture_gles.h
validation.h
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:91