9 #include "flutter/fml/trace_event.h"
10 #include "fml/closure.h"
11 #include "fml/logging.h"
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()) {}
34 RenderPassGLES::~RenderPassGLES() =
default;
37 bool RenderPassGLES::IsValid()
const {
42 void RenderPassGLES::OnSetLabel(std::string_view label) {
56 gl.BlendEquationSeparate(
67 return (mask & check) ? GL_TRUE : GL_FALSE;
71 is_set(color->
write_mask, ColorWriteMaskBits::kRed),
72 is_set(color->
write_mask, ColorWriteMaskBits::kGreen),
73 is_set(color->
write_mask, ColorWriteMaskBits::kBlue),
74 is_set(color->
write_mask, ColorWriteMaskBits::kAlpha)
82 uint32_t stencil_reference) {
89 gl.StencilFuncSeparate(face,
94 gl.StencilMaskSeparate(face, stencil.
write_mask);
99 uint32_t stencil_reference) {
101 gl.Disable(GL_STENCIL_TEST);
105 gl.Enable(GL_STENCIL_TEST);
109 if (front.has_value() && back.has_value() && front == back) {
113 if (front.has_value()) {
116 if (back.has_value()) {
129 uint32_t clear_stencil = 0u;
137 bool clear_color_attachment =
true;
138 bool clear_depth_attachment =
true;
139 bool clear_stencil_attachment =
true;
141 bool discard_color_attachment =
true;
142 bool discard_depth_attachment =
true;
143 bool discard_stencil_attachment =
true;
151 size_t buffer_index) {
152 if (!vertex_buffer_view) {
158 if (!vertex_buffer) {
162 const auto& vertex_buffer_gles = DeviceBufferGLES::Cast(*vertex_buffer);
163 if (!vertex_buffer_gles.BindAndUploadDataIfNecessary(
164 DeviceBufferGLES::BindingType::kArrayBuffer)) {
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);
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 TRACE_EVENT0(
"impeller",
"RenderPassGLES::EncodeCommandsInReactor");
203 #ifdef IMPELLER_DEBUG
204 tracer->MarkFrameStart(gl);
206 fml::ScopedCleanupClosure pop_pass_debug_marker(
207 [&gl]() { gl.PopDebugGroup(); });
208 if (!pass_data.
label.empty()) {
211 pop_pass_debug_marker.Release();
216 const bool is_default_fbo = color_gles.
IsWrapped();
218 std::optional<GLuint> fbo = 0;
219 if (is_default_fbo) {
220 if (color_gles.
GetFBO().has_value()) {
222 gl.BindFramebuffer(GL_FRAMEBUFFER, *color_gles.
GetFBO());
228 if (!fbo.has_value()) {
231 gl.BindFramebuffer(GL_FRAMEBUFFER, fbo.value());
237 if (!fbo.has_value()) {
240 gl.BindFramebuffer(GL_FRAMEBUFFER, fbo.value());
243 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kColor0)) {
248 if (!depth->SetAsFramebufferAttachment(
249 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kDepth)) {
255 if (!stencil->SetAsFramebufferAttachment(
256 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kStencil)) {
261 auto status = gl.CheckFramebufferStatus(GL_FRAMEBUFFER);
262 if (status != GL_FRAMEBUFFER_COMPLETE) {
276 if (gl.DepthRangef.IsAvailable()) {
286 GLenum clear_bits = 0u;
288 clear_bits |= GL_COLOR_BUFFER_BIT;
291 clear_bits |= GL_DEPTH_BUFFER_BIT;
294 clear_bits |= GL_STENCIL_BUFFER_BIT;
297 RenderPassGLES::ResetGLState(gl);
299 gl.Clear(clear_bits);
309 const auto& viewport = pass_data.
viewport;
310 gl.Viewport(viewport.rect.GetX(),
311 target_size.
height - viewport.rect.GetY() -
312 viewport.rect.GetHeight(),
313 viewport.rect.GetWidth(),
314 viewport.rect.GetHeight()
317 if (gl.DepthRangef.IsAvailable()) {
318 gl.DepthRangef(viewport.depth_range.z_near, viewport.depth_range.z_far);
320 gl.DepthRange(viewport.depth_range.z_near, viewport.depth_range.z_far);
324 CullMode current_cull_mode = CullMode::kNone;
325 WindingOrder current_winding_order = WindingOrder::kClockwise;
328 for (
const auto& command : commands) {
329 #ifdef IMPELLER_DEBUG
330 fml::ScopedCleanupClosure pop_cmd_debug_marker(
331 [&gl]() { gl.PopDebugGroup(); });
332 if (!command.label.empty()) {
333 gl.PushDebugGroup(command.label);
335 pop_cmd_debug_marker.Release();
339 const auto& pipeline = PipelineGLES::Cast(*command.pipeline);
341 const auto* color_attachment =
342 pipeline.GetDescriptor().GetLegacyCompatibleColorAttachment();
343 if (!color_attachment) {
345 <<
"Color attachment is too complicated for a legacy renderer.";
363 pipeline.GetDescriptor().GetDepthStencilAttachmentDescriptor();
365 gl.Enable(GL_DEPTH_TEST);
367 gl.DepthMask(depth->depth_write_enabled ? GL_TRUE : GL_FALSE);
369 gl.Disable(GL_DEPTH_TEST);
375 if (command.viewport.has_value()) {
376 gl.Viewport(viewport.rect.GetX(),
377 target_size.
height - viewport.rect.GetY() -
378 viewport.rect.GetHeight(),
379 viewport.rect.GetWidth(),
380 viewport.rect.GetHeight()
383 if (gl.DepthRangef.IsAvailable()) {
384 gl.DepthRangef(viewport.depth_range.z_near,
385 viewport.depth_range.z_far);
387 gl.DepthRange(viewport.depth_range.z_near,
388 viewport.depth_range.z_far);
396 if (command.scissor.has_value()) {
397 const auto& scissor = command.scissor.value();
398 gl.Enable(GL_SCISSOR_TEST);
401 target_size.
height - scissor.GetY() - scissor.GetHeight(),
410 CullMode pipeline_cull_mode = pipeline.GetDescriptor().GetCullMode();
411 if (current_cull_mode != pipeline_cull_mode) {
412 switch (pipeline_cull_mode) {
413 case CullMode::kNone:
414 gl.Disable(GL_CULL_FACE);
416 case CullMode::kFrontFace:
417 gl.Enable(GL_CULL_FACE);
418 gl.CullFace(GL_FRONT);
420 case CullMode::kBackFace:
421 gl.Enable(GL_CULL_FACE);
422 gl.CullFace(GL_BACK);
425 current_cull_mode = pipeline_cull_mode;
432 pipeline.GetDescriptor().GetWindingOrder();
433 if (current_winding_order != pipeline_winding_order) {
434 switch (pipeline.GetDescriptor().GetWindingOrder()) {
435 case WindingOrder::kClockwise:
438 case WindingOrder::kCounterClockwise:
439 gl.FrontFace(GL_CCW);
442 current_winding_order = pipeline_winding_order;
454 for (
size_t i = 0; i < command.vertex_buffers.length; i++) {
456 vertex_buffers[i + command.vertex_buffers.offset],
465 if (!pipeline.BindProgram()) {
476 command.bound_textures,
477 command.bound_buffers
491 pipeline.GetDescriptor().GetPolygonMode() == PolygonMode::kLine
493 :
ToMode(pipeline.GetDescriptor().GetPrimitiveType());
498 if (command.index_type == IndexType::kNone) {
499 gl.DrawArrays(mode, command.base_vertex, command.element_count);
502 auto index_buffer_view = command.index_buffer;
503 const DeviceBuffer* index_buffer = index_buffer_view.GetBuffer();
504 const auto& index_buffer_gles = DeviceBufferGLES::Cast(*index_buffer);
505 if (!index_buffer_gles.BindAndUploadDataIfNecessary(
506 DeviceBufferGLES::BindingType::kElementArrayBuffer)) {
509 gl.DrawElements(mode,
510 command.element_count,
512 reinterpret_cast<const GLvoid*
>(
static_cast<GLsizei
>(
513 index_buffer_view.GetRange().offset))
526 !gl.GetCapabilities()->SupportsImplicitResolvingMSAA() &&
532 gl.GenFramebuffers(1u, &resolve_fbo);
533 gl.BindFramebuffer(GL_FRAMEBUFFER, resolve_fbo);
536 .SetAsFramebufferAttachment(
537 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kColor0)) {
541 auto status = gl.CheckFramebufferStatus(GL_FRAMEBUFFER);
542 if (gl.CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
549 gl.BindFramebuffer(GL_READ_FRAMEBUFFER, fbo.value());
550 gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo);
552 RenderPassGLES::ResetGLState(gl);
555 gl.BlitFramebuffer(0,
566 gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, GL_NONE);
567 gl.BindFramebuffer(GL_READ_FRAMEBUFFER, GL_NONE);
568 gl.DeleteFramebuffers(1u, &resolve_fbo);
570 gl.BindFramebuffer(GL_FRAMEBUFFER, fbo.value());
573 if (gl.DiscardFramebufferEXT.IsAvailable()) {
574 std::array<GLenum, 3> attachments;
575 size_t attachment_count = 0;
580 bool angle_safe = gl.GetCapabilities()->IsANGLE() ? !is_default_fbo :
true;
583 attachments[attachment_count++] =
584 (is_default_fbo ? GL_COLOR_EXT : GL_COLOR_ATTACHMENT0);
587 attachments[attachment_count++] =
588 (is_default_fbo ? GL_DEPTH_EXT : GL_DEPTH_ATTACHMENT);
592 attachments[attachment_count++] =
593 (is_default_fbo ? GL_STENCIL_EXT : GL_STENCIL_ATTACHMENT);
595 gl.DiscardFramebufferEXT(GL_FRAMEBUFFER,
601 #ifdef IMPELLER_DEBUG
602 if (is_default_fbo) {
603 tracer->MarkFrameEnd(gl);
611 bool RenderPassGLES::OnEncodeCommands(
const Context& context)
const {
615 const auto& render_target = GetRenderTarget();
616 if (!render_target.HasColorAttachment(0u)) {
619 const ColorAttachment& color0 = render_target.GetColorAttachment(0);
620 const std::optional<DepthAttachment>& depth0 =
621 render_target.GetDepthAttachment();
622 const std::optional<StencilAttachment>& stencil0 =
623 render_target.GetStencilAttachment();
625 auto pass_data = std::make_shared<RenderPassData>();
626 pass_data->label = label_;
627 pass_data->viewport.rect = Rect::MakeSize(GetRenderTargetSize());
632 pass_data->color_attachment = color0.texture;
633 pass_data->resolve_attachment = color0.resolve_texture;
634 pass_data->clear_color = color0.clear_color;
636 pass_data->discard_color_attachment =
644 if (color0.resolve_texture) {
645 pass_data->discard_color_attachment =
646 pass_data->discard_color_attachment &&
647 !context.GetCapabilities()->SupportsImplicitResolvingMSAA();
653 if (depth0.has_value()) {
654 pass_data->depth_attachment = depth0->texture;
655 pass_data->clear_depth = depth0->clear_depth;
657 pass_data->discard_depth_attachment =
664 if (stencil0.has_value()) {
665 pass_data->stencil_attachment = stencil0->texture;
666 pass_data->clear_stencil = stencil0->clear_stencil;
667 pass_data->clear_stencil_attachment =
669 pass_data->discard_stencil_attachment =
673 return reactor_->AddOperation(
674 [pass_data = std::move(pass_data), render_pass = shared_from_this(),
676 ContextGLES::Cast(context).GetGPUTracer()](
const auto& reactor) {
680 render_pass->commands_,
681 render_pass->vertex_buffers_,
682 render_pass->bound_textures_,
683 render_pass->bound_buffers_,
687 <<
"Must be able to encode GL commands without error.";
Sets up stage bindings for single draw call in the OpenGLES backend.
bool BindVertexAttributes(const ProcTableGLES &gl, size_t binding, size_t vertex_offset)
bool UnbindVertexAttributes(const ProcTableGLES &gl)
bool BindUniformData(const ProcTableGLES &gl, const std::vector< TextureAndSampler > &bound_textures, const std::vector< BufferResource > &bound_buffers, Range texture_range, Range buffer_range)
Represents a handle to an underlying OpenGL object. Unlike OpenGL object handles, these handles can b...
constexpr bool IsDead() const
Determines if the handle is dead.
std::optional< StencilAttachmentDescriptor > GetBackStencilAttachmentDescriptor() const
std::optional< StencilAttachmentDescriptor > GetFrontStencilAttachmentDescriptor() const
bool HasStencilAttachmentDescriptors() const
void PushDebugGroup(const std::string &string) const
The reactor attempts to make thread-safe usage of OpenGL ES easier to reason about.
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...
HandleGLES CreateUntrackedHandle(HandleType type) const
Create a handle that is not managed by ReactorGLES.
const ProcTableGLES & GetProcTable() const
Get the OpenGL proc. table the reactor uses to manage handles.
const HandleGLES & GetCachedFBO() const
Retrieve the cached FBO object, or a dead handle if there is no object.
void SetCachedFBO(HandleGLES fbo)
bool SetAsFramebufferAttachment(GLenum target, AttachmentType attachment_type) const
std::optional< GLuint > GetFBO() const
constexpr bool CanClearAttachment(LoadAction action)
constexpr GLenum ToIndexType(IndexType type)
constexpr GLenum ToCompareFunction(CompareFunction func)
std::string DebugToFramebufferError(int status)
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)
constexpr GLenum ToStencilOp(StencilOperation op)
constexpr GLenum ToMode(PrimitiveType primitive_type)
void ConfigureBlending(const ProcTableGLES &gl, const ColorAttachmentDescriptor *color)
void ConfigureStencil(const ProcTableGLES &gl, const PipelineDescriptor &pipeline, uint32_t stencil_reference)
static bool BindVertexBuffer(const ProcTableGLES &gl, BufferBindingsGLES *vertex_desc_gles, const BufferView &vertex_buffer_view, size_t buffer_index)
constexpr GLenum ToBlendFactor(BlendFactor factor)
constexpr GLenum ToBlendOperation(BlendOperation op)
constexpr bool CanDiscardAttachmentWhenDone(StoreAction action)
const DeviceBuffer * GetBuffer() const
Describe the color attachment that will be used with this pipeline.
BlendOperation color_blend_op
BlendFactor dst_color_blend_factor
ColorWriteMask write_mask
BlendFactor src_alpha_blend_factor
BlendOperation alpha_blend_op
BlendFactor src_color_blend_factor
BlendFactor dst_alpha_blend_factor
Encapsulates data that will be needed in the reactor for the encoding of commands for this render pas...
bool clear_color_attachment
std::shared_ptr< Texture > depth_attachment
bool discard_color_attachment
bool clear_stencil_attachment
std::shared_ptr< Texture > color_attachment
bool discard_depth_attachment
std::shared_ptr< Texture > stencil_attachment
bool discard_stencil_attachment
std::shared_ptr< Texture > resolve_attachment
bool clear_depth_attachment
StencilOperation stencil_failure
CompareFunction stencil_compare
StencilOperation depth_failure
StencilOperation depth_stencil_pass