From d77a2700f17c6597ff1c2f418d06b08291e9ac3e Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Wed, 26 Apr 2023 02:01:46 -0700 Subject: [PATCH 1/4] [Impeller] Store the root stencil on iOS --- impeller/entity/entity_pass.cc | 43 +++++++---- .../renderer/backend/metal/surface_mtl.mm | 2 +- impeller/renderer/render_target.cc | 75 +++++++++---------- impeller/renderer/render_target.h | 7 ++ 4 files changed, 72 insertions(+), 55 deletions(-) diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index c9a00df681bdb..c4aca7d4f9d23 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -148,6 +148,15 @@ EntityPass* EntityPass::AddSubpass(std::unique_ptr pass) { return subpass_pointer; } +static RenderTarget::AttachmentConfig GetDefaultStencilConfig(bool readable) { + return RenderTarget::AttachmentConfig{ + .storage_mode = readable ? StorageMode::kDevicePrivate + : StorageMode::kDeviceTransient, + .load_action = LoadAction::kDontCare, + .store_action = StoreAction::kDontCare, + }; +} + static EntityPassTarget CreateRenderTarget(ContentContext& renderer, ISize size, bool readable, @@ -170,13 +179,8 @@ static EntityPassTarget CreateRenderTarget(ContentContext& renderer, .resolve_storage_mode = StorageMode::kDevicePrivate, .load_action = LoadAction::kDontCare, .store_action = StoreAction::kMultisampleResolve, - .clear_color = clear_color}, // color_attachment_config - RenderTarget::AttachmentConfig{ - .storage_mode = readable ? StorageMode::kDevicePrivate - : StorageMode::kDeviceTransient, - .load_action = LoadAction::kDontCare, - .store_action = StoreAction::kDontCare, - } // stencil_attachment_config + .clear_color = clear_color}, // color_attachment_config + GetDefaultStencilConfig(readable) // stencil_attachment_config ); } else { target = RenderTarget::CreateOffscreen( @@ -187,13 +191,8 @@ static EntityPassTarget CreateRenderTarget(ContentContext& renderer, .storage_mode = StorageMode::kDevicePrivate, .load_action = LoadAction::kDontCare, .store_action = StoreAction::kDontCare, - }, // color_attachment_config - RenderTarget::AttachmentConfig{ - .storage_mode = readable ? StorageMode::kDevicePrivate - : StorageMode::kDeviceTransient, - .load_action = LoadAction::kDontCare, - .store_action = StoreAction::kDontCare, - } // stencil_attachment_config + }, // color_attachment_config + GetDefaultStencilConfig(readable) // stencil_attachment_config ); } @@ -214,6 +213,10 @@ bool EntityPass::Render(ContentContext& renderer, VALIDATION_LOG << "The root RenderTarget must have a color attachment."; return false; } + if (!render_target.GetStencilAttachment().has_value()) { + VALIDATION_LOG << "The root RenderTarget must have a stencil attachment."; + return false; + } StencilCoverageStack stencil_coverage_stack = {StencilCoverageLayer{ .coverage = Rect::MakeSize(render_target.GetRenderTargetSize()), @@ -293,6 +296,18 @@ bool EntityPass::Render(ContentContext& renderer, return true; } + { + auto stencil_texture = render_target.GetStencilAttachment()->texture; + if (stencil_texture && + stencil_texture->GetTextureDescriptor().storage_mode == + StorageMode::kDeviceTransient) { + VALIDATION_LOG + << "The root RenderTarget stencil must not be transient on " + "this backend."; + return false; + } + } + // Set up the clear color of the root pass. auto color0 = render_target.GetColorAttachments().find(0)->second; color0.clear_color = clear_color_.Premultiply(); diff --git a/impeller/renderer/backend/metal/surface_mtl.mm b/impeller/renderer/backend/metal/surface_mtl.mm index dccdac147f4e9..ef73b61681d88 100644 --- a/impeller/renderer/backend/metal/surface_mtl.mm +++ b/impeller/renderer/backend/metal/surface_mtl.mm @@ -83,7 +83,7 @@ color0.resolve_texture = resolve_tex; TextureDescriptor stencil_tex_desc; - stencil_tex_desc.storage_mode = StorageMode::kDeviceTransient; + stencil_tex_desc.storage_mode = StorageMode::kDevicePrivate; stencil_tex_desc.type = TextureType::kTexture2DMultisample; stencil_tex_desc.sample_count = SampleCount::kCount4; stencil_tex_desc.format = diff --git a/impeller/renderer/render_target.cc b/impeller/renderer/render_target.cc index fe29d31df6e1b..67c18d95386e6 100644 --- a/impeller/renderer/render_target.cc +++ b/impeller/renderer/render_target.cc @@ -239,25 +239,8 @@ RenderTarget RenderTarget::CreateOffscreen( target.SetColorAttachment(color0, 0u); if (stencil_attachment_config.has_value()) { - TextureDescriptor stencil_tex0; - stencil_tex0.storage_mode = stencil_attachment_config->storage_mode; - stencil_tex0.format = context.GetCapabilities()->GetDefaultStencilFormat(); - stencil_tex0.size = size; - stencil_tex0.usage = - static_cast(TextureUsage::kRenderTarget); - - StencilAttachment stencil0; - stencil0.load_action = stencil_attachment_config->load_action; - stencil0.store_action = stencil_attachment_config->store_action; - stencil0.clear_stencil = 0u; - stencil0.texture = - context.GetResourceAllocator()->CreateTexture(stencil_tex0); - - if (!stencil0.texture) { - return {}; - } - stencil0.texture->SetLabel(SPrintF("%s Stencil Texture", label.c_str())); - target.SetStencilAttachment(std::move(stencil0)); + target.SetupStencilAttachment(context, size, false, label, + stencil_attachment_config.value()); } else { target.SetStencilAttachment(std::nullopt); } @@ -331,27 +314,8 @@ RenderTarget RenderTarget::CreateOffscreenMSAA( // Create MSAA stencil texture. if (stencil_attachment_config.has_value()) { - TextureDescriptor stencil_tex0; - stencil_tex0.storage_mode = stencil_attachment_config->storage_mode; - stencil_tex0.type = TextureType::kTexture2DMultisample; - stencil_tex0.sample_count = SampleCount::kCount4; - stencil_tex0.format = context.GetCapabilities()->GetDefaultStencilFormat(); - stencil_tex0.size = size; - stencil_tex0.usage = - static_cast(TextureUsage::kRenderTarget); - - StencilAttachment stencil0; - stencil0.load_action = stencil_attachment_config->load_action; - stencil0.store_action = stencil_attachment_config->store_action; - stencil0.clear_stencil = 0u; - stencil0.texture = - context.GetResourceAllocator()->CreateTexture(stencil_tex0); - - if (!stencil0.texture) { - return {}; - } - stencil0.texture->SetLabel(SPrintF("%s Stencil Texture", label.c_str())); - target.SetStencilAttachment(std::move(stencil0)); + target.SetupStencilAttachment(context, size, true, label, + stencil_attachment_config.value()); } else { target.SetStencilAttachment(std::nullopt); } @@ -359,6 +323,37 @@ RenderTarget RenderTarget::CreateOffscreenMSAA( return target; } +void RenderTarget::SetupStencilAttachment( + const Context& context, + ISize size, + bool msaa, + const std::string& label, + AttachmentConfig stencil_attachment_config) { + TextureDescriptor stencil_tex0; + stencil_tex0.storage_mode = stencil_attachment_config.storage_mode; + if (msaa) { + stencil_tex0.type = TextureType::kTexture2DMultisample; + stencil_tex0.sample_count = SampleCount::kCount4; + } + stencil_tex0.format = context.GetCapabilities()->GetDefaultStencilFormat(); + stencil_tex0.size = size; + stencil_tex0.usage = + static_cast(TextureUsage::kRenderTarget); + + StencilAttachment stencil0; + stencil0.load_action = stencil_attachment_config.load_action; + stencil0.store_action = stencil_attachment_config.store_action; + stencil0.clear_stencil = 0u; + stencil0.texture = + context.GetResourceAllocator()->CreateTexture(stencil_tex0); + + if (!stencil0.texture) { + return; // Error messages are handled by `Allocator::CreateTexture`. + } + stencil0.texture->SetLabel(SPrintF("%s Stencil Texture", label.c_str())); + SetStencilAttachment(std::move(stencil0)); +} + size_t RenderTarget::GetTotalAttachmentCount() const { size_t count = 0u; for (const auto& [_, color] : colors_) { diff --git a/impeller/renderer/render_target.h b/impeller/renderer/render_target.h index 9e1da3272104a..bc54976a030a8 100644 --- a/impeller/renderer/render_target.h +++ b/impeller/renderer/render_target.h @@ -76,6 +76,13 @@ class RenderTarget final { bool IsValid() const; + void SetupStencilAttachment(const Context& context, + ISize size, + bool msaa, + const std::string& label = "Offscreen", + AttachmentConfig stencil_attachment_config = + kDefaultStencilAttachmentConfig); + SampleCount GetSampleCount() const; bool HasColorAttachment(size_t index) const; From 726ecda1c19fb43b8d7c414903d8cbd4d0a50fdd Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Wed, 26 Apr 2023 02:33:05 -0700 Subject: [PATCH 2/4] Vulkan --- impeller/renderer/backend/vulkan/surface_vk.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impeller/renderer/backend/vulkan/surface_vk.cc b/impeller/renderer/backend/vulkan/surface_vk.cc index 02992a35ebc0f..72aa2508b4083 100644 --- a/impeller/renderer/backend/vulkan/surface_vk.cc +++ b/impeller/renderer/backend/vulkan/surface_vk.cc @@ -61,7 +61,7 @@ std::unique_ptr SurfaceVK::WrapSwapchainImage( color0.resolve_texture = resolve_tex; TextureDescriptor stencil0_tex; - stencil0_tex.storage_mode = StorageMode::kDeviceTransient; + stencil0_tex.storage_mode = StorageMode::kDevicePrivate; stencil0_tex.type = TextureType::kTexture2D; stencil0_tex.sample_count = SampleCount::kCount4; stencil0_tex.format = context->GetCapabilities()->GetDefaultStencilFormat(); From b8f350aa94254dc7cec095dfbfc726bedc9ab0ff Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Wed, 26 Apr 2023 03:30:14 -0700 Subject: [PATCH 3/4] Gracefully handle transients in EntityPass --- impeller/entity/entity_pass.cc | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index c4aca7d4f9d23..0b67412fed0a1 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -213,21 +213,29 @@ bool EntityPass::Render(ContentContext& renderer, VALIDATION_LOG << "The root RenderTarget must have a color attachment."; return false; } + if (!render_target.GetStencilAttachment().has_value()) { VALIDATION_LOG << "The root RenderTarget must have a stencil attachment."; return false; } + auto stencil_texture = render_target.GetStencilAttachment()->texture; + if (!stencil_texture) { + VALIDATION_LOG << "The root RenderTarget must have a stencil texture."; + return false; + } + StencilCoverageStack stencil_coverage_stack = {StencilCoverageLayer{ .coverage = Rect::MakeSize(render_target.GetRenderTargetSize()), .stencil_depth = 0}}; - // bool supports_root_pass_reads = renderer.GetDeviceCapabilities().SupportsReadFromOnscreenTexture() && // If the backend doesn't have `SupportsReadFromResolve`, we need to flip // between two textures when restoring a previous MSAA pass. - renderer.GetDeviceCapabilities().SupportsReadFromResolve(); + renderer.GetDeviceCapabilities().SupportsReadFromResolve() && + stencil_texture->GetTextureDescriptor().storage_mode != + StorageMode::kDeviceTransient; if (!supports_root_pass_reads && GetTotalPassReads(renderer) > 0) { auto offscreen_target = CreateRenderTarget(renderer, render_target.GetRenderTargetSize(), true, @@ -296,18 +304,6 @@ bool EntityPass::Render(ContentContext& renderer, return true; } - { - auto stencil_texture = render_target.GetStencilAttachment()->texture; - if (stencil_texture && - stencil_texture->GetTextureDescriptor().storage_mode == - StorageMode::kDeviceTransient) { - VALIDATION_LOG - << "The root RenderTarget stencil must not be transient on " - "this backend."; - return false; - } - } - // Set up the clear color of the root pass. auto color0 = render_target.GetColorAttachments().find(0)->second; color0.clear_color = clear_color_.Premultiply(); From 1300ebd342b6be4cbb07587c7116bd46784731c8 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Wed, 26 Apr 2023 03:30:30 -0700 Subject: [PATCH 4/4] Fix VK stencil --- impeller/renderer/backend/vulkan/surface_vk.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impeller/renderer/backend/vulkan/surface_vk.cc b/impeller/renderer/backend/vulkan/surface_vk.cc index 72aa2508b4083..721b2fe75790a 100644 --- a/impeller/renderer/backend/vulkan/surface_vk.cc +++ b/impeller/renderer/backend/vulkan/surface_vk.cc @@ -62,7 +62,7 @@ std::unique_ptr SurfaceVK::WrapSwapchainImage( TextureDescriptor stencil0_tex; stencil0_tex.storage_mode = StorageMode::kDevicePrivate; - stencil0_tex.type = TextureType::kTexture2D; + stencil0_tex.type = TextureType::kTexture2DMultisample; stencil0_tex.sample_count = SampleCount::kCount4; stencil0_tex.format = context->GetCapabilities()->GetDefaultStencilFormat(); stencil0_tex.size = msaa_tex_desc.size;