| Flutter Impeller |

context.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_CONTEXT_H_
6 #define FLUTTER_IMPELLER_RENDERER_CONTEXT_H_
7
8 #include <future>
9 #include <memory>
10 #include <string>
11
12 #include "fml/closure.h"
13 #include "impeller/base/flags.h"
14 #include "impeller/base/thread_safety.h"
15 #include "impeller/core/allocator.h"
16 #include "impeller/core/formats.h"
17 #include "impeller/renderer/capabilities.h"
18 #include "impeller/renderer/command_queue.h"
19 #include "impeller/renderer/sampler_library.h"
20
21 namespace impeller {
22
23 class ShaderLibrary;
24 class CommandBuffer;
25 class PipelineLibrary;
26
27 /// A wrapper for provided a deferred initialization of impeller to various
28 /// engine subsystems.
29 class ImpellerContextFuture {
30 public:
31 explicit ImpellerContextFuture(
32 std::future<std::shared_ptr<impeller::Context>> context);
33
34 std::shared_ptr<impeller::Context> GetContext();
35
36 private:
37 std::mutex mutex_;
38 std::future<std::shared_ptr<impeller::Context>> future_;
39 std::shared_ptr<impeller::Context> context_;
40 bool did_wait_ = false;
41 };
42
43 //------------------------------------------------------------------------------
44 /// @brief To do anything rendering related with Impeller, you need a
45 /// context.
46 ///
47 /// Contexts are expensive to construct and typically you only need
48 /// one in the process. The context represents a connection to a
49 /// graphics or compute accelerator on the device.
50 ///
51 /// If there are multiple context in a process, it would typically
52 /// be for separation of concerns (say, use with multiple engines in
53 /// Flutter), talking to multiple accelerators, or talking to the
54 /// same accelerator using different client APIs (Metal, Vulkan,
55 /// OpenGL ES, etc..).
56 ///
57 /// Contexts are thread-safe. They may be created, used, and
58 /// collected (though not from a thread used by an internal pool) on
59 /// any thread. They may also be accessed simultaneously from
60 /// multiple threads.
61 ///
62 /// Contexts are abstract and a concrete instance must be created
63 /// using one of the subclasses of `Context` in
64 /// `//impeller/renderer/backend`.
65 class Context {
66 public:
67 enum class BackendType {
68 kMetal,
69 kOpenGLES,
70 kVulkan,
71 };
72
73 /// The maximum number of tasks that should ever be stored for
74 /// `StoreTaskForGPU`.
75 ///
76 /// This number was arbitrarily chosen. The idea is that this is a somewhat
77 /// rare situation where tasks happen to get executed in that tiny amount of
78 /// time while an app is being backgrounded but still executing.
79 static constexpr int32_t kMaxTasksAwaitingGPU = 1024;
80
81 //----------------------------------------------------------------------------
82 /// @brief Destroys an Impeller context.
83 ///
84 virtual ~Context();
85
86 //----------------------------------------------------------------------------
87 /// @brief Get the graphics backend of an Impeller context.
88 ///
89 /// This is useful for cases where a renderer needs to track and
90 /// lookup backend-specific resources, like shaders or uniform
91 /// layout information.
92 ///
93 /// It's not recommended to use this as a substitute for
94 /// per-backend capability checking. Instead, check for specific
95 /// capabilities via `GetCapabilities()`.
96 ///
97 /// @return The graphics backend of the `Context`.
98 ///
99 virtual BackendType GetBackendType() const = 0;
100
101 // TODO(129920): Refactor and move to capabilities.
102 virtual std::string DescribeGpuModel() const = 0;
103
104 //----------------------------------------------------------------------------
105 /// @brief Determines if a context is valid. If the caller ever receives
106 /// an invalid context, they must discard it and construct a new
107 /// context. There is no recovery mechanism to repair a bad
108 /// context.
109 ///
110 /// It is convention in Impeller to never return an invalid
111 /// context from a call that returns an pointer to a context. The
112 /// call implementation performs validity checks itself and return
113 /// a null context instead of a pointer to an invalid context.
114 ///
115 /// How a context goes invalid is backend specific. It could
116 /// happen due to device loss, or any other unrecoverable error.
117 ///
118 /// @return If the context is valid.
119 ///
120 virtual bool IsValid() const = 0;
121
122 //----------------------------------------------------------------------------
123 /// @brief Get the capabilities of Impeller context. All optionally
124 /// supported feature of the platform, client-rendering API, and
125 /// device can be queried using the `Capabilities`.
126 ///
127 /// @return The capabilities. Can never be `nullptr` for a valid context.
128 ///
129 virtual const std::shared_ptr<const Capabilities>& GetCapabilities()
130 const = 0;
131
132 // TODO(129920): Refactor and move to capabilities.
133 virtual bool UpdateOffscreenLayerPixelFormat(PixelFormat format);
134
135 //----------------------------------------------------------------------------
136 /// @brief Returns the allocator used to create textures and buffers on
137 /// the device.
138 ///
139 /// @return The resource allocator. Can never be `nullptr` for a valid
140 /// context.
141 ///
142 virtual std::shared_ptr<Allocator> GetResourceAllocator() const = 0;
143
144 //----------------------------------------------------------------------------
145 /// @brief Returns the library of shaders used to specify the
146 /// programmable stages of a pipeline.
147 ///
148 /// @return The shader library. Can never be `nullptr` for a valid
149 /// context.
150 ///
151 virtual std::shared_ptr<ShaderLibrary> GetShaderLibrary() const = 0;
152
153 //----------------------------------------------------------------------------
154 /// @brief Returns the library of combined image samplers used in
155 /// shaders.
156 ///
157 /// @return The sampler library. Can never be `nullptr` for a valid
158 /// context.
159 ///
160 virtual std::shared_ptr<SamplerLibrary> GetSamplerLibrary() const = 0;
161
162 //----------------------------------------------------------------------------
163 /// @brief Returns the library of pipelines used by render or compute
164 /// commands.
165 ///
166 /// @return The pipeline library. Can never be `nullptr` for a valid
167 /// context.
168 ///
169 virtual std::shared_ptr<PipelineLibrary> GetPipelineLibrary() const = 0;
170
171 //----------------------------------------------------------------------------
172 /// @brief Create a new command buffer. Command buffers can be used to
173 /// encode graphics, blit, or compute commands to be submitted to
174 /// the device.
175 ///
176 /// A command buffer can only be used on a single thread.
177 /// Multi-threaded render, blit, or compute passes must create a
178 /// new command buffer on each thread.
179 ///
180 /// @return A new command buffer.
181 ///
182 virtual std::shared_ptr<CommandBuffer> CreateCommandBuffer() const = 0;
183
184 /// @brief Return the graphics queue for submitting command buffers.
185 virtual std::shared_ptr<CommandQueue> GetCommandQueue() const = 0;
186
187 //----------------------------------------------------------------------------
188 /// @brief Force all pending asynchronous work to finish. This is
189 /// achieved by deleting all owned concurrent message loops.
190 ///
191 virtual void Shutdown() = 0;
192
193 /// Stores a task on the `ContextMTL` that is awaiting access for the GPU.
194 ///
195 /// The task will be executed in the event that the GPU access has changed to
196 /// being available or that the task has been canceled. The task should
197 /// operate with the `SyncSwitch` to make sure the GPU is accessible.
198 ///
199 /// If the queue of pending tasks is cleared without GPU access, then the
200 /// failure callback will be invoked and the primary task function will not
201 ///
202 /// Threadsafe.
203 ///
204 /// `task` will be executed on the platform thread.
205 virtual void StoreTaskForGPU(const fml::closure& task,
206 const fml::closure& failure) {
207 FML_CHECK(false && "not supported in this context");
208 }
209
210 /// Run backend specific additional setup and create common shader variants.
211 ///
212 /// This bootstrap is intended to improve the performance of several
213 /// first frame benchmarks that are tracked in the flutter device lab.
214 /// The workload includes initializing commonly used but not default
215 /// shader variants, as well as forcing driver initialization.
216 virtual void InitializeCommonlyUsedShadersIfNeeded() const {}
217
218 /// Dispose resources that are cached on behalf of the current thread.
219 ///
220 /// Some backends such as Vulkan may cache resources that can be reused while
221 /// executing a rendering operation. This API can be called after the
222 /// operation completes in order to clear the cache.
223 virtual void DisposeThreadLocalCachedResources() {}
224
225 /// @brief Enqueue command_buffer for submission by the end of the frame.
226 ///
227 /// Certain backends may immediately flush the command buffer if batch
228 /// submission is not supported. This functionality is not thread safe
229 /// and should only be used via the ContentContext for rendering a
230 /// 2D workload.
231 ///
232 /// Returns true if submission has succeeded. If the buffer is enqueued
233 /// then no error may be returned until FlushCommandBuffers is called.
234 [[nodiscard]] virtual bool EnqueueCommandBuffer(
235 std::shared_ptr<CommandBuffer> command_buffer);
236
237 /// @brief Flush all pending command buffers.
238 ///
239 /// Returns whether or not submission was successful. This functionality
240 /// is not threadsafe and should only be used via the ContentContext for
241 /// rendering a 2D workload.
242 [[nodiscard]] virtual bool FlushCommandBuffers();
243
244 virtual bool AddTrackingFence(const std::shared_ptr<Texture>& texture) const;
245
246 virtual std::shared_ptr<const IdleWaiter> GetIdleWaiter() const;
247
248 //----------------------------------------------------------------------------
249 /// Resets any thread local state that may interfere with embedders.
250 ///
251 /// Today, only the OpenGL backend can trample on thread local state that the
252 /// embedder can access. This call puts the GL state in a sane "clean" state.
253 ///
254 /// Impeller itself is resilient to a dirty thread local state table.
255 ///
256 virtual void ResetThreadLocalState() const;
257
258 /// @brief Retrieve the runtime stage for this context type.
259 ///
260 /// This is used by the engine shell and other subsystems for loading the
261 /// correct shader types.
262 virtual RuntimeStageBackend GetRuntimeStageBackend() const = 0;
263
264 /// @brief Submit the command buffer that renders to the onscreen surface.
265 virtual bool SubmitOnscreen(std::shared_ptr<CommandBuffer> cmd_buffer);
266
267 const Flags& GetFlags() const { return flags_; }
268
269 protected:
270 explicit Context(const Flags& flags);
271
272 Flags flags_;
273 std::vector<std::function<void()>> per_frame_task_;
274
275 private:
276 Context(const Context&) = delete;
277
278 Context& operator=(const Context&) = delete;
279 };
280
281 } // namespace impeller
282
283 #endif // FLUTTER_IMPELLER_RENDERER_CONTEXT_H_
allocator.h
capabilities.h
impeller::Context
To do anything rendering related with Impeller, you need a context.
Definition: context.h:65
impeller::Context::GetIdleWaiter
virtual std::shared_ptr< const IdleWaiter > GetIdleWaiter() const
Definition: context.cc:42
impeller::Context::AddTrackingFence
virtual bool AddTrackingFence(const std::shared_ptr< Texture > &texture) const
Definition: context.cc:50
impeller::Context::GetSamplerLibrary
virtual std::shared_ptr< SamplerLibrary > GetSamplerLibrary() const =0
Returns the library of combined image samplers used in shaders.
impeller::Context::CreateCommandBuffer
virtual std::shared_ptr< CommandBuffer > CreateCommandBuffer() const =0
Create a new command buffer. Command buffers can be used to encode graphics, blit,...
impeller::Context::GetPipelineLibrary
virtual std::shared_ptr< PipelineLibrary > GetPipelineLibrary() const =0
Returns the library of pipelines used by render or compute commands.
impeller::Context::SubmitOnscreen
virtual bool SubmitOnscreen(std::shared_ptr< CommandBuffer > cmd_buffer)
Submit the command buffer that renders to the onscreen surface.
Definition: context.cc:54
impeller::Context::GetShaderLibrary
virtual std::shared_ptr< ShaderLibrary > GetShaderLibrary() const =0
Returns the library of shaders used to specify the programmable stages of a pipeline.
impeller::Context::GetFlags
const Flags & GetFlags() const
Definition: context.h:267
impeller::Context::kMaxTasksAwaitingGPU
static constexpr int32_t kMaxTasksAwaitingGPU
Definition: context.h:79
impeller::Context::GetCapabilities
virtual const std::shared_ptr< const Capabilities > & GetCapabilities() const =0
Get the capabilities of Impeller context. All optionally supported feature of the platform,...
impeller::Context::per_frame_task_
std::vector< std::function< void()> > per_frame_task_
Definition: context.h:273
impeller::Context::UpdateOffscreenLayerPixelFormat
virtual bool UpdateOffscreenLayerPixelFormat(PixelFormat format)
Definition: context.cc:29
impeller::Context::GetBackendType
virtual BackendType GetBackendType() const =0
Get the graphics backend of an Impeller context.
impeller::Context::Shutdown
virtual void Shutdown()=0
Force all pending asynchronous work to finish. This is achieved by deleting all owned concurrent mess...
impeller::Context::Context
Context(const Flags &flags)
Definition: context.cc:27
impeller::Context::DisposeThreadLocalCachedResources
virtual void DisposeThreadLocalCachedResources()
Definition: context.h:223
impeller::Context::FlushCommandBuffers
virtual bool FlushCommandBuffers()
Flush all pending command buffers.
Definition: context.cc:38
impeller::Context::GetCommandQueue
virtual std::shared_ptr< CommandQueue > GetCommandQueue() const =0
Return the graphics queue for submitting command buffers.
impeller::Context::GetRuntimeStageBackend
virtual RuntimeStageBackend GetRuntimeStageBackend() const =0
Retrieve the runtime stage for this context type.
impeller::Context::StoreTaskForGPU
virtual void StoreTaskForGPU(const fml::closure &task, const fml::closure &failure)
Definition: context.h:205
impeller::Context::InitializeCommonlyUsedShadersIfNeeded
virtual void InitializeCommonlyUsedShadersIfNeeded() const
Definition: context.h:216
impeller::Context::GetResourceAllocator
virtual std::shared_ptr< Allocator > GetResourceAllocator() const =0
Returns the allocator used to create textures and buffers on the device.
impeller::Context::DescribeGpuModel
virtual std::string DescribeGpuModel() const =0
impeller::Context::~Context
virtual ~Context()
Destroys an Impeller context.
impeller::Context::IsValid
virtual bool IsValid() const =0
Determines if a context is valid. If the caller ever receives an invalid context, they must discard i...
impeller::Context::flags_
Flags flags_
Definition: context.h:272
impeller::Context::BackendType
BackendType
Definition: context.h:67
impeller::Context::BackendType::kOpenGLES
@ kOpenGLES
impeller::Context::BackendType::kMetal
@ kMetal
impeller::Context::BackendType::kVulkan
@ kVulkan
impeller::Context::ResetThreadLocalState
virtual void ResetThreadLocalState() const
Definition: context.cc:46
impeller::Context::EnqueueCommandBuffer
virtual bool EnqueueCommandBuffer(std::shared_ptr< CommandBuffer > command_buffer)
Enqueue command_buffer for submission by the end of the frame.
Definition: context.cc:33
impeller::ImpellerContextFuture
Definition: context.h:29
impeller::ImpellerContextFuture::ImpellerContextFuture
ImpellerContextFuture(std::future< std::shared_ptr< impeller::Context >> context)
Definition: context.cc:12
impeller::ImpellerContextFuture::GetContext
std::shared_ptr< impeller::Context > GetContext()
Definition: context.cc:16
command_queue.h
formats.h
flags.h
impeller
Definition: allocation.cc:12
impeller::RuntimeStageBackend
RuntimeStageBackend
Definition: runtime_types.h:16
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:99
sampler_library.h
impeller::Flags
Definition: flags.h:9
thread_safety.h