Flutter Engine
The Flutter Engine
shader_library_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
6
7#include "flutter/fml/closure.h"
10
11namespace impeller {
12
13ShaderLibraryMTL::ShaderLibraryMTL(NSArray<id<MTLLibrary>>* libraries)
14 : libraries_([libraries mutableCopy]) {
15 if (libraries_ == nil || libraries_.count == 0) {
16 return;
17 }
18
19 is_valid_ = true;
20}
21
22ShaderLibraryMTL::~ShaderLibraryMTL() = default;
23
24bool ShaderLibraryMTL::IsValid() const {
25 return is_valid_;
26}
27
28static MTLFunctionType ToMTLFunctionType(ShaderStage stage) {
29 switch (stage) {
30 case ShaderStage::kVertex:
31 return MTLFunctionTypeVertex;
32 case ShaderStage::kFragment:
33 return MTLFunctionTypeFragment;
35 case ShaderStage::kCompute:
36 return MTLFunctionTypeKernel;
37 }
39}
40
41std::shared_ptr<const ShaderFunction> ShaderLibraryMTL::GetFunction(
42 std::string_view name,
43 ShaderStage stage) {
44 if (!IsValid()) {
45 return nullptr;
46 }
47
48 if (name.empty()) {
49 VALIDATION_LOG << "Library function name was empty.";
50 return nullptr;
51 }
52
53 ShaderKey key(name, stage);
54
55 id<MTLFunction> function = nil;
56 id<MTLLibrary> library = nil;
57
58 {
59 ReaderLock lock(libraries_mutex_);
60
61 if (auto found = functions_.find(key); found != functions_.end()) {
62 return found->second;
63 }
64
65 for (size_t i = 0, count = [libraries_ count]; i < count; i++) {
66 library = libraries_[i];
67 function = [library newFunctionWithName:@(name.data())];
68 if (function) {
69 break;
70 }
71 }
72
73 if (function == nil) {
74 return nullptr;
75 }
76
77 if (function.functionType != ToMTLFunctionType(stage)) {
78 VALIDATION_LOG << "Library function named " << name
79 << " was for an unexpected shader stage.";
80 return nullptr;
81 }
82
83 auto func = std::shared_ptr<ShaderFunctionMTL>(new ShaderFunctionMTL(
84 library_id_, function, library, {name.data(), name.size()}, stage));
85 functions_[key] = func;
86
87 return func;
88 }
89}
90
91id<MTLDevice> ShaderLibraryMTL::GetDevice() const {
92 ReaderLock lock(libraries_mutex_);
93 if (libraries_.count > 0u) {
94 return libraries_[0].device;
95 }
96 return nil;
97}
98
99// |ShaderLibrary|
100void ShaderLibraryMTL::RegisterFunction(std::string name, // unused
101 ShaderStage stage, // unused
102 std::shared_ptr<fml::Mapping> code,
103 RegistrationCallback callback) {
104 if (!callback) {
105 callback = [](auto) {};
106 }
107 auto failure_callback = std::make_shared<fml::ScopedCleanupClosure>(
108 [callback]() { callback(false); });
109 if (!IsValid()) {
110 return;
111 }
112 if (code == nullptr || code->GetMapping() == nullptr) {
113 return;
114 }
115 auto device = GetDevice();
116 if (device == nil) {
117 return;
118 }
119
120 auto source = [[NSString alloc] initWithBytes:code->GetMapping()
121 length:code->GetSize()
122 encoding:NSUTF8StringEncoding];
123
124 auto weak_this = weak_from_this();
125 [device newLibraryWithSource:source
126 options:NULL
127 completionHandler:^(id<MTLLibrary> library, NSError* error) {
128 auto strong_this = weak_this.lock();
129 if (!strong_this) {
130 VALIDATION_LOG << "Shader library was collected before "
131 "dynamic shader stage could be registered.";
132 return;
133 }
134 if (!library) {
135 VALIDATION_LOG << "Could not register dynamic stage library: "
136 << error.localizedDescription.UTF8String;
137 return;
138 }
139 reinterpret_cast<ShaderLibraryMTL*>(strong_this.get())
140 ->RegisterLibrary(library);
141 failure_callback->Release();
142 callback(true);
143 }];
144}
145
146// |ShaderLibrary|
147void ShaderLibraryMTL::UnregisterFunction(std::string name, ShaderStage stage) {
148 ReaderLock lock(libraries_mutex_);
149
150 // Find the shader library containing this function name and remove it.
151
152 bool found_library = false;
153 for (size_t i = [libraries_ count] - 1; i >= 0; i--) {
154 id<MTLFunction> function =
155 [libraries_[i] newFunctionWithName:@(name.data())];
156 if (function) {
157 [libraries_ removeObjectAtIndex:i];
158 found_library = true;
159 break;
160 }
161 }
162 if (!found_library) {
163 VALIDATION_LOG << "Library containing function " << name
164 << " was not found, so it couldn't be unregistered.";
165 }
166
167 // Remove the shader from the function cache.
168
169 ShaderKey key(name, stage);
170
171 auto found = functions_.find(key);
172 if (found == functions_.end()) {
173 VALIDATION_LOG << "Library function named " << name
174 << " was not found, so it couldn't be unregistered.";
175 return;
176 }
177
178 functions_.erase(found);
179}
180
181void ShaderLibraryMTL::RegisterLibrary(id<MTLLibrary> library) {
182 WriterLock lock(libraries_mutex_);
183 [libraries_ addObject:library];
184}
185
186} // namespace impeller
const char * options
int count
Definition: FontMgrTest.cpp:50
VkDevice device
Definition: main.cc:53
SkBitmap source
Definition: examples.cpp:28
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
const uint8_t uint32_t uint32_t GError ** error
#define FML_UNREACHABLE()
Definition: logging.h:109
Dart_NativeFunction function
Definition: fuchsia.cc:51
size_t length
FunctionPtr GetFunction(const Library &lib, const char *name)
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
static MTLFunctionType ToMTLFunctionType(ShaderStage stage)
#define VALIDATION_LOG
Definition: validation.h:73