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"
18 
19 namespace impeller {
20 
21 using PipelineKey = int64_t;
22 
23 class PipelineLibrary;
24 template <typename PipelineDescriptor_>
25 class Pipeline;
26 
27 template <typename T>
29  std::optional<T> descriptor;
30  std::shared_future<std::shared_ptr<Pipeline<T>>> future;
31 
32  const std::shared_ptr<Pipeline<T>> Get() const { return future.get(); }
33 
34  bool IsValid() const { return future.valid(); }
35 };
36 
37 //------------------------------------------------------------------------------
38 /// @brief Describes the fixed function and programmable aspects of
39 /// rendering and compute operations performed by commands submitted
40 /// to the GPU via a command buffer.
41 ///
42 /// A pipeline handle must be allocated upfront and kept alive for
43 /// as long as possible. Do not create a pipeline object within a
44 /// frame workload.
45 ///
46 /// This pipeline object is almost never used directly as it is
47 /// untyped. Use reflected shader information generated by the
48 /// Impeller offline shader compiler to generate a typed pipeline
49 /// object.
50 ///
51 template <typename T>
52 class Pipeline {
53  public:
54  virtual ~Pipeline();
55 
56  virtual bool IsValid() const = 0;
57 
58  //----------------------------------------------------------------------------
59  /// @brief Get the descriptor that was responsible for creating this
60  /// pipeline. It may be copied and modified to create a pipeline
61  /// variant.
62  ///
63  /// @return The descriptor.
64  ///
65  const T& GetDescriptor() const;
66 
68  bool async,
69  std::function<void(T& desc)> descriptor_callback) const;
70 
71  protected:
72  const std::weak_ptr<PipelineLibrary> library_;
73 
74  const T desc_;
75 
76  Pipeline(std::weak_ptr<PipelineLibrary> library, T desc);
77 
78  private:
79  Pipeline(const Pipeline&) = delete;
80 
81  Pipeline& operator=(const Pipeline&) = delete;
82 };
83 
84 /// @brief A raw ptr to a pipeline object.
85 ///
86 /// These pipeline refs are safe to use as the context will keep the
87 /// pipelines alive throughout rendering.
89 
90 extern template class Pipeline<PipelineDescriptor>;
91 extern template class Pipeline<ComputePipelineDescriptor>;
92 
93 /// @brief Create a pipeline for the given descriptor.
94 ///
95 /// If `async` is true, the compilation is performed on a worker thread. The
96 /// returned future will complete once that work is done. If `async` is false,
97 /// the work is done on the current thread.
98 ///
99 /// It is more performant to set async to false than to spawn a
100 /// worker and immediately block on the future completion.
102  const Context& context,
103  std::optional<PipelineDescriptor> desc,
104  bool async = true);
105 
107  const Context& context,
108  std::optional<ComputePipelineDescriptor> desc);
109 
110 /// Holds a reference to a Pipeline used for rendering.
111 ///
112 /// @see RenderPipelineHandle the templated subclass that stores compile-time
113 /// shader information.
115  public:
116  explicit GenericRenderPipelineHandle(const Context& context,
117  std::optional<PipelineDescriptor> desc,
118  bool async = true)
120  CreatePipelineFuture(context, std::move(desc), /*async=*/async)) {}
121 
124  : pipeline_future_(std::move(future)) {}
125 
126  virtual ~GenericRenderPipelineHandle() = default;
127 
128  std::shared_ptr<Pipeline<PipelineDescriptor>> WaitAndGet() {
129  if (did_wait_) {
130  return pipeline_;
131  }
132  did_wait_ = true;
133  if (pipeline_future_.IsValid()) {
134  pipeline_ = pipeline_future_.Get();
135  }
136  return pipeline_;
137  }
138 
139  std::optional<PipelineDescriptor> GetDescriptor() const {
140  return pipeline_future_.descriptor;
141  }
142 
143  private:
144  PipelineFuture<PipelineDescriptor> pipeline_future_;
145  std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline_;
146  bool did_wait_ = false;
147 
149 
151  delete;
152 };
153 
154 /// Holds a reference to a Pipeline used for rendering while also maintaining
155 /// the vertex shader and fragment shader types at compile-time.
156 ///
157 /// See also:
158 /// - impeller::ContentContext::Variants - the typical container for
159 /// RenderPipelineHandles.
160 template <class VertexShader_, class FragmentShader_>
162  public:
163  using VertexShader = VertexShader_;
164  using FragmentShader = FragmentShader_;
166 
167  explicit RenderPipelineHandle(const Context& context, bool async = true)
169  context,
170  Builder::MakeDefaultPipelineDescriptor(context),
171  async)) {}
172 
173  explicit RenderPipelineHandle(const Context& context,
174  std::optional<PipelineDescriptor> desc,
175  bool async = true)
176  : GenericRenderPipelineHandle(context, desc, async) {}
177 
179  : GenericRenderPipelineHandle(std::move(future)) {}
180 
181  private:
183 
184  RenderPipelineHandle& operator=(const RenderPipelineHandle&) = delete;
185 };
186 
187 template <class ComputeShader_>
189  public:
190  using ComputeShader = ComputeShader_;
192 
193  explicit ComputePipelineHandle(const Context& context)
195  context,
196  Builder::MakeDefaultPipelineDescriptor(context))) {}
197 
199  const Context& context,
200  std::optional<ComputePipelineDescriptor> compute_desc)
201  : ComputePipelineHandle(CreatePipelineFuture(context, compute_desc)) {}
202 
205  : pipeline_future_(std::move(future)) {}
206 
207  std::shared_ptr<Pipeline<ComputePipelineDescriptor>> WaitAndGet() {
208  if (did_wait_) {
209  return pipeline_;
210  }
211  did_wait_ = true;
212  if (pipeline_future_.IsValid()) {
213  pipeline_ = pipeline_future_.Get();
214  }
215  return pipeline_;
216  }
217 
218  private:
220  std::shared_ptr<Pipeline<ComputePipelineDescriptor>> pipeline_;
221  bool did_wait_ = false;
222 
224 
225  ComputePipelineHandle& operator=(const ComputePipelineHandle&) = delete;
226 };
227 
228 } // namespace impeller
229 
230 #endif // FLUTTER_IMPELLER_RENDERER_PIPELINE_H_
ComputePipelineHandle(PipelineFuture< ComputePipelineDescriptor > future)
Definition: pipeline.h:203
ComputePipelineHandle(const Context &context, std::optional< ComputePipelineDescriptor > compute_desc)
Definition: pipeline.h:198
ComputePipelineHandle(const Context &context)
Definition: pipeline.h:193
ComputeShader_ ComputeShader
Definition: pipeline.h:190
std::shared_ptr< Pipeline< ComputePipelineDescriptor > > WaitAndGet()
Definition: pipeline.h:207
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:139
GenericRenderPipelineHandle(PipelineFuture< PipelineDescriptor > future)
Definition: pipeline.h:122
GenericRenderPipelineHandle(const Context &context, std::optional< PipelineDescriptor > desc, bool async=true)
Definition: pipeline.h:116
std::shared_ptr< Pipeline< PipelineDescriptor > > WaitAndGet()
Definition: pipeline.h:128
Describes the fixed function and programmable aspects of rendering and compute operations performed b...
Definition: pipeline.h:52
PipelineFuture< T > CreateVariant(bool async, std::function< void(T &desc)> descriptor_callback) const
Definition: pipeline.cc:56
const std::weak_ptr< PipelineLibrary > library_
Definition: pipeline.h:72
virtual bool IsValid() const =0
Pipeline(std::weak_ptr< PipelineLibrary > library, T desc)
Definition: pipeline.cc:18
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:173
RenderPipelineHandle(const Context &context, bool async=true)
Definition: pipeline.h:167
RenderPipelineHandle(PipelineFuture< PipelineDescriptor > future)
Definition: pipeline.h:178
FragmentShader_ FragmentShader
Definition: pipeline.h:164
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:21
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:30
const std::shared_ptr< Pipeline< T > > Get() const
Definition: pipeline.h:32
bool IsValid() const
Definition: pipeline.h:34
std::optional< T > descriptor
Definition: pipeline.h:29