diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 03cf5495b6b86..e339790379ec0 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -3557,6 +3557,8 @@ TEST_P(AiksTest, GaussianBlurWithoutDecalSupport) { .WillRepeatedly(::testing::Return(false)); FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultColorFormat); FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultStencilFormat); + FLT_FORWARD(mock_capabilities, old_capabilities, + GetDefaultDepthStencilFormat); FLT_FORWARD(mock_capabilities, old_capabilities, SupportsOffscreenMSAA); FLT_FORWARD(mock_capabilities, old_capabilities, SupportsImplicitResolvingMSAA); diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index 9323692ffac1b..8d3fc0aaa3dbc 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -423,7 +423,8 @@ bool EntityPass::Render(ContentContext& renderer, // If a root stencil was provided by the caller, then verify that it has a // configuration which can be used to render this pass. auto stencil_attachment = root_render_target.GetStencilAttachment(); - if (stencil_attachment.has_value()) { + auto depth_attachment = root_render_target.GetDepthAttachment(); + if (stencil_attachment.has_value() && depth_attachment.has_value()) { auto stencil_texture = stencil_attachment->texture; if (!stencil_texture) { VALIDATION_LOG << "The root RenderTarget must have a stencil texture."; @@ -442,7 +443,7 @@ bool EntityPass::Render(ContentContext& renderer, // Setup a new root stencil with an optimal configuration if one wasn't // provided by the caller. else { - root_render_target.SetupStencilAttachment( + root_render_target.SetupDepthStencilAttachments( *renderer.GetContext(), *renderer.GetRenderTargetCache(), color0.texture->GetSize(), renderer.GetContext()->GetCapabilities()->SupportsOffscreenMSAA(), diff --git a/impeller/renderer/backend/gles/blit_command_gles.cc b/impeller/renderer/backend/gles/blit_command_gles.cc index 7be7fea9d6f88..f30ce5446f5d8 100644 --- a/impeller/renderer/backend/gles/blit_command_gles.cc +++ b/impeller/renderer/backend/gles/blit_command_gles.cc @@ -41,7 +41,7 @@ static std::optional ConfigureFBO( gl.BindFramebuffer(fbo_type, fbo); if (!TextureGLES::Cast(*texture).SetAsFramebufferAttachment( - fbo_type, TextureGLES::AttachmentPoint::kColor0)) { + fbo_type, TextureGLES::AttachmentType::kColor0)) { VALIDATION_LOG << "Could not attach texture to framebuffer."; DeleteFBO(gl, fbo, fbo_type); return std::nullopt; diff --git a/impeller/renderer/backend/gles/render_pass_gles.cc b/impeller/renderer/backend/gles/render_pass_gles.cc index 20b6fd4bea71b..62f23bbdf86ef 100644 --- a/impeller/renderer/backend/gles/render_pass_gles.cc +++ b/impeller/renderer/backend/gles/render_pass_gles.cc @@ -186,20 +186,20 @@ struct RenderPassData { if (auto color = TextureGLES::Cast(pass_data.color_attachment.get())) { if (!color->SetAsFramebufferAttachment( - GL_FRAMEBUFFER, TextureGLES::AttachmentPoint::kColor0)) { + GL_FRAMEBUFFER, TextureGLES::AttachmentType::kColor0)) { return false; } } if (auto depth = TextureGLES::Cast(pass_data.depth_attachment.get())) { if (!depth->SetAsFramebufferAttachment( - GL_FRAMEBUFFER, TextureGLES::AttachmentPoint::kDepth)) { + GL_FRAMEBUFFER, TextureGLES::AttachmentType::kDepth)) { return false; } } if (auto stencil = TextureGLES::Cast(pass_data.stencil_attachment.get())) { if (!stencil->SetAsFramebufferAttachment( - GL_FRAMEBUFFER, TextureGLES::AttachmentPoint::kStencil)) { + GL_FRAMEBUFFER, TextureGLES::AttachmentType::kStencil)) { return false; } } diff --git a/impeller/renderer/backend/gles/texture_gles.cc b/impeller/renderer/backend/gles/texture_gles.cc index 8d6bdc2609feb..9a4dfc7ba169b 100644 --- a/impeller/renderer/backend/gles/texture_gles.cc +++ b/impeller/renderer/backend/gles/texture_gles.cc @@ -7,6 +7,7 @@ #include #include +#include "flutter/fml/logging.h" #include "flutter/fml/mapping.h" #include "flutter/fml/trace_event.h" #include "impeller/base/allocation.h" @@ -17,13 +18,37 @@ namespace impeller { +static bool IsDepthStencilFormat(PixelFormat format) { + switch (format) { + case PixelFormat::kS8UInt: + case PixelFormat::kD24UnormS8Uint: + case PixelFormat::kD32FloatS8UInt: + return true; + case PixelFormat::kUnknown: + case PixelFormat::kA8UNormInt: + case PixelFormat::kR8UNormInt: + case PixelFormat::kR8G8UNormInt: + case PixelFormat::kR8G8B8A8UNormInt: + case PixelFormat::kR8G8B8A8UNormIntSRGB: + case PixelFormat::kB8G8R8A8UNormInt: + case PixelFormat::kB8G8R8A8UNormIntSRGB: + case PixelFormat::kR32G32B32A32Float: + case PixelFormat::kR16G16B16A16Float: + case PixelFormat::kB10G10R10XR: + case PixelFormat::kB10G10R10XRSRGB: + case PixelFormat::kB10G10R10A10XR: + return false; + } + FML_UNREACHABLE(); +} + static TextureGLES::Type GetTextureTypeFromDescriptor( const TextureDescriptor& desc) { const auto usage = static_cast(desc.usage); const auto render_target = static_cast(TextureUsage::kRenderTarget); const auto is_msaa = desc.sample_count == SampleCount::kCount4; - if (usage == render_target && desc.format == PixelFormat::kS8UInt) { + if (usage == render_target && IsDepthStencilFormat(desc.format)) { return is_msaa ? TextureGLES::Type::kRenderBufferMultisampled : TextureGLES::Type::kRenderBuffer; } @@ -457,19 +482,20 @@ TextureGLES::Type TextureGLES::GetType() const { return type_; } -static GLenum ToAttachmentPoint(TextureGLES::AttachmentPoint point) { +static GLenum ToAttachmentType(TextureGLES::AttachmentType point) { switch (point) { - case TextureGLES::AttachmentPoint::kColor0: + case TextureGLES::AttachmentType::kColor0: return GL_COLOR_ATTACHMENT0; - case TextureGLES::AttachmentPoint::kDepth: + case TextureGLES::AttachmentType::kDepth: return GL_DEPTH_ATTACHMENT; - case TextureGLES::AttachmentPoint::kStencil: + case TextureGLES::AttachmentType::kStencil: return GL_STENCIL_ATTACHMENT; } } -bool TextureGLES::SetAsFramebufferAttachment(GLenum target, - AttachmentPoint point) const { +bool TextureGLES::SetAsFramebufferAttachment( + GLenum target, + AttachmentType attachment_type) const { if (!IsValid()) { return false; } @@ -482,29 +508,30 @@ bool TextureGLES::SetAsFramebufferAttachment(GLenum target, switch (type_) { case Type::kTexture: - gl.FramebufferTexture2D(target, // target - ToAttachmentPoint(point), // attachment - GL_TEXTURE_2D, // textarget - handle.value(), // texture - 0 // level + gl.FramebufferTexture2D(target, // target + ToAttachmentType(attachment_type), // attachment + GL_TEXTURE_2D, // textarget + handle.value(), // texture + 0 // level ); break; case Type::kTextureMultisampled: gl.FramebufferTexture2DMultisampleEXT( - target, // target - ToAttachmentPoint(point), // attachment - GL_TEXTURE_2D, // textarget - handle.value(), // texture - 0, // level - 4 // samples + target, // target + ToAttachmentType(attachment_type), // attachment + GL_TEXTURE_2D, // textarget + handle.value(), // texture + 0, // level + 4 // samples ); break; case Type::kRenderBuffer: case Type::kRenderBufferMultisampled: - gl.FramebufferRenderbuffer(target, // target - ToAttachmentPoint(point), // attachment - GL_RENDERBUFFER, // render-buffer target - handle.value() // render-buffer + gl.FramebufferRenderbuffer( + target, // target + ToAttachmentType(attachment_type), // attachment + GL_RENDERBUFFER, // render-buffer target + handle.value() // render-buffer ); break; } diff --git a/impeller/renderer/backend/gles/texture_gles.h b/impeller/renderer/backend/gles/texture_gles.h index 704d0ef3a8503..adfc2e49d4b90 100644 --- a/impeller/renderer/backend/gles/texture_gles.h +++ b/impeller/renderer/backend/gles/texture_gles.h @@ -41,13 +41,14 @@ class TextureGLES final : public Texture, [[nodiscard]] bool GenerateMipmap(); - enum class AttachmentPoint { + enum class AttachmentType { kColor0, kDepth, kStencil, }; - [[nodiscard]] bool SetAsFramebufferAttachment(GLenum target, - AttachmentPoint point) const; + [[nodiscard]] bool SetAsFramebufferAttachment( + GLenum target, + AttachmentType attachment_type) const; Type GetType() const; diff --git a/impeller/renderer/render_target.cc b/impeller/renderer/render_target.cc index d4a1e3c6cf0bb..f9a3b4a055451 100644 --- a/impeller/renderer/render_target.cc +++ b/impeller/renderer/render_target.cc @@ -255,8 +255,8 @@ RenderTarget RenderTarget::CreateOffscreen( target.SetColorAttachment(color0, 0u); if (stencil_attachment_config.has_value()) { - target.SetupStencilAttachment(context, allocator, size, false, label, - stencil_attachment_config.value()); + target.SetupDepthStencilAttachments(context, allocator, size, false, label, + stencil_attachment_config.value()); } else { target.SetStencilAttachment(std::nullopt); } @@ -347,8 +347,8 @@ RenderTarget RenderTarget::CreateOffscreenMSAA( // Create MSAA stencil texture. if (stencil_attachment_config.has_value()) { - target.SetupStencilAttachment(context, allocator, size, true, label, - stencil_attachment_config.value()); + target.SetupDepthStencilAttachments(context, allocator, size, true, label, + stencil_attachment_config.value()); } else { target.SetStencilAttachment(std::nullopt); } @@ -356,34 +356,47 @@ RenderTarget RenderTarget::CreateOffscreenMSAA( return target; } -void RenderTarget::SetupStencilAttachment( +void RenderTarget::SetupDepthStencilAttachments( const Context& context, RenderTargetAllocator& allocator, ISize size, bool msaa, const std::string& label, AttachmentConfig stencil_attachment_config) { - TextureDescriptor stencil_tex0; - stencil_tex0.storage_mode = stencil_attachment_config.storage_mode; + TextureDescriptor depth_stencil_texture_desc; + depth_stencil_texture_desc.storage_mode = + stencil_attachment_config.storage_mode; if (msaa) { - stencil_tex0.type = TextureType::kTexture2DMultisample; - stencil_tex0.sample_count = SampleCount::kCount4; + depth_stencil_texture_desc.type = TextureType::kTexture2DMultisample; + depth_stencil_texture_desc.sample_count = SampleCount::kCount4; } - stencil_tex0.format = context.GetCapabilities()->GetDefaultStencilFormat(); - stencil_tex0.size = size; - stencil_tex0.usage = + depth_stencil_texture_desc.format = + context.GetCapabilities()->GetDefaultDepthStencilFormat(); + depth_stencil_texture_desc.size = size; + depth_stencil_texture_desc.usage = static_cast(TextureUsage::kRenderTarget); + auto depth_stencil_texture = + allocator.CreateTexture(depth_stencil_texture_desc); + if (!depth_stencil_texture) { + return; // Error messages are handled by `Allocator::CreateTexture`. + } + + DepthAttachment depth0; + depth0.load_action = stencil_attachment_config.load_action; + depth0.store_action = stencil_attachment_config.store_action; + depth0.clear_depth = 0u; + depth0.texture = depth_stencil_texture; + StencilAttachment stencil0; stencil0.load_action = stencil_attachment_config.load_action; stencil0.store_action = stencil_attachment_config.store_action; stencil0.clear_stencil = 0u; - stencil0.texture = allocator.CreateTexture(stencil_tex0); + stencil0.texture = depth_stencil_texture; - if (!stencil0.texture) { - return; // Error messages are handled by `Allocator::CreateTexture`. - } - stencil0.texture->SetLabel(SPrintF("%s Stencil Texture", label.c_str())); + stencil0.texture->SetLabel( + SPrintF("%s Depth+Stencil Texture", label.c_str())); + SetDepthAttachment(std::move(depth0)); SetStencilAttachment(std::move(stencil0)); } @@ -403,6 +416,9 @@ size_t RenderTarget::GetTotalAttachmentCount() const { if (stencil_.has_value()) { count++; } + if (depth_.has_value()) { + count++; + } return count; } diff --git a/impeller/renderer/render_target.h b/impeller/renderer/render_target.h index 997ebac1b7eab..fc3fd345cbc60 100644 --- a/impeller/renderer/render_target.h +++ b/impeller/renderer/render_target.h @@ -109,13 +109,13 @@ class RenderTarget final { bool IsValid() const; - void SetupStencilAttachment(const Context& context, - RenderTargetAllocator& allocator, - ISize size, - bool msaa, - const std::string& label = "Offscreen", - AttachmentConfig stencil_attachment_config = - kDefaultStencilAttachmentConfig); + void SetupDepthStencilAttachments(const Context& context, + RenderTargetAllocator& allocator, + ISize size, + bool msaa, + const std::string& label = "Offscreen", + AttachmentConfig stencil_attachment_config = + kDefaultStencilAttachmentConfig); SampleCount GetSampleCount() const; diff --git a/impeller/renderer/renderer_unittests.cc b/impeller/renderer/renderer_unittests.cc index 0881fd6c4bd15..a477ebe4f9796 100644 --- a/impeller/renderer/renderer_unittests.cc +++ b/impeller/renderer/renderer_unittests.cc @@ -1161,9 +1161,9 @@ TEST_P(RendererTest, StencilMask) { stencil_config.storage_mode = StorageMode::kHostVisible; auto render_target_allocator = RenderTargetAllocator(context->GetResourceAllocator()); - render_target.SetupStencilAttachment(*context, render_target_allocator, - render_target.GetRenderTargetSize(), - true, "stencil", stencil_config); + render_target.SetupDepthStencilAttachments( + *context, render_target_allocator, + render_target.GetRenderTargetSize(), true, "stencil", stencil_config); // Fill the stencil buffer with an checkerboard pattern. const auto target_width = render_target.GetRenderTargetSize().width; const auto target_height = render_target.GetRenderTargetSize().height; @@ -1289,6 +1289,20 @@ TEST_P(RendererTest, CanLookupRenderTargetProperties) { render_target.GetRenderTargetSize()); } +TEST_P(RendererTest, + RenderTargetCreateOffscreenMSAASetsDefaultDepthStencilFormat) { + auto context = GetContext(); + auto render_target_cache = std::make_shared( + GetContext()->GetResourceAllocator()); + + RenderTarget render_target = RenderTarget::CreateOffscreenMSAA( + *context, *render_target_cache, {100, 100}, /*mip_count=*/1); + EXPECT_EQ(render_target.GetDepthAttachment() + ->texture->GetTextureDescriptor() + .format, + GetContext()->GetCapabilities()->GetDefaultDepthStencilFormat()); +} + } // namespace testing } // namespace impeller