diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index 984d9b8095f22..5284c7f79fb46 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -121,6 +121,10 @@ void ContentContextOptions::ApplyToPipelineDescriptor( } desc.SetColorAttachmentDescriptor(0u, color0); + if (!has_stencil_attachment) { + desc.ClearStencilAttachments(); + } + if (desc.GetFrontStencilAttachmentDescriptor().has_value()) { StencilAttachmentDescriptor stencil = desc.GetFrontStencilAttachmentDescriptor().value(); diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index e109ae4aad2db..c534afddc1d9d 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -179,17 +179,29 @@ using GeometryColorPipeline = using YUVToRGBFilterPipeline = RenderPipelineT; +/// Pipeline state configuration. +/// +/// Each unique combination of these options requires a different pipeline state +/// object to be built. This struct is used as a key for the per-pipeline +/// variant cache. +/// +/// When adding fields to this key, reliant features should take care to limit +/// the combinatorical explosion of variations. A sufficiently complicated +/// Flutter application may easily require building hundreds of PSOs in total, +/// but they shouldn't require e.g. 10s of thousands. struct ContentContextOptions { SampleCount sample_count = SampleCount::kCount1; BlendMode blend_mode = BlendMode::kSourceOver; CompareFunction stencil_compare = CompareFunction::kEqual; StencilOperation stencil_operation = StencilOperation::kKeep; PrimitiveType primitive_type = PrimitiveType::kTriangle; + bool has_stencil_attachment = true; struct Hash { constexpr std::size_t operator()(const ContentContextOptions& o) const { return fml::HashCombine(o.sample_count, o.blend_mode, o.stencil_compare, - o.stencil_operation, o.primitive_type); + o.stencil_operation, o.primitive_type, + o.has_stencil_attachment); } }; @@ -200,7 +212,8 @@ struct ContentContextOptions { lhs.blend_mode == rhs.blend_mode && lhs.stencil_compare == rhs.stencil_compare && lhs.stencil_operation == rhs.stencil_operation && - lhs.primitive_type == rhs.primitive_type; + lhs.primitive_type == rhs.primitive_type && + lhs.has_stencil_attachment == rhs.has_stencil_attachment; } }; diff --git a/impeller/entity/contents/contents.cc b/impeller/entity/contents/contents.cc index f6f52cd519f63..0105704a1a450 100644 --- a/impeller/entity/contents/contents.cc +++ b/impeller/entity/contents/contents.cc @@ -16,6 +16,8 @@ namespace impeller { ContentContextOptions OptionsFromPass(const RenderPass& pass) { ContentContextOptions opts; opts.sample_count = pass.GetRenderTarget().GetSampleCount(); + opts.has_stencil_attachment = + pass.GetRenderTarget().GetStencilAttachment().has_value(); return opts; } @@ -23,6 +25,8 @@ ContentContextOptions OptionsFromPassAndEntity(const RenderPass& pass, const Entity& entity) { ContentContextOptions opts; opts.sample_count = pass.GetRenderTarget().GetSampleCount(); + opts.has_stencil_attachment = + pass.GetRenderTarget().GetStencilAttachment().has_value(); opts.blend_mode = entity.GetBlendMode(); return opts; } diff --git a/impeller/entity/contents/scene_contents.cc b/impeller/entity/contents/scene_contents.cc index ffcb1afa4c18a..37dbb702c7355 100644 --- a/impeller/entity/contents/scene_contents.cc +++ b/impeller/entity/contents/scene_contents.cc @@ -45,16 +45,20 @@ bool SceneContents::Render(const ContentContext& renderer, } RenderTarget subpass_target = RenderTarget::CreateOffscreenMSAA( - *renderer.GetContext(), // context - ISize(coverage.value().size), // size - "SceneContents", // label - StorageMode::kDeviceTransient, // color_storage_mode - StorageMode::kDevicePrivate, // color_resolve_storage_mode - LoadAction::kClear, // color_load_action - StoreAction::kMultisampleResolve, // color_store_action - StorageMode::kDeviceTransient, // stencil_storage_mode - LoadAction::kDontCare, // stencil_load_action - StoreAction::kDontCare // stencil_store_action + *renderer.GetContext(), // context + ISize(coverage.value().size), // size + "SceneContents", // label + RenderTarget::AttachmentConfigMSAA{ + .storage_mode = StorageMode::kDeviceTransient, + .resolve_storage_mode = StorageMode::kDevicePrivate, + .load_action = LoadAction::kClear, + .store_action = StoreAction::kMultisampleResolve, + }, // color_attachment_config + RenderTarget::AttachmentConfig{ + .storage_mode = StorageMode::kDeviceTransient, + .load_action = LoadAction::kDontCare, + .store_action = StoreAction::kDontCare, + } // stencil_attachment_config ); if (!subpass_target.IsValid()) { return false; diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index df9e860f2c48b..7f94b5e071145 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -155,31 +155,39 @@ static RenderTarget CreateRenderTarget(ContentContext& renderer, if (context->SupportsOffscreenMSAA()) { return RenderTarget::CreateOffscreenMSAA( - *context, // context - size, // size - "EntityPass", // label - StorageMode::kDeviceTransient, // color_storage_mode - StorageMode::kDevicePrivate, // color_resolve_storage_mode - LoadAction::kDontCare, // color_load_action - StoreAction::kMultisampleResolve, // color_store_action - readable ? StorageMode::kDevicePrivate - : StorageMode::kDeviceTransient, // stencil_storage_mode - LoadAction::kDontCare, // stencil_load_action - StoreAction::kDontCare // stencil_store_action + *context, // context + size, // size + "EntityPass", // label + RenderTarget::AttachmentConfigMSAA{ + .storage_mode = StorageMode::kDeviceTransient, + .resolve_storage_mode = StorageMode::kDevicePrivate, + .load_action = LoadAction::kDontCare, + .store_action = StoreAction::kMultisampleResolve, + }, // color_attachment_config + RenderTarget::AttachmentConfig{ + .storage_mode = readable ? StorageMode::kDevicePrivate + : StorageMode::kDeviceTransient, + .load_action = LoadAction::kDontCare, + .store_action = StoreAction::kDontCare, + } // stencil_attachment_config ); } return RenderTarget::CreateOffscreen( - *context, // context - size, // size - "EntityPass", // label - StorageMode::kDevicePrivate, // color_storage_mode - LoadAction::kDontCare, // color_load_action - StoreAction::kDontCare, // color_store_action - readable ? StorageMode::kDevicePrivate - : StorageMode::kDeviceTransient, // stencil_storage_mode - LoadAction::kDontCare, // stencil_load_action - StoreAction::kDontCare // stencil_store_action + *context, // context + size, // size + "EntityPass", // label + RenderTarget::AttachmentConfig{ + .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 ); } diff --git a/impeller/playground/imgui/imgui_impl_impeller.cc b/impeller/playground/imgui/imgui_impl_impeller.cc index 443b32d8dcc85..8657751ef7198 100644 --- a/impeller/playground/imgui/imgui_impl_impeller.cc +++ b/impeller/playground/imgui/imgui_impl_impeller.cc @@ -94,10 +94,8 @@ bool ImGui_ImplImpeller_Init( auto desc = impeller::PipelineBuilder:: MakeDefaultPipelineDescriptor(*context); - desc->SetStencilPixelFormat(impeller::PixelFormat::kUnknown); - desc->SetStencilAttachmentDescriptors(std::nullopt); - desc->SetDepthPixelFormat(impeller::PixelFormat::kUnknown); - desc->SetDepthStencilAttachmentDescriptor(std::nullopt); + desc->ClearStencilAttachments(); + desc->ClearDepthAttachment(); bd->pipeline = context->GetPipelineLibrary()->GetPipeline(std::move(desc)).Get(); diff --git a/impeller/renderer/pipeline_descriptor.cc b/impeller/renderer/pipeline_descriptor.cc index aaebe968485c2..f22971fbff5e9 100644 --- a/impeller/renderer/pipeline_descriptor.cc +++ b/impeller/renderer/pipeline_descriptor.cc @@ -153,6 +153,26 @@ PipelineDescriptor& PipelineDescriptor::SetStencilAttachmentDescriptors( return *this; } +void PipelineDescriptor::ClearStencilAttachments() { + back_stencil_attachment_descriptor_.reset(); + front_stencil_attachment_descriptor_.reset(); + SetStencilPixelFormat(impeller::PixelFormat::kUnknown); +} + +void PipelineDescriptor::ClearDepthAttachment() { + depth_attachment_descriptor_.reset(); + SetDepthPixelFormat(impeller::PixelFormat::kUnknown); +} + +void PipelineDescriptor::ClearColorAttachment(size_t index) { + if (color_attachment_descriptors_.find(index) == + color_attachment_descriptors_.end()) { + return; + } + + color_attachment_descriptors_.erase(index); +} + void PipelineDescriptor::ResetAttachments() { color_attachment_descriptors_.clear(); depth_attachment_descriptor_.reset(); diff --git a/impeller/renderer/pipeline_descriptor.h b/impeller/renderer/pipeline_descriptor.h index e7ba72efc48eb..be13e1d2f7687 100644 --- a/impeller/renderer/pipeline_descriptor.h +++ b/impeller/renderer/pipeline_descriptor.h @@ -83,6 +83,12 @@ class PipelineDescriptor final : public Comparable { std::optional front, std::optional back); + void ClearStencilAttachments(); + + void ClearDepthAttachment(); + + void ClearColorAttachment(size_t index); + std::optional GetFrontStencilAttachmentDescriptor() const; diff --git a/impeller/renderer/render_target.cc b/impeller/renderer/render_target.cc index 57f3d71c6893a..c4178d6333c4e 100644 --- a/impeller/renderer/render_target.cc +++ b/impeller/renderer/render_target.cc @@ -183,62 +183,61 @@ const std::optional& RenderTarget::GetStencilAttachment() return stencil_; } -RenderTarget RenderTarget::CreateOffscreen(const Context& context, - ISize size, - const std::string& label, - StorageMode color_storage_mode, - LoadAction color_load_action, - StoreAction color_store_action, - StorageMode stencil_storage_mode, - LoadAction stencil_load_action, - StoreAction stencil_store_action) { +RenderTarget RenderTarget::CreateOffscreen( + const Context& context, + ISize size, + const std::string& label, + AttachmentConfig color_attachment_config, + std::optional stencil_attachment_config) { if (size.IsEmpty()) { return {}; } + RenderTarget target; + TextureDescriptor color_tex0; - color_tex0.storage_mode = color_storage_mode; + color_tex0.storage_mode = color_attachment_config.storage_mode; color_tex0.format = context.GetColorAttachmentPixelFormat(); color_tex0.size = size; color_tex0.usage = static_cast(TextureUsage::kRenderTarget) | static_cast(TextureUsage::kShaderRead); - TextureDescriptor stencil_tex0; - stencil_tex0.storage_mode = stencil_storage_mode; - stencil_tex0.format = PixelFormat::kDefaultStencil; - stencil_tex0.size = size; - stencil_tex0.usage = - static_cast(TextureUsage::kRenderTarget); - ColorAttachment color0; color0.clear_color = Color::BlackTransparent(); - color0.load_action = color_load_action; - color0.store_action = color_store_action; + color0.load_action = color_attachment_config.load_action; + color0.store_action = color_attachment_config.store_action; color0.texture = context.GetResourceAllocator()->CreateTexture(color_tex0); if (!color0.texture) { return {}; } - color0.texture->SetLabel(SPrintF("%s Color Texture", label.c_str())); + target.SetColorAttachment(color0, 0u); - StencilAttachment stencil0; - stencil0.load_action = stencil_load_action; - stencil0.store_action = stencil_store_action; - stencil0.clear_stencil = 0u; - stencil0.texture = - context.GetResourceAllocator()->CreateTexture(stencil_tex0); - - if (!stencil0.texture) { - return {}; + if (stencil_attachment_config.has_value()) { + TextureDescriptor stencil_tex0; + stencil_tex0.storage_mode = stencil_attachment_config->storage_mode; + stencil_tex0.format = PixelFormat::kDefaultStencil; + 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)); + } else { + target.SetStencilAttachment(std::nullopt); } - stencil0.texture->SetLabel(SPrintF("%s Stencil Texture", label.c_str())); - - RenderTarget target; - target.SetColorAttachment(color0, 0u); - target.SetStencilAttachment(std::move(stencil0)); - return target; } @@ -246,21 +245,18 @@ RenderTarget RenderTarget::CreateOffscreenMSAA( const Context& context, ISize size, const std::string& label, - StorageMode color_storage_mode, - StorageMode color_resolve_storage_mode, - LoadAction color_load_action, - StoreAction color_store_action, - StorageMode stencil_storage_mode, - LoadAction stencil_load_action, - StoreAction stencil_store_action) { + AttachmentConfigMSAA color_attachment_config, + std::optional stencil_attachment_config) { if (size.IsEmpty()) { return {}; } + RenderTarget target; + // Create MSAA color texture. TextureDescriptor color0_tex_desc; - color0_tex_desc.storage_mode = color_storage_mode; + color0_tex_desc.storage_mode = color_attachment_config.storage_mode; color0_tex_desc.type = TextureType::kTexture2DMultisample; color0_tex_desc.sample_count = SampleCount::kCount4; color0_tex_desc.format = context.GetColorAttachmentPixelFormat(); @@ -279,7 +275,8 @@ RenderTarget RenderTarget::CreateOffscreenMSAA( // Create color resolve texture. TextureDescriptor color0_resolve_tex_desc; - color0_resolve_tex_desc.storage_mode = color_resolve_storage_mode; + color0_resolve_tex_desc.storage_mode = + color_attachment_config.resolve_storage_mode; color0_resolve_tex_desc.format = context.GetColorAttachmentPixelFormat(); color0_resolve_tex_desc.size = size; color0_resolve_tex_desc.usage = @@ -298,39 +295,41 @@ RenderTarget RenderTarget::CreateOffscreenMSAA( ColorAttachment color0; color0.clear_color = Color::BlackTransparent(); - color0.load_action = color_load_action; - color0.store_action = color_store_action; + color0.load_action = color_attachment_config.load_action; + color0.store_action = color_attachment_config.store_action; color0.texture = color0_msaa_tex; color0.resolve_texture = color0_resolve_tex; + target.SetColorAttachment(color0, 0u); + // Create MSAA stencil texture. - TextureDescriptor stencil_tex0; - stencil_tex0.storage_mode = stencil_storage_mode; - stencil_tex0.type = TextureType::kTexture2DMultisample; - stencil_tex0.sample_count = SampleCount::kCount4; - stencil_tex0.format = PixelFormat::kDefaultStencil; - stencil_tex0.size = size; - stencil_tex0.usage = - static_cast(TextureUsage::kRenderTarget); - - StencilAttachment stencil0; - stencil0.load_action = stencil_load_action; - stencil0.store_action = stencil_store_action; - stencil0.clear_stencil = 0u; - stencil0.texture = - context.GetResourceAllocator()->CreateTexture(stencil_tex0); - - if (!stencil0.texture) { - return {}; + 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 = PixelFormat::kDefaultStencil; + 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)); + } else { + target.SetStencilAttachment(std::nullopt); } - stencil0.texture->SetLabel(SPrintF("%s Stencil Texture", label.c_str())); - - RenderTarget target; - target.SetColorAttachment(color0, 0u); - target.SetStencilAttachment(std::move(stencil0)); - return target; } diff --git a/impeller/renderer/render_target.h b/impeller/renderer/render_target.h index 5951d5900cab6..aac8c508938a4 100644 --- a/impeller/renderer/render_target.h +++ b/impeller/renderer/render_target.h @@ -19,28 +19,44 @@ class Context; class RenderTarget { public: + struct AttachmentConfig { + StorageMode storage_mode; + LoadAction load_action; + StoreAction store_action; + }; + + struct AttachmentConfigMSAA { + StorageMode storage_mode; + StorageMode resolve_storage_mode; + LoadAction load_action; + StoreAction store_action; + }; + + static constexpr AttachmentConfig kDefaultAttachmentConfig = { + .storage_mode = StorageMode::kDevicePrivate, + .load_action = LoadAction::kClear, + .store_action = StoreAction::kStore}; + + static constexpr AttachmentConfigMSAA kDefaultAttachmentConfigMSAA = { + .storage_mode = StorageMode::kDeviceTransient, + .resolve_storage_mode = StorageMode::kDevicePrivate, + .load_action = LoadAction::kClear, + .store_action = StoreAction::kMultisampleResolve}; + static RenderTarget CreateOffscreen( const Context& context, ISize size, const std::string& label = "Offscreen", - StorageMode color_storage_mode = StorageMode::kDevicePrivate, - LoadAction color_load_action = LoadAction::kClear, - StoreAction color_store_action = StoreAction::kStore, - StorageMode stencil_storage_mode = StorageMode::kDeviceTransient, - LoadAction stencil_load_action = LoadAction::kClear, - StoreAction stencil_store_action = StoreAction::kDontCare); + AttachmentConfig color_attachment_config = kDefaultAttachmentConfig, + std::optional stencil_attachment_config = std::nullopt); static RenderTarget CreateOffscreenMSAA( const Context& context, ISize size, const std::string& label = "Offscreen MSAA", - StorageMode color_storage_mode = StorageMode::kDeviceTransient, - StorageMode color_resolve_storage_mode = StorageMode::kDevicePrivate, - LoadAction color_load_action = LoadAction::kClear, - StoreAction color_store_action = StoreAction::kMultisampleResolve, - StorageMode stencil_storage_mode = StorageMode::kDeviceTransient, - LoadAction stencil_load_action = LoadAction::kClear, - StoreAction stencil_store_action = StoreAction::kDontCare); + AttachmentConfigMSAA color_attachment_config = + kDefaultAttachmentConfigMSAA, + std::optional stencil_attachment_config = std::nullopt); RenderTarget();