diff --git a/engine/src/flutter/impeller/entity/contents/content_context.cc b/engine/src/flutter/impeller/entity/contents/content_context.cc index b138f95d0d4..aa81e774bde 100644 --- a/engine/src/flutter/impeller/entity/contents/content_context.cc +++ b/engine/src/flutter/impeller/entity/contents/content_context.cc @@ -28,6 +28,56 @@ namespace impeller { namespace { +/// A generic version of `Variants` which mostly exists to reduce code size. +class GenericVariants { + public: + void Set(const ContentContextOptions& options, + std::unique_ptr pipeline) { + uint64_t p_key = options.ToKey(); + for (const auto& [key, pipeline] : pipelines_) { + if (key == p_key) { + return; + } + } + pipelines_.push_back(std::make_pair(p_key, std::move(pipeline))); + } + + void SetDefault(const ContentContextOptions& options, + std::unique_ptr pipeline) { + default_options_ = options; + if (pipeline) { + Set(options, std::move(pipeline)); + } + } + + GenericRenderPipelineHandle* Get(const ContentContextOptions& options) const { + uint64_t p_key = options.ToKey(); + for (const auto& [key, pipeline] : pipelines_) { + if (key == p_key) { + return pipeline.get(); + } + } + return nullptr; + } + + void SetDefaultDescriptor(std::optional desc) { + desc_ = std::move(desc); + } + + size_t GetPipelineCount() const { return pipelines_.size(); } + + bool IsDefault(const ContentContextOptions& opts) { + return default_options_.has_value() && + opts.ToKey() == default_options_.value().ToKey(); + } + + protected: + std::optional desc_; + std::optional default_options_; + std::vector>> + pipelines_; +}; + /// Holds multiple Pipelines associated with the same PipelineHandle types. /// /// For example, it may have multiple @@ -42,7 +92,7 @@ namespace { /// - impeller::RenderPipelineHandle<> - The type of objects this typically /// contains. template -class Variants { +class Variants : public GenericVariants { static_assert( ShaderStageCompatibilityChecker< typename PipelineHandleT::VertexShader, @@ -55,32 +105,20 @@ class Variants { void Set(const ContentContextOptions& options, std::unique_ptr pipeline) { - uint64_t p_key = options.ToKey(); - for (const auto& [key, pipeline] : pipelines_) { - if (key == p_key) { - return; - } - } - pipelines_.push_back(std::make_pair(p_key, std::move(pipeline))); + GenericVariants::Set(options, std::move(pipeline)); } void SetDefault(const ContentContextOptions& options, std::unique_ptr pipeline) { - default_options_ = options; - if (pipeline) { - Set(options, std::move(pipeline)); - } - } - - void SetDefaultDescriptor(std::optional desc) { - desc_ = std::move(desc); + GenericVariants::SetDefault(options, std::move(pipeline)); } void CreateDefault(const Context& context, const ContentContextOptions& options, const std::vector& constants = {}) { - auto desc = PipelineHandleT::Builder::MakeDefaultPipelineDescriptor( - context, constants); + std::optional desc = + PipelineHandleT::Builder::MakeDefaultPipelineDescriptor(context, + constants); if (!desc.has_value()) { VALIDATION_LOG << "Failed to create default pipeline."; return; @@ -96,18 +134,7 @@ class Variants { } PipelineHandleT* Get(const ContentContextOptions& options) const { - uint64_t p_key = options.ToKey(); - for (const auto& [key, pipeline] : pipelines_) { - if (key == p_key) { - return pipeline.get(); - } - } - return nullptr; - } - - bool IsDefault(const ContentContextOptions& opts) { - return default_options_.has_value() && - opts.ToKey() == default_options_.value().ToKey(); + return static_cast(GenericVariants::Get(options)); } PipelineHandleT* GetDefault(const Context& context) { @@ -123,13 +150,7 @@ class Variants { return Get(default_options_.value()); } - size_t GetPipelineCount() const { return pipelines_.size(); } - private: - std::optional desc_; - std::optional default_options_; - std::vector>> pipelines_; - Variants(const Variants&) = delete; Variants& operator=(const Variants&) = delete; diff --git a/engine/src/flutter/impeller/renderer/pipeline.h b/engine/src/flutter/impeller/renderer/pipeline.h index 0bb5c7c4756..110d804b7f2 100644 --- a/engine/src/flutter/impeller/renderer/pipeline.h +++ b/engine/src/flutter/impeller/renderer/pipeline.h @@ -107,34 +107,24 @@ PipelineFuture CreatePipelineFuture( const Context& context, std::optional desc); -/// Holds a reference to a Pipeline used for rendering while also maintaining -/// the vertex shader and fragment shader types at compile-time. +/// Holds a reference to a Pipeline used for rendering. /// -/// See also: -/// - impeller::ContentContext::Variants - the typical container for -/// RenderPipelineHandles. -template -class RenderPipelineHandle { +/// @see RenderPipelineHandle the templated subclass that stores compile-time +/// shader information. +class GenericRenderPipelineHandle { public: - using VertexShader = VertexShader_; - using FragmentShader = FragmentShader_; - using Builder = PipelineBuilder; + explicit GenericRenderPipelineHandle(const Context& context, + std::optional desc, + bool async = true) + : GenericRenderPipelineHandle( + CreatePipelineFuture(context, std::move(desc), /*async=*/async)) {} - explicit RenderPipelineHandle(const Context& context, bool async = true) - : RenderPipelineHandle(CreatePipelineFuture( - context, - Builder::MakeDefaultPipelineDescriptor(context), - async)) {} - - explicit RenderPipelineHandle(const Context& context, - std::optional desc, - bool async = true) - : RenderPipelineHandle( - CreatePipelineFuture(context, desc, /*async=*/async)) {} - - explicit RenderPipelineHandle(PipelineFuture future) + explicit GenericRenderPipelineHandle( + PipelineFuture future) : pipeline_future_(std::move(future)) {} + virtual ~GenericRenderPipelineHandle() = default; + std::shared_ptr> WaitAndGet() { if (did_wait_) { return pipeline_; @@ -155,6 +145,40 @@ class RenderPipelineHandle { std::shared_ptr> pipeline_; bool did_wait_ = false; + GenericRenderPipelineHandle(const GenericRenderPipelineHandle&) = delete; + + GenericRenderPipelineHandle& operator=(const GenericRenderPipelineHandle&) = + delete; +}; + +/// Holds a reference to a Pipeline used for rendering while also maintaining +/// the vertex shader and fragment shader types at compile-time. +/// +/// See also: +/// - impeller::ContentContext::Variants - the typical container for +/// RenderPipelineHandles. +template +class RenderPipelineHandle : public GenericRenderPipelineHandle { + public: + using VertexShader = VertexShader_; + using FragmentShader = FragmentShader_; + using Builder = PipelineBuilder; + + explicit RenderPipelineHandle(const Context& context, bool async = true) + : GenericRenderPipelineHandle(CreatePipelineFuture( + context, + Builder::MakeDefaultPipelineDescriptor(context), + async)) {} + + explicit RenderPipelineHandle(const Context& context, + std::optional desc, + bool async = true) + : GenericRenderPipelineHandle(context, desc, async) {} + + explicit RenderPipelineHandle(PipelineFuture future) + : GenericRenderPipelineHandle(std::move(future)) {} + + private: RenderPipelineHandle(const RenderPipelineHandle&) = delete; RenderPipelineHandle& operator=(const RenderPipelineHandle&) = delete;