240 const std::vector<Command>& commands,
241 const std::vector<BufferView>& vertex_buffers,
242 const std::vector<TextureAndSampler>& bound_textures,
243 const std::vector<BufferResource>& bound_buffers,
244 const std::shared_ptr<GPUTracerGLES>& tracer,
245 const std::shared_ptr<const Context>& impeller_context) {
246 TRACE_EVENT0(
"impeller",
"RenderPassGLES::EncodeCommandsInReactor");
248 const auto& gl =
reactor.GetProcTable();
250 tracer->MarkFrameStart(gl);
253 [&gl]() { gl.PopDebugGroup(); });
254 if (!pass_data.
label.empty()) {
255 gl.PushDebugGroup(pass_data.
label);
257 pop_pass_debug_marker.
Release();
262 const bool is_wrapped_fbo = color_gles.
IsWrapped();
264 std::optional<GLuint> fbo = 0;
265 if (is_wrapped_fbo) {
266 if (color_gles.
GetFBO().has_value()) {
268 gl.BindFramebuffer(GL_FRAMEBUFFER, *color_gles.
GetFBO());
275 bool needs_attachment =
false;
278 reactor.CreateUntrackedHandle(HandleType::kFrameBuffer));
279 needs_attachment =
true;
282 if (!fbo.has_value()) {
285 gl.BindFramebuffer(GL_FRAMEBUFFER, fbo.value());
287 if (needs_attachment ||
291 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kColor0,
297 if (!depth->SetAsFramebufferAttachment(
298 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kDepth,
305 if (!stencil->SetAsFramebufferAttachment(
306 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kStencil,
312 auto status = gl.CheckFramebufferStatusDebug(GL_FRAMEBUFFER);
313 if (status != GL_FRAMEBUFFER_COMPLETE) {
329 if (gl.DepthRangef.IsAvailable()) {
339 GLenum clear_bits = 0u;
341 clear_bits |= GL_COLOR_BUFFER_BIT;
344 clear_bits |= GL_DEPTH_BUFFER_BIT;
347 clear_bits |= GL_STENCIL_BUFFER_BIT;
350 RenderPassGLES::ResetGLState(gl);
352 gl.Clear(clear_bits);
361 const bool flip_y = !is_wrapped_fbo;
362 const float y_flip_value = flip_y ? -1.0f : 1.0f;
364 std::optional<Viewport> current_viewport;
365 CullMode current_cull_mode = CullMode::kNone;
366 WindingOrder current_winding_order = WindingOrder::kClockwise;
368 gl.FrontFace(flip_y ? GL_CCW : GL_CW);
370 for (
const auto& command : commands) {
373 [&gl]() { gl.PopDebugGroup(); });
374 if (!command.label.empty()) {
375 gl.PushDebugGroup(command.label);
377 pop_cmd_debug_marker.
Release();
380 const auto&
pipeline = PipelineGLES::Cast(*command.pipeline);
381 impeller_context->GetPipelineLibrary()->LogPipelineUsage(
383 const auto* color_attachment =
384 pipeline.GetDescriptor().GetLegacyCompatibleColorAttachment();
385 if (!color_attachment) {
387 <<
"Color attachment is too complicated for a legacy renderer.";
405 pipeline.GetDescriptor().GetDepthStencilAttachmentDescriptor();
407 gl.Enable(GL_DEPTH_TEST);
409 gl.DepthMask(depth->depth_write_enabled ? GL_TRUE : GL_FALSE);
411 gl.Disable(GL_DEPTH_TEST);
428 if (command.scissor.has_value()) {
429 const auto& scissor = command.scissor.value();
430 gl.Enable(GL_SCISSOR_TEST);
432 const auto scissor_y_gl =
433 flip_y ? scissor.GetY()
434 : target_size.
height - scissor.GetY() - scissor.GetHeight();
435 gl.Scissor(scissor.GetX(),
437 scissor.GetWidth(), scissor.GetHeight());
444 if (current_cull_mode != pipeline_cull_mode) {
445 switch (pipeline_cull_mode) {
446 case CullMode::kNone:
447 gl.Disable(GL_CULL_FACE);
449 case CullMode::kFrontFace:
450 gl.Enable(GL_CULL_FACE);
451 gl.CullFace(GL_FRONT);
453 case CullMode::kBackFace:
454 gl.Enable(GL_CULL_FACE);
455 gl.CullFace(GL_BACK);
458 current_cull_mode = pipeline_cull_mode;
466 pipeline.GetDescriptor().GetWindingOrder();
467 if (current_winding_order != pipeline_winding_order) {
468 switch (
pipeline.GetDescriptor().GetWindingOrder()) {
469 case WindingOrder::kClockwise:
470 gl.FrontFace(flip_y ? GL_CCW : GL_CW);
472 case WindingOrder::kCounterClockwise:
473 gl.FrontFace(flip_y ? GL_CW : GL_CCW);
476 current_winding_order = pipeline_winding_order;
488 for (
size_t i = 0;
i < command.vertex_buffers.length;
i++) {
490 vertex_buffers[
i + command.vertex_buffers.offset],
505 const GLint y_flip_loc =
pipeline.GetYFlipUniformLocation();
506 if (y_flip_loc >= 0) {
507 gl.Uniform1fv(y_flip_loc, 1, &y_flip_value);
517 command.bound_textures,
518 command.bound_buffers
532 pipeline.GetDescriptor().GetPolygonMode() == PolygonMode::kLine
545 const bool instanced = command.instance_count > 1u;
546 const bool hardware_instanced =
548 (gl.DrawArraysInstanced.IsAvailable() ||
549 gl.DrawArraysInstancedEXT.IsAvailable()) &&
550 (gl.DrawElementsInstanced.IsAvailable() ||
551 gl.DrawElementsInstancedEXT.IsAvailable()) &&
552 (gl.VertexAttribDivisor.IsAvailable() ||
553 gl.VertexAttribDivisorEXT.IsAvailable());
554 const bool emulate_instanced = instanced && !hardware_instanced;
555 const GLsizei instance_count =
static_cast<GLsizei
>(command.instance_count);
561 const bool is_indexed = command.index_type != IndexType::kNone &&
562 command.index_type != IndexType::kUnknown;
565 const GLvoid* index_offset =
nullptr;
567 auto index_buffer_view = command.index_buffer;
568 const DeviceBuffer* index_buffer = index_buffer_view.GetBuffer();
569 const auto& index_buffer_gles = DeviceBufferGLES::Cast(*index_buffer);
570 if (!index_buffer_gles.BindAndUploadDataIfNecessary(
571 DeviceBufferGLES::BindingType::kElementArrayBuffer)) {
574 index_offset =
reinterpret_cast<const GLvoid*
>(
575 static_cast<uintptr_t
>(index_buffer_view.GetRange().offset));
580 const auto draw_geometry = [&]() {
582 gl.DrawArrays(mode, command.base_vertex, command.element_count);
584 gl.DrawElements(mode, command.element_count,
589 if (command.instance_count == 0u) {
592 }
else if (emulate_instanced) {
598 for (
size_t i = 0;
i < command.vertex_buffers.length;
i++) {
600 gl, vertex_desc_gles,
601 vertex_buffers[
i + command.vertex_buffers.offset],
i,
609 }
else if (hardware_instanced) {
612 const auto& gl_draw_arrays_instanced =
613 gl.DrawArraysInstanced.IsAvailable() ? gl.DrawArraysInstanced
614 : gl.DrawArraysInstancedEXT;
615 gl_draw_arrays_instanced(mode, command.base_vertex,
616 command.element_count, instance_count);
618 const auto& gl_draw_elements_instanced =
619 gl.DrawElementsInstanced.IsAvailable()
620 ? gl.DrawElementsInstanced
621 : gl.DrawElementsInstancedEXT;
622 gl_draw_elements_instanced(mode, command.element_count,
624 index_offset, instance_count);
639 !gl.GetCapabilities()->SupportsImplicitResolvingMSAA() &&
644 std::optional<GLuint> resolve_fbo_opt;
650 if (!resolve_fbo_opt.has_value()) {
652 reactor.CreateUntrackedHandle(HandleType::kFrameBuffer);
654 resolve_fbo_opt =
reactor.GetGLHandle(cached_fbo);
655 gl.BindFramebuffer(GL_FRAMEBUFFER, resolve_fbo_opt.value());
658 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kColor0)) {
662 auto status = gl.CheckFramebufferStatusDebug(GL_FRAMEBUFFER);
663 if (status != GL_FRAMEBUFFER_COMPLETE) {
669 gl.BindFramebuffer(GL_FRAMEBUFFER, resolve_fbo_opt.value());
673 gl.BindFramebuffer(GL_READ_FRAMEBUFFER, fbo.value());
674 gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo_opt.value());
676 RenderPassGLES::ResetGLState(gl);
679 gl.BlitFramebuffer(0,
690 gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, GL_NONE);
691 gl.BindFramebuffer(GL_READ_FRAMEBUFFER, GL_NONE);
693 gl.BindFramebuffer(GL_FRAMEBUFFER, fbo.value());
700 if (gl.InvalidateFramebuffer.IsAvailable()) {
701 std::array<GLenum, 3> attachments;
702 size_t attachment_count = 0;
704 bool angle_safe = gl.GetCapabilities()->IsANGLE() ? !is_default_fbo :
true;
707 attachments[attachment_count++] =
708 (is_default_fbo ? GL_COLOR_EXT : GL_COLOR_ATTACHMENT0);
712 attachments[attachment_count++] =
713 (is_default_fbo ? GL_DEPTH_EXT : GL_DEPTH_ATTACHMENT);
717 attachments[attachment_count++] =
718 (is_default_fbo ? GL_STENCIL_EXT : GL_STENCIL_ATTACHMENT);
720 gl.InvalidateFramebuffer(GL_FRAMEBUFFER,
724 }
else if (gl.DiscardFramebufferEXT.IsAvailable()) {
725 std::array<GLenum, 3> attachments;
726 size_t attachment_count = 0;
731 bool angle_safe = gl.GetCapabilities()->IsANGLE() ? !is_default_fbo :
true;
734 attachments[attachment_count++] =
735 (is_default_fbo ? GL_COLOR_EXT : GL_COLOR_ATTACHMENT0);
739 attachments[attachment_count++] =
740 (is_default_fbo ? GL_DEPTH_EXT : GL_DEPTH_ATTACHMENT);
744 attachments[attachment_count++] =
745 (is_default_fbo ? GL_STENCIL_EXT : GL_STENCIL_ATTACHMENT);
747 gl.DiscardFramebufferEXT(GL_FRAMEBUFFER,
754 if (is_default_fbo) {
755 tracer->MarkFrameEnd(gl);