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"
17 #include "impeller/core/sampler.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.
38  public:
39  /// @brief Construct a new capture manager from the provided Metal device.
40  explicit ImpellerMetalCaptureManager(id<MTLDevice> device);
41 
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 
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 Flags& flags,
71  const std::vector<std::string>& shader_library_paths,
72  std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch);
73 
74  static std::shared_ptr<ContextMTL> Create(
75  const Flags& flags,
76  const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries_data,
77  std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch,
78  const std::string& label,
79  std::optional<PixelFormat> pixel_format_override = std::nullopt);
80 
81  static std::shared_ptr<ContextMTL> Create(
82  const Flags& flags,
83  id<MTLDevice> device,
84  id<MTLCommandQueue> command_queue,
85  const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries_data,
86  std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch,
87  const std::string& label);
88 
89  // |Context|
90  ~ContextMTL() override;
91 
92  // |Context|
93  BackendType GetBackendType() const override;
94 
95  id<MTLDevice> GetMTLDevice() const;
96 
97  // |Context|
98  std::string DescribeGpuModel() const override;
99 
100  // |Context|
101  bool IsValid() const override;
102 
103  // |Context|
104  std::shared_ptr<Allocator> GetResourceAllocator() const override;
105 
106  // |Context|
107  std::shared_ptr<ShaderLibrary> GetShaderLibrary() const override;
108 
109  // |Context|
110  std::shared_ptr<SamplerLibrary> GetSamplerLibrary() const override;
111 
112  // |Context|
113  std::shared_ptr<PipelineLibrary> GetPipelineLibrary() const override;
114 
115  // |Context|
116  std::shared_ptr<CommandBuffer> CreateCommandBuffer() const override;
117 
118  // |Context|
119  std::shared_ptr<CommandQueue> GetCommandQueue() const override;
120 
121  // |Context|
122  const std::shared_ptr<const Capabilities>& GetCapabilities() const override;
123 
124  // |Context|
126 
127  void SetCapabilities(const std::shared_ptr<const Capabilities>& capabilities);
128 
129  // |Context|
130  bool UpdateOffscreenLayerPixelFormat(PixelFormat format) override;
131 
132  // |Context|
133  void Shutdown() override;
134 
135  id<MTLCommandBuffer> CreateMTLCommandBuffer(const std::string& label) const;
136 
137  std::shared_ptr<const fml::SyncSwitch> GetIsGpuDisabledSyncSwitch() const;
138 
139 #ifdef IMPELLER_DEBUG
140  std::shared_ptr<GPUTracerMTL> GetGPUTracer() const;
141 
142  const std::shared_ptr<ImpellerMetalCaptureManager> GetCaptureManager() const;
143 #endif // IMPELLER_DEBUG
144 
145  // |Context|
146  void StoreTaskForGPU(const fml::closure& task,
147  const fml::closure& failure) override;
148 
149  // visible for testing.
150  void FlushTasksAwaitingGPU();
151 
152  private:
153  class SyncSwitchObserver : public fml::SyncSwitch::Observer {
154  public:
155  explicit SyncSwitchObserver(ContextMTL& parent);
156  virtual ~SyncSwitchObserver() = default;
157  void OnSyncSwitchUpdate(bool new_value) override;
158 
159  private:
160  ContextMTL& parent_;
161  };
162 
163  struct PendingTasks {
164  fml::closure task;
165  fml::closure failure;
166  };
167 
168  id<MTLDevice> device_ = nullptr;
169  id<MTLCommandQueue> command_queue_ = nullptr;
170  std::shared_ptr<ShaderLibraryMTL> shader_library_;
171  std::shared_ptr<PipelineLibraryMTL> pipeline_library_;
172  std::shared_ptr<SamplerLibrary> sampler_library_;
173  std::shared_ptr<AllocatorMTL> resource_allocator_;
174  std::shared_ptr<const Capabilities> device_capabilities_;
175  std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch_;
176  Mutex tasks_awaiting_gpu_mutex_;
177  std::deque<PendingTasks> tasks_awaiting_gpu_ IPLR_GUARDED_BY(
178  tasks_awaiting_gpu_mutex_);
179  std::unique_ptr<SyncSwitchObserver> sync_switch_observer_;
180  std::shared_ptr<CommandQueue> command_queue_ip_;
181 #ifdef IMPELLER_DEBUG
182  std::shared_ptr<GPUTracerMTL> gpu_tracer_;
183  std::shared_ptr<ImpellerMetalCaptureManager> capture_manager_;
184 #endif // IMPELLER_DEBUG
185  bool is_valid_ = false;
186 
187  ContextMTL(const Flags& flags,
188  id<MTLDevice> device,
189  id<MTLCommandQueue> command_queue,
190  NSArray<id<MTLLibrary>>* shader_libraries,
191  std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch,
192  std::optional<PixelFormat> pixel_format_override = std::nullopt);
193 
194  std::shared_ptr<CommandBuffer> CreateCommandBufferInQueue(
195  id<MTLCommandQueue> queue) const;
196 
197  ContextMTL(const ContextMTL&) = delete;
198 
199  ContextMTL& operator=(const ContextMTL&) = delete;
200 };
201 
202 } // namespace impeller
203 
204 #endif // FLUTTER_IMPELLER_RENDERER_BACKEND_METAL_CONTEXT_MTL_H_
To do anything rendering related with Impeller, you need a context.
Definition: context.h:65
std::shared_ptr< SamplerLibrary > GetSamplerLibrary() const override
Returns the library of combined image samplers used in shaders.
Definition: context_mtl.mm:320
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:325
id< MTLCommandBuffer > CreateMTLCommandBuffer(const std::string &label) const
Definition: context_mtl.mm:380
void SetCapabilities(const std::shared_ptr< const Capabilities > &capabilities)
Definition: context_mtl.mm:369
std::shared_ptr< PipelineLibrary > GetPipelineLibrary() const override
Returns the library of pipelines used by render or compute commands.
Definition: context_mtl.mm:315
std::shared_ptr< CommandQueue > GetCommandQueue() const override
Return the graphics queue for submitting command buffers.
Definition: context_mtl.mm:454
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:365
static std::shared_ptr< ContextMTL > Create(const Flags &flags, const std::vector< std::string > &shader_library_paths, std::shared_ptr< const fml::SyncSwitch > is_gpu_disabled_sync_switch)
Definition: context_mtl.mm:229
std::string DescribeGpuModel() const override
Definition: context_mtl.mm:300
RuntimeStageBackend GetRuntimeStageBackend() const override
Retrieve the runtime stage for this context type.
Definition: context_mtl.mm:459
~ContextMTL() override
Definition: context_mtl.mm:291
BackendType GetBackendType() const override
Get the graphics backend of an Impeller context.
Definition: context_mtl.mm:295
void Shutdown() override
Force all pending asynchronous work to finish. This is achieved by deleting all owned concurrent mess...
Definition: context_mtl.mm:330
void StoreTaskForGPU(const fml::closure &task, const fml::closure &failure) override
Definition: context_mtl.mm:389
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:310
bool UpdateOffscreenLayerPixelFormat(PixelFormat format) override
Definition: context_mtl.mm:375
std::shared_ptr< Allocator > GetResourceAllocator() const override
Returns the allocator used to create textures and buffers on the device.
Definition: context_mtl.mm:357
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:305
id< MTLDevice > GetMTLDevice() const
Definition: context_mtl.mm:361
std::shared_ptr< const fml::SyncSwitch > GetIsGpuDisabledSyncSwitch() const
Definition: context_mtl.mm:338
Creates and manages a Metal capture scope that supports frame capture when using the FlutterMetalLaye...
Definition: context_mtl.h:37
ImpellerMetalCaptureManager(id< MTLDevice > device)
Construct a new capture manager from the provided Metal device.
Definition: context_mtl.mm:470
void FinishCapture()
End the current capture scope.
Definition: context_mtl.mm:488
void StartCapture()
Begin a new capture scope, no-op if the scope has already started.
Definition: context_mtl.mm:480
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:99