| // Copyright 2013 The Flutter Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef FLUTTER_IMPELLER_RENDERER_PIPELINE_H_ | |
| #define FLUTTER_IMPELLER_RENDERER_PIPELINE_H_ | |
| #include <future> | |
| #include "compute_pipeline_descriptor.h" | |
| #include "impeller/renderer/compute_pipeline_builder.h" | |
| #include "impeller/renderer/compute_pipeline_descriptor.h" | |
| #include "impeller/renderer/context.h" | |
| #include "impeller/renderer/pipeline_builder.h" | |
| #include "impeller/renderer/pipeline_descriptor.h" | |
| namespace impeller { | |
| class PipelineLibrary; | |
| template <typename PipelineDescriptor_> | |
| class Pipeline; | |
| template <typename T> | |
| struct PipelineFuture { | |
| std::optional<T> descriptor; | |
| std::shared_future<std::shared_ptr<Pipeline<T>>> future; | |
| const std::shared_ptr<Pipeline<T>> Get() const { return future.get(); } | |
| bool IsValid() const { return future.valid(); } | |
| }; | |
| //------------------------------------------------------------------------------ | |
| /// @brief Describes the fixed function and programmable aspects of | |
| /// rendering and compute operations performed by commands submitted | |
| /// to the GPU via a command buffer. | |
| /// | |
| /// A pipeline handle must be allocated upfront and kept alive for | |
| /// as long as possible. Do not create a pipeline object within a | |
| /// frame workload. | |
| /// | |
| /// This pipeline object is almost never used directly as it is | |
| /// untyped. Use reflected shader information generated by the | |
| /// Impeller offline shader compiler to generate a typed pipeline | |
| /// object. | |
| /// | |
| template <typename T> | |
| class Pipeline { | |
| public: | |
| virtual ~Pipeline(); | |
| virtual bool IsValid() const = 0; | |
| //---------------------------------------------------------------------------- | |
| /// @brief Get the descriptor that was responsible for creating this | |
| /// pipeline. It may be copied and modified to create a pipeline | |
| /// variant. | |
| /// | |
| /// @return The descriptor. | |
| /// | |
| const T& GetDescriptor() const; | |
| PipelineFuture<T> CreateVariant( | |
| std::function<void(T& desc)> descriptor_callback) const; | |
| protected: | |
| Pipeline(std::weak_ptr<PipelineLibrary> library, T desc); | |
| private: | |
| const std::weak_ptr<PipelineLibrary> library_; | |
| const T desc_; | |
| Pipeline(const Pipeline&) = delete; | |
| Pipeline& operator=(const Pipeline&) = delete; | |
| }; | |
| extern template class Pipeline<PipelineDescriptor>; | |
| extern template class Pipeline<ComputePipelineDescriptor>; | |
| PipelineFuture<PipelineDescriptor> CreatePipelineFuture( | |
| const Context& context, | |
| std::optional<PipelineDescriptor> desc); | |
| PipelineFuture<ComputePipelineDescriptor> CreatePipelineFuture( | |
| const Context& context, | |
| std::optional<ComputePipelineDescriptor> desc); | |
| template <class VertexShader_, class FragmentShader_> | |
| class RenderPipelineT { | |
| public: | |
| using VertexShader = VertexShader_; | |
| using FragmentShader = FragmentShader_; | |
| using Builder = PipelineBuilder<VertexShader, FragmentShader>; | |
| explicit RenderPipelineT(const Context& context) | |
| : RenderPipelineT(CreatePipelineFuture( | |
| context, | |
| Builder::MakeDefaultPipelineDescriptor(context))) {} | |
| explicit RenderPipelineT(const Context& context, | |
| std::optional<PipelineDescriptor> desc) | |
| : RenderPipelineT(CreatePipelineFuture(context, desc)) {} | |
| explicit RenderPipelineT(PipelineFuture<PipelineDescriptor> future) | |
| : pipeline_future_(std::move(future)) {} | |
| std::shared_ptr<Pipeline<PipelineDescriptor>> WaitAndGet() { | |
| if (did_wait_) { | |
| return pipeline_; | |
| } | |
| did_wait_ = true; | |
| if (pipeline_future_.IsValid()) { | |
| pipeline_ = pipeline_future_.Get(); | |
| } | |
| return pipeline_; | |
| } | |
| std::optional<PipelineDescriptor> GetDescriptor() const { | |
| return pipeline_future_.descriptor; | |
| } | |
| private: | |
| PipelineFuture<PipelineDescriptor> pipeline_future_; | |
| std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline_; | |
| bool did_wait_ = false; | |
| RenderPipelineT(const RenderPipelineT&) = delete; | |
| RenderPipelineT& operator=(const RenderPipelineT&) = delete; | |
| }; | |
| template <class ComputeShader_> | |
| class ComputePipelineT { | |
| public: | |
| using ComputeShader = ComputeShader_; | |
| using Builder = ComputePipelineBuilder<ComputeShader>; | |
| explicit ComputePipelineT(const Context& context) | |
| : ComputePipelineT(CreatePipelineFuture( | |
| context, | |
| Builder::MakeDefaultPipelineDescriptor(context))) {} | |
| explicit ComputePipelineT( | |
| const Context& context, | |
| std::optional<ComputePipelineDescriptor> compute_desc) | |
| : ComputePipelineT(CreatePipelineFuture(context, compute_desc)) {} | |
| explicit ComputePipelineT(PipelineFuture<ComputePipelineDescriptor> future) | |
| : pipeline_future_(std::move(future)) {} | |
| std::shared_ptr<Pipeline<ComputePipelineDescriptor>> WaitAndGet() { | |
| if (did_wait_) { | |
| return pipeline_; | |
| } | |
| did_wait_ = true; | |
| if (pipeline_future_.IsValid()) { | |
| pipeline_ = pipeline_future_.Get(); | |
| } | |
| return pipeline_; | |
| } | |
| private: | |
| PipelineFuture<ComputePipelineDescriptor> pipeline_future_; | |
| std::shared_ptr<Pipeline<ComputePipelineDescriptor>> pipeline_; | |
| bool did_wait_ = false; | |
| ComputePipelineT(const ComputePipelineT&) = delete; | |
| ComputePipelineT& operator=(const ComputePipelineT&) = delete; | |
| }; | |
| } // namespace impeller | |
| #endif // FLUTTER_IMPELLER_RENDERER_PIPELINE_H_ |