| Flutter Impeller |

context_mtl.mm
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 #include "impeller/renderer/backend/metal/context_mtl.h"
6 #include <Metal/Metal.h>
7
8 #include <memory>
9
10 #include "flutter/fml/concurrent_message_loop.h"
11 #include "flutter/fml/file.h"
12 #include "flutter/fml/logging.h"
13 #include "flutter/fml/paths.h"
14 #include "flutter/fml/synchronization/sync_switch.h"
15 #include "impeller/core/formats.h"
16 #include "impeller/core/runtime_types.h"
17 #include "impeller/core/sampler_descriptor.h"
18 #include "impeller/renderer/backend/metal/gpu_tracer_mtl.h"
19 #include "impeller/renderer/backend/metal/sampler_library_mtl.h"
20 #include "impeller/renderer/capabilities.h"
21
22 namespace impeller {
23
24 static bool DeviceSupportsFramebufferFetch(id<MTLDevice> device) {
25 // The iOS simulator lies about supporting framebuffer fetch.
26 #if FML_OS_IOS_SIMULATOR
27 return false;
28 #else // FML_OS_IOS_SIMULATOR
29
30 if (@available(macOS 10.15, iOS 13, tvOS 13, *)) {
31 return [device supportsFamily:MTLGPUFamilyApple2];
32 }
33 // According to
34 // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf , Apple2
35 // corresponds to iOS GPU family 2, which supports A8 devices.
36 #if FML_OS_IOS
37 return [device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v1];
38 #else
39 return false;
40 #endif // FML_OS_IOS
41 #endif // FML_OS_IOS_SIMULATOR
42 }
43
44 static bool DeviceSupportsComputeSubgroups(id<MTLDevice> device) {
45 bool supports_subgroups = false;
46 // Refer to the "SIMD-scoped reduction operations" feature in the table
47 // below: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
48 if (@available(ios 13.0, tvos 13.0, macos 10.15, *)) {
49 supports_subgroups = [device supportsFamily:MTLGPUFamilyApple7] ||
50 [device supportsFamily:MTLGPUFamilyMac2];
51 }
52 return supports_subgroups;
53 }
54
55 // See "Extended Range and wide color pixel formats" in the metal feature set
56 // tables.
57 static bool DeviceSupportsExtendedRangeFormats(id<MTLDevice> device) {
58 if (@available(macOS 10.15, iOS 13, tvOS 13, *)) {
59 return [device supportsFamily:MTLGPUFamilyApple3];
60 }
61 return false;
62 }
63
64 static std::unique_ptr<Capabilities> InferMetalCapabilities(
65 id<MTLDevice> device,
66 PixelFormat color_format) {
67 return CapabilitiesBuilder()
68 .SetSupportsOffscreenMSAA(true)
69 .SetSupportsSSBO(true)
70 .SetSupportsTextureToTextureBlits(true)
71 .SetSupportsDecalSamplerAddressMode(true)
72 .SetSupportsFramebufferFetch(DeviceSupportsFramebufferFetch(device))
73 .SetDefaultColorFormat(color_format)
74 .SetDefaultStencilFormat(PixelFormat::kS8UInt)
75 .SetDefaultDepthStencilFormat(PixelFormat::kD32FloatS8UInt)
76 .SetSupportsCompute(true)
77 .SetSupportsComputeSubgroups(DeviceSupportsComputeSubgroups(device))
78 .SetSupportsReadFromResolve(true)
79 .SetSupportsDeviceTransientTextures(true)
80 .SetDefaultGlyphAtlasFormat(PixelFormat::kA8UNormInt)
81 .SetSupportsTriangleFan(false)
82 .SetMaximumRenderPassAttachmentSize(DeviceMaxTextureSizeSupported(device))
83 .SetSupportsExtendedRangeFormats(
84 DeviceSupportsExtendedRangeFormats(device))
85 .Build();
86 }
87
88 ContextMTL::ContextMTL(
89 const Flags& flags,
90 id<MTLDevice> device,
91 id<MTLCommandQueue> command_queue,
92 NSArray<id<MTLLibrary>>* shader_libraries,
93 std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch,
94 std::optional<PixelFormat> pixel_format_override)
95 : Context(flags),
96 device_(device),
97 command_queue_(command_queue),
98 is_gpu_disabled_sync_switch_(std::move(is_gpu_disabled_sync_switch)) {
99 // Validate device.
100 if (!device_) {
101 VALIDATION_LOG << "Could not set up valid Metal device.";
102 return;
103 }
104
105 sync_switch_observer_.reset(new SyncSwitchObserver(*this));
106 is_gpu_disabled_sync_switch_->AddObserver(sync_switch_observer_.get());
107
108 // Setup the shader library.
109 {
110 if (shader_libraries == nil) {
111 VALIDATION_LOG << "Shader libraries were null.";
112 return;
113 }
114
115 // std::make_shared disallowed because of private friend ctor.
116 auto library = std::shared_ptr<ShaderLibraryMTL>(
117 new ShaderLibraryMTL(shader_libraries));
118 if (!library->IsValid()) {
119 VALIDATION_LOG << "Could not create valid Metal shader library.";
120 return;
121 }
122 shader_library_ = std::move(library);
123 }
124
125 // Setup the pipeline library.
126 {
127 pipeline_library_ =
128 std::shared_ptr<PipelineLibraryMTL>(new PipelineLibraryMTL(device_));
129 }
130
131 // Setup the sampler library.
132 {
133 sampler_library_ =
134 std::shared_ptr<SamplerLibraryMTL>(new SamplerLibraryMTL(device_));
135 }
136
137 // Setup the resource allocator.
138 {
139 resource_allocator_ = std::shared_ptr<AllocatorMTL>(
140 new AllocatorMTL(device_, "Impeller Permanents Allocator"));
141 if (!resource_allocator_) {
142 VALIDATION_LOG << "Could not set up the resource allocator.";
143 return;
144 }
145 }
146
147 device_capabilities_ =
148 InferMetalCapabilities(device_, pixel_format_override.has_value()
149 ? pixel_format_override.value()
150 : PixelFormat::kB8G8R8A8UNormInt);
151 command_queue_ip_ = std::make_shared<CommandQueue>();
152 #ifdef IMPELLER_DEBUG
153 gpu_tracer_ = std::make_shared<GPUTracerMTL>();
154 capture_manager_ = std::make_shared<ImpellerMetalCaptureManager>(device_);
155 #endif // IMPELLER_DEBUG
156 is_valid_ = true;
157 }
158
159 static NSArray<id<MTLLibrary>>* MTLShaderLibraryFromFilePaths(
160 id<MTLDevice> device,
161 const std::vector<std::string>& libraries_paths) {
162 NSMutableArray<id<MTLLibrary>>* found_libraries = [NSMutableArray array];
163 for (const auto& library_path : libraries_paths) {
164 if (!fml::IsFile(library_path)) {
165 VALIDATION_LOG << "Shader library does not exist at path '"
166 << library_path << "'";
167 return nil;
168 }
169 NSError* shader_library_error = nil;
170 auto library = [device newLibraryWithFile:@(library_path.c_str())
171 error:&shader_library_error];
172 if (!library) {
173 FML_LOG(ERROR) << "Could not create shader library: "
174 << shader_library_error.localizedDescription.UTF8String;
175 return nil;
176 }
177 [found_libraries addObject:library];
178 }
179 return found_libraries;
180 }
181
182 static NSArray<id<MTLLibrary>>* MTLShaderLibraryFromFileData(
183 id<MTLDevice> device,
184 const std::vector<std::shared_ptr<fml::Mapping>>& libraries_data,
185 const std::string& label) {
186 NSMutableArray<id<MTLLibrary>>* found_libraries = [NSMutableArray array];
187 for (const auto& library_data : libraries_data) {
188 if (library_data == nullptr) {
189 FML_LOG(ERROR) << "Shader library data was null.";
190 return nil;
191 }
192
193 __block auto data = library_data;
194
195 auto dispatch_data =
196 ::dispatch_data_create(library_data->GetMapping(), // buffer
197 library_data->GetSize(), // size
198 dispatch_get_main_queue(), // queue
199 ^() {
200 // We just need a reference.
201 data.reset();
202 } // destructor
203 );
204 if (!dispatch_data) {
205 FML_LOG(ERROR) << "Could not wrap shader data in dispatch data.";
206 return nil;
207 }
208
209 NSError* shader_library_error = nil;
210 auto library = [device newLibraryWithData:dispatch_data
211 error:&shader_library_error];
212 if (!library) {
213 FML_LOG(ERROR) << "Could not create shader library: "
214 << shader_library_error.localizedDescription.UTF8String;
215 return nil;
216 }
217 if (!label.empty()) {
218 library.label = @(label.c_str());
219 }
220 [found_libraries addObject:library];
221 }
222 return found_libraries;
223 }
224
225 static id<MTLDevice> CreateMetalDevice() {
226 return ::MTLCreateSystemDefaultDevice();
227 }
228
229 static id<MTLCommandQueue> CreateMetalCommandQueue(id<MTLDevice> device) {
230 auto command_queue = device.newCommandQueue;
231 if (!command_queue) {
232 VALIDATION_LOG << "Could not set up the command queue.";
233 return nullptr;
234 }
235 command_queue.label = @"Impeller Command Queue";
236 return command_queue;
237 }
238
239 std::shared_ptr<ContextMTL> ContextMTL::Create(
240 const Flags& flags,
241 const std::vector<std::string>& shader_library_paths,
242 std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch) {
243 auto device = CreateMetalDevice();
244 auto command_queue = CreateMetalCommandQueue(device);
245 if (!command_queue) {
246 return nullptr;
247 }
248 auto context = std::shared_ptr<ContextMTL>(new ContextMTL(
249 flags, device, command_queue,
250 MTLShaderLibraryFromFilePaths(device, shader_library_paths),
251 std::move(is_gpu_disabled_sync_switch)));
252 if (!context->IsValid()) {
253 FML_LOG(ERROR) << "Could not create Metal context.";
254 return nullptr;
255 }
256 return context;
257 }
258
259 std::shared_ptr<ContextMTL> ContextMTL::Create(
260 const Flags& flags,
261 const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries_data,
262 std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch,
263 const std::string& library_label,
264 std::optional<PixelFormat> pixel_format_override) {
265 auto device = CreateMetalDevice();
266 auto command_queue = CreateMetalCommandQueue(device);
267 if (!command_queue) {
268 return nullptr;
269 }
270 auto context = std::shared_ptr<ContextMTL>(new ContextMTL(
271 flags, device, command_queue,
272 MTLShaderLibraryFromFileData(device, shader_libraries_data,
273 library_label),
274 std::move(is_gpu_disabled_sync_switch), pixel_format_override));
275 if (!context->IsValid()) {
276 FML_LOG(ERROR) << "Could not create Metal context.";
277 return nullptr;
278 }
279 return context;
280 }
281
282 std::shared_ptr<ContextMTL> ContextMTL::Create(
283 const Flags& flags,
284 id<MTLDevice> device,
285 id<MTLCommandQueue> command_queue,
286 const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries_data,
287 std::shared_ptr<const fml::SyncSwitch> is_gpu_disabled_sync_switch,
288 const std::string& library_label) {
289 auto context = std::shared_ptr<ContextMTL>(
290 new ContextMTL(flags, device, command_queue,
291 MTLShaderLibraryFromFileData(device, shader_libraries_data,
292 library_label),
293 std::move(is_gpu_disabled_sync_switch)));
294 if (!context->IsValid()) {
295 FML_LOG(ERROR) << "Could not create Metal context.";
296 return nullptr;
297 }
298 return context;
299 }
300
301 ContextMTL::~ContextMTL() {
302 is_gpu_disabled_sync_switch_->RemoveObserver(sync_switch_observer_.get());
303 }
304
305 Context::BackendType ContextMTL::GetBackendType() const {
306 return Context::BackendType::kMetal;
307 }
308
309 // |Context|
310 std::string ContextMTL::DescribeGpuModel() const {
311 return std::string([[device_ name] UTF8String]);
312 }
313
314 // |Context|
315 bool ContextMTL::IsValid() const {
316 return is_valid_;
317 }
318
319 // |Context|
320 std::shared_ptr<ShaderLibrary> ContextMTL::GetShaderLibrary() const {
321 return shader_library_;
322 }
323
324 // |Context|
325 std::shared_ptr<PipelineLibrary> ContextMTL::GetPipelineLibrary() const {
326 return pipeline_library_;
327 }
328
329 // |Context|
330 std::shared_ptr<SamplerLibrary> ContextMTL::GetSamplerLibrary() const {
331 return sampler_library_;
332 }
333
334 // |Context|
335 std::shared_ptr<CommandBuffer> ContextMTL::CreateCommandBuffer() const {
336 return CreateCommandBufferInQueue(command_queue_);
337 }
338
339 // |Context|
340 void ContextMTL::Shutdown() {}
341
342 #ifdef IMPELLER_DEBUG
343 std::shared_ptr<GPUTracerMTL> ContextMTL::GetGPUTracer() const {
344 return gpu_tracer_;
345 }
346 #endif // IMPELLER_DEBUG
347
348 std::shared_ptr<const fml::SyncSwitch> ContextMTL::GetIsGpuDisabledSyncSwitch()
349 const {
350 return is_gpu_disabled_sync_switch_;
351 }
352
353 std::shared_ptr<CommandBuffer> ContextMTL::CreateCommandBufferInQueue(
354 id<MTLCommandQueue> queue) const {
355 if (!IsValid()) {
356 return nullptr;
357 }
358
359 auto buffer = std::shared_ptr<CommandBufferMTL>(
360 new CommandBufferMTL(weak_from_this(), device_, queue));
361 if (!buffer->IsValid()) {
362 return nullptr;
363 }
364 return buffer;
365 }
366
367 std::shared_ptr<Allocator> ContextMTL::GetResourceAllocator() const {
368 return resource_allocator_;
369 }
370
371 id<MTLDevice> ContextMTL::GetMTLDevice() const {
372 return device_;
373 }
374
375 const std::shared_ptr<const Capabilities>& ContextMTL::GetCapabilities() const {
376 return device_capabilities_;
377 }
378
379 void ContextMTL::SetCapabilities(
380 const std::shared_ptr<const Capabilities>& capabilities) {
381 device_capabilities_ = capabilities;
382 }
383
384 // |Context|
385 bool ContextMTL::UpdateOffscreenLayerPixelFormat(PixelFormat format) {
386 device_capabilities_ = InferMetalCapabilities(device_, format);
387 return true;
388 }
389
390 id<MTLCommandBuffer> ContextMTL::CreateMTLCommandBuffer(
391 const std::string& label) const {
392 auto buffer = [command_queue_ commandBuffer];
393 if (!label.empty()) {
394 [buffer setLabel:@(label.data())];
395 }
396 return buffer;
397 }
398
399 void ContextMTL::StoreTaskForGPU(const fml::closure& task,
400 const fml::closure& failure) {
401 std::vector<PendingTasks> failed_tasks;
402 {
403 Lock lock(tasks_awaiting_gpu_mutex_);
404 tasks_awaiting_gpu_.push_back(PendingTasks{task, failure});
405 int32_t failed_task_count =
406 tasks_awaiting_gpu_.size() - kMaxTasksAwaitingGPU;
407 if (failed_task_count > 0) {
408 failed_tasks.reserve(failed_task_count);
409 failed_tasks.insert(failed_tasks.end(),
410 std::make_move_iterator(tasks_awaiting_gpu_.begin()),
411 std::make_move_iterator(tasks_awaiting_gpu_.begin() +
412 failed_task_count));
413 tasks_awaiting_gpu_.erase(
414 tasks_awaiting_gpu_.begin(),
415 tasks_awaiting_gpu_.begin() + failed_task_count);
416 }
417 }
418 for (const PendingTasks& task : failed_tasks) {
419 if (task.failure) {
420 task.failure();
421 }
422 }
423 }
424
425 void ContextMTL::FlushTasksAwaitingGPU() {
426 std::deque<PendingTasks> tasks_awaiting_gpu;
427 {
428 Lock lock(tasks_awaiting_gpu_mutex_);
429 std::swap(tasks_awaiting_gpu, tasks_awaiting_gpu_);
430 }
431 for (const auto& task : tasks_awaiting_gpu) {
432 task.task();
433 }
434 }
435
436 ContextMTL::SyncSwitchObserver::SyncSwitchObserver(ContextMTL& parent)
437 : parent_(parent) {}
438
439 void ContextMTL::SyncSwitchObserver::OnSyncSwitchUpdate(bool new_is_disabled) {
440 if (!new_is_disabled) {
441 parent_.FlushTasksAwaitingGPU();
442 }
443 }
444
445 // |Context|
446 std::shared_ptr<CommandQueue> ContextMTL::GetCommandQueue() const {
447 return command_queue_ip_;
448 }
449
450 // |Context|
451 RuntimeStageBackend ContextMTL::GetRuntimeStageBackend() const {
452 return RuntimeStageBackend::kMetal;
453 }
454
455 #ifdef IMPELLER_DEBUG
456 const std::shared_ptr<ImpellerMetalCaptureManager>
457 ContextMTL::GetCaptureManager() const {
458 return capture_manager_;
459 }
460 #endif // IMPELLER_DEBUG
461
462 ImpellerMetalCaptureManager::ImpellerMetalCaptureManager(id<MTLDevice> device) {
463 current_capture_scope_ = [[MTLCaptureManager sharedCaptureManager]
464 newCaptureScopeWithDevice:device];
465 [current_capture_scope_ setLabel:@"Impeller Frame"];
466 }
467
468 bool ImpellerMetalCaptureManager::CaptureScopeActive() const {
469 return scope_active_;
470 }
471
472 void ImpellerMetalCaptureManager::StartCapture() {
473 if (scope_active_) {
474 return;
475 }
476 scope_active_ = true;
477 [current_capture_scope_ beginScope];
478 }
479
480 void ImpellerMetalCaptureManager::FinishCapture() {
481 FML_DCHECK(scope_active_);
482 [current_capture_scope_ endScope];
483 scope_active_ = false;
484 }
485
486 } // namespace impeller
capabilities.h
impeller::CapabilitiesBuilder
Definition: capabilities.h:134
impeller::CapabilitiesBuilder::SetDefaultColorFormat
CapabilitiesBuilder & SetDefaultColorFormat(PixelFormat value)
Definition: capabilities.cc:196
impeller::CapabilitiesBuilder::SetSupportsComputeSubgroups
CapabilitiesBuilder & SetSupportsComputeSubgroups(bool value)
Definition: capabilities.cc:190
impeller::CapabilitiesBuilder::SetSupportsTextureToTextureBlits
CapabilitiesBuilder & SetSupportsTextureToTextureBlits(bool value)
Definition: capabilities.cc:173
impeller::CapabilitiesBuilder::SetDefaultStencilFormat
CapabilitiesBuilder & SetDefaultStencilFormat(PixelFormat value)
Definition: capabilities.cc:202
impeller::CapabilitiesBuilder::SetSupportsDeviceTransientTextures
CapabilitiesBuilder & SetSupportsDeviceTransientTextures(bool value)
Definition: capabilities.cc:226
impeller::CapabilitiesBuilder::SetSupportsTriangleFan
CapabilitiesBuilder & SetSupportsTriangleFan(bool value)
Definition: capabilities.cc:238
impeller::CapabilitiesBuilder::SetSupportsFramebufferFetch
CapabilitiesBuilder & SetSupportsFramebufferFetch(bool value)
Definition: capabilities.cc:179
impeller::CapabilitiesBuilder::SetSupportsDecalSamplerAddressMode
CapabilitiesBuilder & SetSupportsDecalSamplerAddressMode(bool value)
Definition: capabilities.cc:220
impeller::CapabilitiesBuilder::SetSupportsOffscreenMSAA
CapabilitiesBuilder & SetSupportsOffscreenMSAA(bool value)
Definition: capabilities.cc:163
impeller::CapabilitiesBuilder::SetSupportsSSBO
CapabilitiesBuilder & SetSupportsSSBO(bool value)
Definition: capabilities.cc:168
impeller::CapabilitiesBuilder::SetMaximumRenderPassAttachmentSize
CapabilitiesBuilder & SetMaximumRenderPassAttachmentSize(ISize size)
Definition: capabilities.cc:243
impeller::CapabilitiesBuilder::SetSupportsExtendedRangeFormats
CapabilitiesBuilder & SetSupportsExtendedRangeFormats(bool value)
Definition: capabilities.cc:249
impeller::CapabilitiesBuilder::SetDefaultGlyphAtlasFormat
CapabilitiesBuilder & SetDefaultGlyphAtlasFormat(PixelFormat value)
Definition: capabilities.cc:232
impeller::CapabilitiesBuilder::SetSupportsCompute
CapabilitiesBuilder & SetSupportsCompute(bool value)
Definition: capabilities.cc:185
impeller::CapabilitiesBuilder::Build
std::unique_ptr< Capabilities > Build()
Definition: capabilities.cc:255
impeller::CapabilitiesBuilder::SetDefaultDepthStencilFormat
CapabilitiesBuilder & SetDefaultDepthStencilFormat(PixelFormat value)
Definition: capabilities.cc:208
impeller::CapabilitiesBuilder::SetSupportsReadFromResolve
CapabilitiesBuilder & SetSupportsReadFromResolve(bool value)
Definition: capabilities.cc:214
impeller::Context::BackendType
BackendType
Definition: context.h:49
impeller::ContextMTL
Definition: context_mtl.h:67
impeller::ContextMTL::GetCommandQueue
std::shared_ptr< CommandQueue > GetCommandQueue() const override
Return the graphics queue for submitting command buffers.
Definition: context_mtl.mm:446
impeller::ContextMTL::GetRuntimeStageBackend
RuntimeStageBackend GetRuntimeStageBackend() const override
Retrieve the runtime stage for this context type.
Definition: context_mtl.mm:451
impeller::ImpellerMetalCaptureManager::ImpellerMetalCaptureManager
ImpellerMetalCaptureManager(id< MTLDevice > device)
Construct a new capture manager from the provided Metal device.
Definition: context_mtl.mm:462
impeller::ImpellerMetalCaptureManager::FinishCapture
void FinishCapture()
End the current capture scope.
Definition: context_mtl.mm:480
impeller::ImpellerMetalCaptureManager::CaptureScopeActive
bool CaptureScopeActive() const
Definition: context_mtl.mm:468
impeller::ImpellerMetalCaptureManager::StartCapture
void StartCapture()
Begin a new capture scope, no-op if the scope has already started.
Definition: context_mtl.mm:472
impeller::Lock
Definition: thread.h:72
formats.h
gpu_tracer_mtl.h
impeller::interop::Create
ScopedObject< Object > Create(CtorArgs &&... args)
Definition: object.h:161
impeller
Definition: allocation.cc:12
impeller::DeviceSupportsExtendedRangeFormats
static bool DeviceSupportsExtendedRangeFormats(id< MTLDevice > device)
Definition: context_mtl.mm:57
impeller::RuntimeStageBackend
RuntimeStageBackend
Definition: runtime_types.h:16
impeller::RuntimeStageBackend::kMetal
@ kMetal
impeller::MTLShaderLibraryFromFileData
static NSArray< id< MTLLibrary > > * MTLShaderLibraryFromFileData(id< MTLDevice > device, const std::vector< std::shared_ptr< fml::Mapping >> &libraries_data, const std::string &label)
Definition: context_mtl.mm:182
impeller::CreateMetalDevice
static id< MTLDevice > CreateMetalDevice()
Definition: context_mtl.mm:225
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:99
impeller::PixelFormat::kA8UNormInt
@ kA8UNormInt
impeller::PixelFormat::kB8G8R8A8UNormInt
@ kB8G8R8A8UNormInt
impeller::PixelFormat::kS8UInt
@ kS8UInt
impeller::PixelFormat::kD32FloatS8UInt
@ kD32FloatS8UInt
impeller::DeviceMaxTextureSizeSupported
ISize DeviceMaxTextureSizeSupported(id< MTLDevice > device)
Definition: allocator_mtl.mm:55
impeller::CreateCommandBuffer
static id< MTLCommandBuffer > CreateCommandBuffer(id< MTLCommandQueue > queue)
Definition: command_buffer_mtl.mm:117
impeller::MTLShaderLibraryFromFilePaths
static NSArray< id< MTLLibrary > > * MTLShaderLibraryFromFilePaths(id< MTLDevice > device, const std::vector< std::string > &libraries_paths)
Definition: context_mtl.mm:159
impeller::CreateMetalCommandQueue
static id< MTLCommandQueue > CreateMetalCommandQueue(id< MTLDevice > device)
Definition: context_mtl.mm:229
impeller::InferMetalCapabilities
static std::unique_ptr< Capabilities > InferMetalCapabilities(id< MTLDevice > device, PixelFormat color_format)
Definition: context_mtl.mm:64
impeller::DeviceSupportsComputeSubgroups
static bool DeviceSupportsComputeSubgroups(id< MTLDevice > device)
Definition: context_mtl.mm:44
impeller::DeviceSupportsFramebufferFetch
static bool DeviceSupportsFramebufferFetch(id< MTLDevice > device)
Definition: context_mtl.mm:24
std
Definition: comparable.h:95
context_mtl.h
runtime_types.h
sampler_descriptor.h
sampler_library_mtl.h
impeller::Flags
Definition: flags.h:9
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:67
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:91