10 #include "flutter/fml/trace_event.h"
11 #include "fml/closure.h"
12 #include "fml/logging.h"
23 RenderPassGLES::RenderPassGLES(std::weak_ptr<const Context> context,
24 const RenderTarget& target,
26 : RenderPass(
std::move(context), target),
27 reactor_(
std::move(reactor)),
28 is_valid_(reactor_ && reactor_->IsValid()) {}
34 bool RenderPassGLES::IsValid()
const {
39 void RenderPassGLES::OnSetLabel(std::string label) {
40 label_ = std::move(label);
53 gl.BlendEquationSeparate(
62 const auto is_set = [](std::underlying_type_t<ColorWriteMask> mask,
64 using RawType = decltype(mask);
65 return (
static_cast<RawType
>(mask) &
static_cast<RawType
>(check))
81 uint32_t stencil_reference) {
88 gl.StencilFuncSeparate(face,
93 gl.StencilMaskSeparate(face, stencil.
write_mask);
98 uint32_t stencil_reference) {
100 gl.Disable(GL_STENCIL_TEST);
104 gl.Enable(GL_STENCIL_TEST);
108 if (front.has_value() && back.has_value() && front == back) {
112 if (front.has_value()) {
115 if (back.has_value()) {
148 const std::shared_ptr<Allocator>& transients_allocator,
150 const std::vector<Command>& commands,
151 const std::shared_ptr<GPUTracerGLES>& tracer) {
152 TRACE_EVENT0(
"impeller",
"RenderPassGLES::EncodeCommandsInReactor");
154 if (commands.empty()) {
159 #ifdef IMPELLER_DEBUG
160 tracer->MarkFrameStart(gl);
161 #endif // IMPELLER_DEBUG
163 fml::ScopedCleanupClosure pop_pass_debug_marker(
164 [&gl]() { gl.PopDebugGroup(); });
165 if (!pass_data.
label.empty()) {
168 pop_pass_debug_marker.Release();
171 GLuint fbo = GL_NONE;
172 fml::ScopedCleanupClosure delete_fbo([&gl, &fbo]() {
173 if (fbo != GL_NONE) {
174 gl.BindFramebuffer(GL_FRAMEBUFFER, GL_NONE);
175 gl.DeleteFramebuffers(1u, &fbo);
179 const auto is_default_fbo =
182 if (!is_default_fbo) {
184 gl.GenFramebuffers(1u, &fbo);
185 gl.BindFramebuffer(GL_FRAMEBUFFER, fbo);
188 if (!color->SetAsFramebufferAttachment(
195 if (!depth->SetAsFramebufferAttachment(
201 if (!stencil->SetAsFramebufferAttachment(
207 auto status = gl.CheckFramebufferStatus(GL_FRAMEBUFFER);
208 if (status != GL_FRAMEBUFFER_COMPLETE) {
232 GLenum clear_bits = 0u;
234 clear_bits |= GL_COLOR_BUFFER_BIT;
237 clear_bits |= GL_DEPTH_BUFFER_BIT;
240 clear_bits |= GL_STENCIL_BUFFER_BIT;
243 gl.Disable(GL_SCISSOR_TEST);
244 gl.Disable(GL_DEPTH_TEST);
245 gl.Disable(GL_STENCIL_TEST);
246 gl.Disable(GL_CULL_FACE);
247 gl.Disable(GL_BLEND);
248 gl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
250 gl.Clear(clear_bits);
252 for (
const auto& command : commands) {
253 if (command.instance_count != 1u) {
254 VALIDATION_LOG <<
"GLES backend does not support instanced rendering.";
258 if (!command.pipeline) {
263 #ifdef IMPELLER_DEBUG
264 fml::ScopedCleanupClosure pop_cmd_debug_marker(
265 [&gl]() { gl.PopDebugGroup(); });
266 if (!command.label.empty()) {
267 gl.PushDebugGroup(command.label);
269 pop_cmd_debug_marker.Release();
271 #endif // IMPELLER_DEBUG
275 const auto* color_attachment =
276 pipeline.GetDescriptor().GetLegacyCompatibleColorAttachment();
277 if (!color_attachment) {
279 <<
"Color attachment is too complicated for a legacy renderer.";
297 pipeline.GetDescriptor().GetDepthStencilAttachmentDescriptor();
299 gl.Enable(GL_DEPTH_TEST);
301 gl.DepthMask(depth->depth_write_enabled ? GL_TRUE : GL_FALSE);
303 gl.Disable(GL_DEPTH_TEST);
314 const auto& viewport = command.viewport.value_or(pass_data.
viewport);
315 gl.Viewport(viewport.rect.GetX(),
316 target_size.height - viewport.rect.GetY() -
317 viewport.rect.GetHeight(),
318 viewport.rect.GetWidth(),
319 viewport.rect.GetHeight()
326 gl.DepthRangef(viewport.depth_range.z_near, viewport.depth_range.z_far);
333 if (command.scissor.has_value()) {
334 const auto& scissor = command.scissor.value();
335 gl.Enable(GL_SCISSOR_TEST);
338 target_size.height - scissor.GetY() - scissor.GetHeight(),
343 gl.Disable(GL_SCISSOR_TEST);
349 switch (pipeline.GetDescriptor().GetCullMode()) {
351 gl.Disable(GL_CULL_FACE);
354 gl.Enable(GL_CULL_FACE);
355 gl.CullFace(GL_FRONT);
358 gl.Enable(GL_CULL_FACE);
359 gl.CullFace(GL_BACK);
365 switch (pipeline.GetDescriptor().GetWindingOrder()) {
370 gl.FrontFace(GL_CCW);
378 auto vertex_desc_gles = pipeline.GetBufferBindings();
383 auto& vertex_buffer_view = command.vertex_buffer.vertex_buffer;
385 if (!vertex_buffer_view) {
390 vertex_buffer_view.buffer->GetDeviceBuffer(*transients_allocator);
392 if (!vertex_buffer) {
397 if (!vertex_buffer_gles.BindAndUploadDataIfNecessary(
405 if (!pipeline.BindProgram()) {
412 if (!vertex_desc_gles->BindVertexAttributes(
413 gl, vertex_buffer_view.range.offset)) {
420 if (!vertex_desc_gles->BindUniformData(gl,
421 *transients_allocator,
422 command.vertex_bindings,
423 command.fragment_bindings
438 :
ToMode(pipeline.GetDescriptor().GetPrimitiveType());
444 gl.DrawArrays(mode, command.base_vertex,
445 command.vertex_buffer.vertex_count);
448 auto index_buffer_view = command.vertex_buffer.index_buffer;
450 index_buffer_view.buffer->GetDeviceBuffer(*transients_allocator);
452 if (!index_buffer_gles.BindAndUploadDataIfNecessary(
456 gl.DrawElements(mode,
457 command.vertex_buffer.vertex_count,
459 reinterpret_cast<const GLvoid*
>(
static_cast<GLsizei
>(
460 index_buffer_view.range.offset))
467 if (!vertex_desc_gles->UnbindVertexAttributes(gl)) {
474 if (!pipeline.UnbindProgram()) {
479 if (gl.DiscardFramebufferEXT.IsAvailable()) {
480 std::vector<GLenum> attachments;
483 attachments.push_back(is_default_fbo ? GL_COLOR_EXT
484 : GL_COLOR_ATTACHMENT0);
487 attachments.push_back(is_default_fbo ? GL_DEPTH_EXT
488 : GL_DEPTH_ATTACHMENT);
499 attachments.push_back(is_default_fbo ? GL_STENCIL_EXT
500 : GL_STENCIL_ATTACHMENT);
502 gl.DiscardFramebufferEXT(GL_FRAMEBUFFER,
508 #ifdef IMPELLER_DEBUG
509 if (is_default_fbo) {
510 tracer->MarkFrameEnd(gl);
512 #endif // IMPELLER_DEBUG
518 bool RenderPassGLES::OnEncodeCommands(
const Context& context)
const {
526 if (!render_target.HasColorAttachment(0u)) {
529 const auto& color0 = render_target.GetColorAttachments().at(0u);
530 const auto& depth0 = render_target.GetDepthAttachment();
531 const auto& stencil0 = render_target.GetStencilAttachment();
533 auto pass_data = std::make_shared<RenderPassData>();
534 pass_data->
label = label_;
549 if (color0.resolve_texture) {
550 FML_DCHECK(context.
GetCapabilities()->SupportsImplicitResolvingMSAA());
557 if (depth0.has_value()) {
568 if (stencil0.has_value()) {
577 std::shared_ptr<const RenderPassGLES> shared_this = shared_from_this();
579 return reactor_->AddOperation([pass_data,
581 render_pass = std::move(shared_this),
582 tracer](
const auto& reactor) {
583 auto result = EncodeCommandsInReactor(*pass_data, allocator, reactor,
584 render_pass->commands_, tracer);
585 FML_CHECK(result) <<
"Must be able to encode GL commands without error.";