| Flutter Impeller |

context_mtl.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_BACKEND_METAL_CONTEXT_MTL_H_
6 #define FLUTTER_IMPELLER_RENDERER_BACKEND_METAL_CONTEXT_MTL_H_
7
8 #include <Metal/Metal.h>
9
10 #include <deque>
11 #include <string>
12
13 #include "flutter/fml/concurrent_message_loop.h"
14 #include "flutter/fml/synchronization/sync_switch.h"
15 #include "fml/closure.h"
16 #include "impeller/base/backend_cast.h"
17 #include "impeller/core/sampler.h"
18 #include "impeller/renderer/backend/metal/allocator_mtl.h"
19 #include "impeller/renderer/backend/metal/command_buffer_mtl.h"
20 #include "impeller/renderer/backend/metal/gpu_tracer_mtl.h"
21 #include "impeller/renderer/backend/metal/pipeline_library_mtl.h"
22 #include "impeller/renderer/backend/metal/shader_library_mtl.h"
23 #include "impeller/renderer/capabilities.h"
24 #include "impeller/renderer/command_queue.h"
25 #include "impeller/renderer/context.h"
26
27 #if TARGET_OS_SIMULATOR
28 #define IMPELLER_CA_METAL_LAYER_AVAILABLE API_AVAILABLE(macos(10.11), ios(13.0))
29 #else // TARGET_OS_SIMULATOR
30 #define IMPELLER_CA_METAL_LAYER_AVAILABLE API_AVAILABLE(macos(10.11), ios(8.0))
31 #endif // TARGET_OS_SIMULATOR
32
33 namespace impeller {
34
35 /// @brief Creates and manages a Metal capture scope that supports frame capture
36 /// when using the FlutterMetalLayer backed drawable.
37 class ImpellerMetalCaptureManager {
38 public:
39 /// @brief Construct a new capture manager from the provided Metal device.
40 explicit ImpellerMetalCaptureManager(id<MTLDevice> device);
41
42 ~ImpellerMetalCaptureManager() = default;
43
44 /// Whether or not the Impeller capture scope is active.
45 ///
46 /// This is distinct from whether or not there is a session recording the
47 /// capture. That can be checked with `[[MTLCaptureManager
48 /// sharedCaptureManager] isCapturing].`
49 bool CaptureScopeActive() const;
50
51 /// @brief Begin a new capture scope, no-op if the scope has already started.
52 void StartCapture();
53
54 /// @brief End the current capture scope.
55 void FinishCapture();
56
57 private:
58 id<MTLCaptureScope> current_capture_scope_;
59 bool scope_active_ = false;
60
61 ImpellerMetalCaptureManager(const ImpellerMetalCaptureManager&) = default;
62 ImpellerMetalCaptureManager(ImpellerMetalCaptureManager&&) = delete;
63 };
64
65 class ContextMTL final : public Context,
66 public BackendCast<ContextMTL, Context>,
67 public std::enable_shared_from_this<ContextMTL> {
68 public:
69 static std::shared_ptr<ContextMTL> Create(
70 const std::vector<std::string>& shader_library_paths,
71 std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch);
72
73 static std::shared_ptr<ContextMTL> Create(
74 const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries_data,
75 std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch,
76 const std::string& label,
77 std::optional<PixelFormat> pixel_format_override = std::nullopt);
78
79 static std::shared_ptr<ContextMTL> Create(
80 id<MTLDevice> device,
81 id<MTLCommandQueue> command_queue,
82 const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries_data,
83 std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch,
84 const std::string& label);
85
86 // |Context|
87 ~ContextMTL() override;
88
89 // |Context|
90 BackendType GetBackendType() const override;
91
92 id<MTLDevice> GetMTLDevice() const;
93
94 // |Context|
95 std::string DescribeGpuModel() const override;
96
97 // |Context|
98 bool IsValid() const override;
99
100 // |Context|
101 std::shared_ptr<Allocator> GetResourceAllocator() const override;
102
103 // |Context|
104 std::shared_ptr<ShaderLibrary> GetShaderLibrary() const override;
105
106 // |Context|
107 std::shared_ptr<SamplerLibrary> GetSamplerLibrary() const override;
108
109 // |Context|
110 std::shared_ptr<PipelineLibrary> GetPipelineLibrary() const override;
111
112 // |Context|
113 std::shared_ptr<CommandBuffer> CreateCommandBuffer() const override;
114
115 // |Context|
116 std::shared_ptr<CommandQueue> GetCommandQueue() const override;
117
118 // |Context|
119 const std::shared_ptr<const Capabilities>& GetCapabilities() const override;
120
121 // |Context|
122 RuntimeStageBackend GetRuntimeStageBackend() const override;
123
124 void SetCapabilities(const std::shared_ptr<const Capabilities>& capabilities);
125
126 // |Context|
127 bool UpdateOffscreenLayerPixelFormat(PixelFormat format) override;
128
129 // |Context|
130 void Shutdown() override;
131
132 id<MTLCommandBuffer> CreateMTLCommandBuffer(const std::string& label) const;
133
134 std::shared_ptr<const fml::SyncSwitch> GetIsGpuDisabledSyncSwitch() const;
135
136 #ifdef IMPELLER_DEBUG
137 std::shared_ptr<GPUTracerMTL> GetGPUTracer() const;
138
139 const std::shared_ptr<ImpellerMetalCaptureManager> GetCaptureManager() const;
140 #endif // IMPELLER_DEBUG
141
142 // |Context|
143 void StoreTaskForGPU(const fml::closure& task,
144 const fml::closure& failure) override;
145
146 private:
147 class SyncSwitchObserver : public fml::SyncSwitch::Observer {
148 public:
149 explicit SyncSwitchObserver(ContextMTL& parent);
150 virtual ~SyncSwitchObserver() = default;
151 void OnSyncSwitchUpdate(bool new_value) override;
152
153 private:
154 ContextMTL& parent_;
155 };
156
157 struct PendingTasks {
158 fml::closure task;
159 fml::closure failure;
160 };
161
162 id<MTLDevice> device_ = nullptr;
163 id<MTLCommandQueue> command_queue_ = nullptr;
164 std::shared_ptr<ShaderLibraryMTL> shader_library_;
165 std::shared_ptr<PipelineLibraryMTL> pipeline_library_;
166 std::shared_ptr<SamplerLibrary> sampler_library_;
167 std::shared_ptr<AllocatorMTL> resource_allocator_;
168 std::shared_ptr<const Capabilities> device_capabilities_;
169 std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch_;
170 Mutex tasks_awaiting_gpu_mutex_;
171 std::deque<PendingTasks> tasks_awaiting_gpu_ IPLR_GUARDED_BY(
172 tasks_awaiting_gpu_mutex_);
173 std::unique_ptr<SyncSwitchObserver> sync_switch_observer_;
174 std::shared_ptr<CommandQueue> command_queue_ip_;
175 #ifdef IMPELLER_DEBUG
176 std::shared_ptr<GPUTracerMTL> gpu_tracer_;
177 std::shared_ptr<ImpellerMetalCaptureManager> capture_manager_;
178 #endif // IMPELLER_DEBUG
179 bool is_valid_ = false;
180
181 ContextMTL(id<MTLDevice> device,
182 id<MTLCommandQueue> command_queue,
183 NSArray<id<MTLLibrary>>* shader_libraries,
184 std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch,
185 std::optional<PixelFormat> pixel_format_override = std::nullopt);
186
187 std::shared_ptr<CommandBuffer> CreateCommandBufferInQueue(
188 id<MTLCommandQueue> queue) const;
189
190 void FlushTasksAwaitingGPU();
191
192 ContextMTL(const ContextMTL&) = delete;
193
194 ContextMTL& operator=(const ContextMTL&) = delete;
195 };
196
197 } // namespace impeller
198
199 #endif // FLUTTER_IMPELLER_RENDERER_BACKEND_METAL_CONTEXT_MTL_H_
impeller::ContextMTL::GetIsGpuDisabledSyncSwitch
std::shared_ptr< const fml::SyncSwitch > GetIsGpuDisabledSyncSwitch() const
Definition: context_mtl.mm:332
impeller::ContextMTL::GetRuntimeStageBackend
RuntimeStageBackend GetRuntimeStageBackend() const override
Retrieve the runtime stage for this context type.
Definition: context_mtl.mm:435
impeller::Context::BackendType
BackendType
Definition: context.h:48
command_buffer_mtl.h
command_queue.h
impeller::ContextMTL::GetSamplerLibrary
std::shared_ptr< SamplerLibrary > GetSamplerLibrary() const override
Returns the library of combined image samplers used in shaders.
Definition: context_mtl.mm:314
allocator_mtl.h
impeller::ContextMTL::GetBackendType
BackendType GetBackendType() const override
Get the graphics backend of an Impeller context.
Definition: context_mtl.mm:289
impeller::ImpellerMetalCaptureManager::CaptureScopeActive
bool CaptureScopeActive() const
Definition: context_mtl.mm:452
impeller::ContextMTL::Create
static std::shared_ptr< ContextMTL > Create(const std::vector< std::string > &shader_library_paths, std::shared_ptr< const fml::SyncSwitch > is_gpu_disabled_sync_switch)
Definition: context_mtl.mm:226
sampler.h
impeller::ImpellerMetalCaptureManager::StartCapture
void StartCapture()
Begin a new capture scope, no-op if the scope has already started.
Definition: context_mtl.mm:456
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:99
impeller::ContextMTL::GetResourceAllocator
std::shared_ptr< Allocator > GetResourceAllocator() const override
Returns the allocator used to create textures and buffers on the device.
Definition: context_mtl.mm:351
impeller::ImpellerMetalCaptureManager::FinishCapture
void FinishCapture()
End the current capture scope.
Definition: context_mtl.mm:464
impeller::ContextMTL::StoreTaskForGPU
void StoreTaskForGPU(const fml::closure &task, const fml::closure &failure) override
Definition: context_mtl.mm:383
impeller::ContextMTL::SetCapabilities
void SetCapabilities(const std::shared_ptr< const Capabilities > &capabilities)
Definition: context_mtl.mm:363
shader_library_mtl.h
impeller::RuntimeStageBackend
RuntimeStageBackend
Definition: runtime_types.h:16
impeller::ContextMTL::UpdateOffscreenLayerPixelFormat
bool UpdateOffscreenLayerPixelFormat(PixelFormat format) override
Definition: context_mtl.mm:369
backend_cast.h
impeller::ImpellerMetalCaptureManager
Creates and manages a Metal capture scope that supports frame capture when using the FlutterMetalLaye...
Definition: context_mtl.h:37
capabilities.h
impeller::ContextMTL::Shutdown
void Shutdown() override
Force all pending asynchronous work to finish. This is achieved by deleting all owned concurrent mess...
Definition: context_mtl.mm:324
impeller::ImpellerMetalCaptureManager::ImpellerMetalCaptureManager
ImpellerMetalCaptureManager(id< MTLDevice > device)
Construct a new capture manager from the provided Metal device.
Definition: context_mtl.mm:446
impeller::ContextMTL::IsValid
bool IsValid() const override
Determines if a context is valid. If the caller ever receives an invalid context, they must discard i...
Definition: context_mtl.mm:299
pipeline_library_mtl.h
impeller::ContextMTL::GetMTLDevice
id< MTLDevice > GetMTLDevice() const
Definition: context_mtl.mm:355
impeller::ImpellerMetalCaptureManager::~ImpellerMetalCaptureManager
~ImpellerMetalCaptureManager()=default
impeller::Context
To do anything rendering related with Impeller, you need a context.
Definition: context.h:46
impeller::BackendCast
Definition: backend_cast.h:11
impeller::ContextMTL::GetPipelineLibrary
std::shared_ptr< PipelineLibrary > GetPipelineLibrary() const override
Returns the library of pipelines used by render or compute commands.
Definition: context_mtl.mm:309
impeller::ContextMTL::DescribeGpuModel
std::string DescribeGpuModel() const override
Definition: context_mtl.mm:294
impeller::ContextMTL::CreateMTLCommandBuffer
id< MTLCommandBuffer > CreateMTLCommandBuffer(const std::string &label) const
Definition: context_mtl.mm:374
impeller::ContextMTL::GetCommandQueue
std::shared_ptr< CommandQueue > GetCommandQueue() const override
Return the graphics queue for submitting command buffers.
Definition: context_mtl.mm:430
gpu_tracer_mtl.h
context.h
impeller::ContextMTL::GetCapabilities
const std::shared_ptr< const Capabilities > & GetCapabilities() const override
Get the capabilities of Impeller context. All optionally supported feature of the platform,...
Definition: context_mtl.mm:359
impeller::ContextMTL
Definition: context_mtl.h:65
impeller
Definition: allocation.cc:12
impeller::ContextMTL::~ContextMTL
~ContextMTL() override
Definition: context_mtl.mm:285
impeller::ContextMTL::CreateCommandBuffer
std::shared_ptr< CommandBuffer > CreateCommandBuffer() const override
Create a new command buffer. Command buffers can be used to encode graphics, blit,...
Definition: context_mtl.mm:319
impeller::ContextMTL::GetShaderLibrary
std::shared_ptr< ShaderLibrary > GetShaderLibrary() const override
Returns the library of shaders used to specify the programmable stages of a pipeline.
Definition: context_mtl.mm:304