Flutter Impeller
pipeline.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef FLUTTER_IMPELLER_RENDERER_PIPELINE_H_
6 #define FLUTTER_IMPELLER_RENDERER_PIPELINE_H_
7 
8 #include <future>
9 
11 #include "impeller/core/raw_ptr.h"
19 
20 namespace impeller {
21 
22 using PipelineKey = int64_t;
23 
24 class PipelineLibrary;
25 template <typename PipelineDescriptor_>
26 class Pipeline;
27 
28 template <typename T>
30  std::optional<T> descriptor;
31  std::shared_future<std::shared_ptr<Pipeline<T>>> future;
32 
33  const std::shared_ptr<Pipeline<T>> Get() const { return future.get(); }
34 
35  bool IsValid() const { return future.valid(); }
36 };
37 
38 //------------------------------------------------------------------------------
39 /// @brief Describes the fixed function and programmable aspects of
40 /// rendering and compute operations performed by commands submitted
41 /// to the GPU via a command buffer.
42 ///
43 /// A pipeline handle must be allocated upfront and kept alive for
44 /// as long as possible. Do not create a pipeline object within a
45 /// frame workload.
46 ///
47 /// This pipeline object is almost never used directly as it is
48 /// untyped. Use reflected shader information generated by the
49 /// Impeller offline shader compiler to generate a typed pipeline
50 /// object.
51 ///
52 template <typename T>
53 class Pipeline {
54  public:
55  virtual ~Pipeline();
56 
57  virtual bool IsValid() const = 0;
58 
59  //----------------------------------------------------------------------------
60  /// @brief Get the descriptor that was responsible for creating this
61  /// pipeline. It may be copied and modified to create a pipeline
62  /// variant.
63  ///
64  /// @return The descriptor.
65  ///
66  const T& GetDescriptor() const;
67 
69  bool async,
70  const std::function<void(T& desc)>& descriptor_callback) const;
71 
72  protected:
73  const std::weak_ptr<PipelineLibrary> library_;
74 
75  const T desc_;
76 
77  Pipeline(std::weak_ptr<PipelineLibrary> library, const T& desc);
78 
79  private:
80  Pipeline(const Pipeline&) = delete;
81 
82  Pipeline& operator=(const Pipeline&) = delete;
83 };
84 
85 /// @brief A raw ptr to a pipeline object.
86 ///
87 /// These pipeline refs are safe to use as the context will keep the
88 /// pipelines alive throughout rendering.
90 
91 extern template class Pipeline<PipelineDescriptor>;
92 extern template class Pipeline<ComputePipelineDescriptor>;
93 
94 /// @brief Create a pipeline for the given descriptor.
95 ///
96 /// If `async` is true, the compilation is performed on a worker thread. The
97 /// returned future will complete once that work is done. If `async` is false,
98 /// the work is done on the current thread.
99 ///
100 /// It is more performant to set async to false than to spawn a
101 /// worker and immediately block on the future completion.
103  const Context& context,
104  std::optional<PipelineDescriptor> desc,
105  bool async = true);
106 
108  const Context& context,
109  std::optional<ComputePipelineDescriptor> desc);
110 
111 /// Holds a reference to a Pipeline used for rendering.
112 ///
113 /// @see RenderPipelineHandle the templated subclass that stores compile-time
114 /// shader information.
116  public:
117  explicit GenericRenderPipelineHandle(const Context& context,
118  std::optional<PipelineDescriptor> desc,
119  bool async = true)
121  CreatePipelineFuture(context, std::move(desc), /*async=*/async)) {}
122 
125  : pipeline_future_(std::move(future)) {}
126 
127  virtual ~GenericRenderPipelineHandle() = default;
128 
129  std::shared_ptr<Pipeline<PipelineDescriptor>> WaitAndGet(
130  PipelineCompileQueue* queue) {
131  if (did_wait_) {
132  return pipeline_;
133  }
134  did_wait_ = true;
135  if (pipeline_future_.IsValid()) {
136  if (queue != nullptr && pipeline_future_.descriptor.has_value()) {
137  queue->PerformJobEagerly(pipeline_future_.descriptor.value());
138  }
139  pipeline_ = pipeline_future_.Get();
140  }
141  return pipeline_;
142  }
143 
144  std::optional<PipelineDescriptor> GetDescriptor() const {
145  return pipeline_future_.descriptor;
146  }
147 
148  private:
149  PipelineFuture<PipelineDescriptor> pipeline_future_;
150  std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline_;
151  bool did_wait_ = false;
152 
154 
156  delete;
157 };
158 
159 /// Holds a reference to a Pipeline used for rendering while also maintaining
160 /// the vertex shader and fragment shader types at compile-time.
161 ///
162 /// See also:
163 /// - impeller::ContentContext::Variants - the typical container for
164 /// RenderPipelineHandles.
165 template <class VertexShader_, class FragmentShader_>
167  public:
168  using VertexShader = VertexShader_;
169  using FragmentShader = FragmentShader_;
171 
172  explicit RenderPipelineHandle(const Context& context, bool async = true)
174  context,
175  Builder::MakeDefaultPipelineDescriptor(context),
176  async)) {}
177 
178  explicit RenderPipelineHandle(const Context& context,
179  std::optional<PipelineDescriptor> desc,
180  bool async = true)
181  : GenericRenderPipelineHandle(context, std::move(desc), async) {}
182 
184  : GenericRenderPipelineHandle(std::move(future)) {}
185 
186  private:
188 
189  RenderPipelineHandle& operator=(const RenderPipelineHandle&) = delete;
190 };
191 
192 template <class ComputeShader_>
194  public:
195  using ComputeShader = ComputeShader_;
197 
198  explicit ComputePipelineHandle(const Context& context)
200  context,
201  Builder::MakeDefaultPipelineDescriptor(context))) {}
202 
204  const Context& context,
205  std::optional<ComputePipelineDescriptor> compute_desc)
206  : ComputePipelineHandle(CreatePipelineFuture(context, compute_desc)) {}
207 
210  : pipeline_future_(std::move(future)) {}
211 
212  std::shared_ptr<Pipeline<ComputePipelineDescriptor>> WaitAndGet() {
213  if (did_wait_) {
214  return pipeline_;
215  }
216  did_wait_ = true;
217  if (pipeline_future_.IsValid()) {
218  pipeline_ = pipeline_future_.Get();
219  }
220  return pipeline_;
221  }
222 
223  private:
225  std::shared_ptr<Pipeline<ComputePipelineDescriptor>> pipeline_;
226  bool did_wait_ = false;
227 
229 
230  ComputePipelineHandle& operator=(const ComputePipelineHandle&) = delete;
231 };
232 
233 } // namespace impeller
234 
235 #endif // FLUTTER_IMPELLER_RENDERER_PIPELINE_H_
ComputePipelineHandle(PipelineFuture< ComputePipelineDescriptor > future)
Definition: pipeline.h:208
ComputePipelineHandle(const Context &context, std::optional< ComputePipelineDescriptor > compute_desc)
Definition: pipeline.h:203
ComputePipelineHandle(const Context &context)
Definition: pipeline.h:198
ComputeShader_ ComputeShader
Definition: pipeline.h:195
std::shared_ptr< Pipeline< ComputePipelineDescriptor > > WaitAndGet()
Definition: pipeline.h:212
To do anything rendering related with Impeller, you need a context.
Definition: context.h:65
virtual ~GenericRenderPipelineHandle()=default
std::optional< PipelineDescriptor > GetDescriptor() const
Definition: pipeline.h:144
GenericRenderPipelineHandle(PipelineFuture< PipelineDescriptor > future)
Definition: pipeline.h:123
GenericRenderPipelineHandle(const Context &context, std::optional< PipelineDescriptor > desc, bool async=true)
Definition: pipeline.h:117
std::shared_ptr< Pipeline< PipelineDescriptor > > WaitAndGet(PipelineCompileQueue *queue)
Definition: pipeline.h:129
A task queue designed for managing compilation of pipeline state objects.
void PerformJobEagerly(const PipelineDescriptor &desc)
If the task has not yet been done, perform it eagerly on the calling thread. This can be used in lieu...
Describes the fixed function and programmable aspects of rendering and compute operations performed b...
Definition: pipeline.h:53
Pipeline(std::weak_ptr< PipelineLibrary > library, const T &desc)
Definition: pipeline.cc:18
PipelineFuture< T > CreateVariant(bool async, const std::function< void(T &desc)> &descriptor_callback) const
Definition: pipeline.cc:56
const std::weak_ptr< PipelineLibrary > library_
Definition: pipeline.h:73
virtual bool IsValid() const =0
const T & GetDescriptor() const
Get the descriptor that was responsible for creating this pipeline. It may be copied and modified to ...
Definition: pipeline.cc:51
RenderPipelineHandle(const Context &context, std::optional< PipelineDescriptor > desc, bool async=true)
Definition: pipeline.h:178
RenderPipelineHandle(const Context &context, bool async=true)
Definition: pipeline.h:172
RenderPipelineHandle(PipelineFuture< PipelineDescriptor > future)
Definition: pipeline.h:183
FragmentShader_ FragmentShader
Definition: pipeline.h:169
PipelineFuture< PipelineDescriptor > CreatePipelineFuture(const Context &context, std::optional< PipelineDescriptor > desc, bool async)
Create a pipeline for the given descriptor.
Definition: pipeline.cc:24
int64_t PipelineKey
Definition: pipeline.h:22
Definition: comparable.h:95
An optional (but highly recommended) utility for creating pipelines from reflected shader information...
An optional (but highly recommended) utility for creating pipelines from reflected shader information...
std::shared_future< std::shared_ptr< Pipeline< T > > > future
Definition: pipeline.h:31
const std::shared_ptr< Pipeline< T > > Get() const
Definition: pipeline.h:33
bool IsValid() const
Definition: pipeline.h:35
std::optional< T > descriptor
Definition: pipeline.h:30