Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
GrMtlUtil.mm
Go to the documentation of this file.
1/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
10#import <Metal/Metal.h>
11
21
22#if !__has_feature(objc_arc)
23#error This file must be compiled with Arc. Use -fobjc-arc flag
24#endif
25
26GR_NORETAIN_BEGIN
27
28NSError* GrCreateMtlError(NSString* description, GrMtlErrorCode errorCode) {
29 NSDictionary* userInfo = [NSDictionary dictionaryWithObject:description
30 forKey:NSLocalizedDescriptionKey];
31 return [NSError errorWithDomain:@"org.skia.ganesh"
32 code:(NSInteger)errorCode
33 userInfo:userInfo];
34}
35
36MTLTextureDescriptor* GrGetMTLTextureDescriptor(id<MTLTexture> mtlTexture) {
37 MTLTextureDescriptor* texDesc = [[MTLTextureDescriptor alloc] init];
38 texDesc.textureType = mtlTexture.textureType;
39 texDesc.pixelFormat = mtlTexture.pixelFormat;
40 texDesc.width = mtlTexture.width;
41 texDesc.height = mtlTexture.height;
42 texDesc.depth = mtlTexture.depth;
43 texDesc.mipmapLevelCount = mtlTexture.mipmapLevelCount;
44 texDesc.arrayLength = mtlTexture.arrayLength;
45 texDesc.sampleCount = mtlTexture.sampleCount;
46 if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) {
47 texDesc.usage = mtlTexture.usage;
48 }
49 return texDesc;
50}
51
52id<MTLLibrary> GrCompileMtlShaderLibrary(const GrMtlGpu* gpu,
53 const std::string& msl,
55 TRACE_EVENT0("skia.shaders", "driver_compile_shader");
56 NSString* nsSource = [[NSString alloc] initWithBytesNoCopy:const_cast<char*>(msl.c_str())
57 length:msl.size()
58 encoding:NSUTF8StringEncoding
59 freeWhenDone:NO];
60 if (!nsSource) {
61 return nil;
62 }
63 MTLCompileOptions* options = [[MTLCompileOptions alloc] init];
64 // array<> is supported in MSL 2.0 on MacOS 10.13+ and iOS 11+,
65 // and in MSL 1.2 on iOS 10+ (but not MacOS).
66 if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
67 options.languageVersion = MTLLanguageVersion2_0;
68#if defined(SK_BUILD_FOR_IOS)
69 } else if (@available(macOS 10.12, iOS 10.0, tvOS 10.0, *)) {
70 options.languageVersion = MTLLanguageVersion1_2;
71#endif
72 }
73 options.fastMathEnabled = YES;
74
75 NSError* error = nil;
76 id<MTLLibrary> compiledLibrary;
77 if (@available(macOS 10.15, *)) {
78 compiledLibrary = [gpu->device() newLibraryWithSource:(NSString* _Nonnull)nsSource
80 error:&error];
81 } else {
82 compiledLibrary = GrMtlNewLibraryWithSource(gpu->device(), (NSString* _Nonnull)nsSource,
83 options, &error);
84 }
85 if (!compiledLibrary) {
86 errorHandler->compileError(
87 msl.c_str(), error.debugDescription.UTF8String, /*shaderWasCached=*/false);
88 return nil;
89 }
90
91 return compiledLibrary;
92}
93
95 const std::string& msl) {
96 NSString* nsSource = [[NSString alloc] initWithBytesNoCopy:const_cast<char*>(msl.c_str())
97 length:msl.size()
98 encoding:NSUTF8StringEncoding
99 freeWhenDone:NO];
100 if (!nsSource) {
101 return;
102 }
103 // Do nothing after completion for now.
104 // TODO: cache the result somewhere so we can use it later.
105 MTLNewLibraryCompletionHandler completionHandler = ^(id<MTLLibrary> library, NSError* error) {};
106 [gpu->device() newLibraryWithSource:(NSString* _Nonnull)nsSource
107 options:nil
108 completionHandler:completionHandler];
109}
110
111// Wrapper to get atomic assignment for compiles and pipeline creation
113public:
114 MtlCompileResult() : fCompiledObject(nil), fError(nil) {}
115 void set(id compiledObject, NSError* error) {
116 SkAutoMutexExclusive automutex(fMutex);
117 fCompiledObject = compiledObject;
118 fError = error;
119 }
120 std::pair<id, NSError*> get() {
121 SkAutoMutexExclusive automutex(fMutex);
122 return std::make_pair(fCompiledObject, fError);
123 }
124private:
125 SkMutex fMutex;
126 id fCompiledObject SK_GUARDED_BY(fMutex);
127 NSError* fError SK_GUARDED_BY(fMutex);
128};
129
130id<MTLLibrary> GrMtlNewLibraryWithSource(id<MTLDevice> device, NSString* mslCode,
131 MTLCompileOptions* options, NSError** error) {
132 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
133 sk_sp<MtlCompileResult> compileResult(new MtlCompileResult);
134 // We have to increment the ref for the Obj-C block manually because it won't do it for us
135 compileResult->ref();
136 MTLNewLibraryCompletionHandler completionHandler =
137 ^(id<MTLLibrary> library, NSError* compileError) {
138 compileResult->set(library, compileError);
139 dispatch_semaphore_signal(semaphore);
140 compileResult->unref();
141 };
142
143 [device newLibraryWithSource: mslCode
145 completionHandler: completionHandler];
146
147 // Wait 1 second for the compiler
148 constexpr auto kTimeoutNS = 1000000000UL;
149 if (dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, kTimeoutNS))) {
150 if (error) {
151 constexpr auto kTimeoutMS = kTimeoutNS/1000000UL;
152 NSString* description =
153 [NSString stringWithFormat:@"Compilation took longer than %lu ms",
154 kTimeoutMS];
156 }
157 return nil;
158 }
159
160 id<MTLLibrary> compiledLibrary;
161 std::tie(compiledLibrary, *error) = compileResult->get();
162
163 return compiledLibrary;
164}
165
167 id<MTLDevice> device, MTLRenderPipelineDescriptor* pipelineDescriptor, NSError** error) {
168 dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
169 sk_sp<MtlCompileResult> compileResult(new MtlCompileResult);
170 // We have to increment the ref for the Obj-C block manually because it won't do it for us
171 compileResult->ref();
172 MTLNewRenderPipelineStateCompletionHandler completionHandler =
173 ^(id<MTLRenderPipelineState> state, NSError* compileError) {
174 compileResult->set(state, compileError);
175 dispatch_semaphore_signal(semaphore);
176 compileResult->unref();
177 };
178
179 [device newRenderPipelineStateWithDescriptor: pipelineDescriptor
180 completionHandler: completionHandler];
181
182 // Wait 1 second for pipeline creation
183 constexpr auto kTimeoutNS = 1000000000UL;
184 if (dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, kTimeoutNS))) {
185 if (error) {
186 constexpr auto kTimeoutMS = kTimeoutNS/1000000UL;
187 NSString* description =
188 [NSString stringWithFormat:@"Pipeline creation took longer than %lu ms",
189 kTimeoutMS];
191 }
192 return nil;
193 }
194
195 id<MTLRenderPipelineState> pipelineState;
196 std::tie(pipelineState, *error) = compileResult->get();
197
198 return pipelineState;
199}
200
202 id<MTLTexture> mtlTexture = nil;
203
204 GrMtlRenderTarget* renderTarget = static_cast<GrMtlRenderTarget*>(surface->asRenderTarget());
206 if (renderTarget) {
207 // We should not be using this for multisampled rendertargets with a separate resolve
208 // texture.
209 if (renderTarget->resolveAttachment()) {
210 SkASSERT(renderTarget->numSamples() > 1);
211 SkASSERT(false);
212 return nil;
213 }
214 mtlTexture = renderTarget->colorMTLTexture();
215 } else {
216 texture = static_cast<GrMtlTexture*>(surface->asTexture());
217 if (texture) {
218 mtlTexture = texture->mtlTexture();
219 }
220 }
221 return mtlTexture;
222}
223
224
225//////////////////////////////////////////////////////////////////////////////
226// CPP Utils
227
229 id<MTLTexture> GR_NORETAIN mtlTexture = GrGetMTLTexture(info.fTexture.get());
230 return static_cast<GrMTLPixelFormat>(mtlTexture.pixelFormat);
231}
232
233GrColorFormatDesc GrMtlFormatDesc(MTLPixelFormat mtlFormat) {
234 switch (mtlFormat) {
235 case MTLPixelFormatRGBA8Unorm:
237 case MTLPixelFormatR8Unorm:
239 case MTLPixelFormatA8Unorm:
241 case MTLPixelFormatBGRA8Unorm:
243 case MTLPixelFormatB5G6R5Unorm:
245 case MTLPixelFormatRGBA16Float:
247 case MTLPixelFormatR16Float:
249 case MTLPixelFormatRG8Unorm:
251 case MTLPixelFormatRGB10A2Unorm:
253 case MTLPixelFormatBGR10A2Unorm:
255 case MTLPixelFormatABGR4Unorm:
257 case MTLPixelFormatRGBA8Unorm_sRGB:
259 case MTLPixelFormatR16Unorm:
261 case MTLPixelFormatRG16Unorm:
263 case MTLPixelFormatRGBA16Unorm:
265 case MTLPixelFormatRG16Float:
267
268 // Compressed texture formats are not expected to have a description.
269 case MTLPixelFormatETC2_RGB8: return GrColorFormatDesc::MakeInvalid();
270#ifdef SK_BUILD_FOR_MAC
271 case MTLPixelFormatBC1_RGBA: return GrColorFormatDesc::MakeInvalid();
272#endif
273
274 // This type only describes color channels.
275 case MTLPixelFormatStencil8: return GrColorFormatDesc::MakeInvalid();
276
277 default:
279 }
280}
281
283 switch (format) {
284 case MTLPixelFormatETC2_RGB8: return SkTextureCompressionType::kETC2_RGB8_UNORM;
285#ifdef SK_BUILD_FOR_MAC
286 case MTLPixelFormatBC1_RGBA: return SkTextureCompressionType::kBC1_RGBA8_UNORM;
287#endif
288 default: return SkTextureCompressionType::kNone;
289 }
290
292}
293
294int GrMtlTextureInfoSampleCount(const GrMtlTextureInfo& info) {
295 id<MTLTexture> texture = GrGetMTLTexture(info.fTexture.get());
296 if (!texture) {
297 return 0;
298 }
299 return texture.sampleCount;
300}
301
302int GrMtlFormatStencilBits(MTLPixelFormat format) {
303 switch (format) {
304 case MTLPixelFormatStencil8:
305 return 8;
306 default:
307 return 0;
308 }
309}
310
311#if defined(SK_DEBUG) || defined(GR_TEST_UTILS)
312bool GrMtlFormatIsBGRA8(GrMTLPixelFormat mtlFormat) {
313 return mtlFormat == MTLPixelFormatBGRA8Unorm;
314}
315#endif
316
317GR_NORETAIN_END
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
unsigned int GrMTLPixelFormat
Definition: GrMtlTypes.h:17
GrMtlErrorCode
Definition: GrMtlUtil.h:63
GR_NORETAIN_BEGIN SK_ALWAYS_INLINE id< MTLTexture > GrGetMTLTexture(const void *mtlTexture)
Definition: GrMtlUtil.h:36
int GrMtlFormatStencilBits(MTLPixelFormat format)
Definition: GrMtlUtil.mm:302
MTLTextureDescriptor * GrGetMTLTextureDescriptor(id< MTLTexture > mtlTexture)
Definition: GrMtlUtil.mm:36
GR_NORETAIN_BEGIN NSError * GrCreateMtlError(NSString *description, GrMtlErrorCode errorCode)
Definition: GrMtlUtil.mm:28
void GrPrecompileMtlShaderLibrary(const GrMtlGpu *gpu, const std::string &msl)
Definition: GrMtlUtil.mm:94
id< MTLRenderPipelineState > GrMtlNewRenderPipelineStateWithDescriptor(id< MTLDevice > device, MTLRenderPipelineDescriptor *pipelineDescriptor, NSError **error)
Definition: GrMtlUtil.mm:166
SkTextureCompressionType GrMtlFormatToCompressionType(MTLPixelFormat format)
Definition: GrMtlUtil.mm:282
GrMTLPixelFormat GrGetMTLPixelFormatFromMtlTextureInfo(const GrMtlTextureInfo &info)
Definition: GrMtlUtil.mm:228
id< MTLLibrary > GrMtlNewLibraryWithSource(id< MTLDevice > device, NSString *mslCode, MTLCompileOptions *options, NSError **error)
Definition: GrMtlUtil.mm:130
int GrMtlTextureInfoSampleCount(const GrMtlTextureInfo &info)
Definition: GrMtlUtil.mm:294
GrColorFormatDesc GrMtlFormatDesc(MTLPixelFormat mtlFormat)
Definition: GrMtlUtil.mm:233
id< MTLTexture > GrGetMTLTextureFromSurface(GrSurface *surface)
Definition: GrMtlUtil.mm:201
id< MTLLibrary > GrCompileMtlShaderLibrary(const GrMtlGpu *gpu, const std::string &msl, GrContextOptions::ShaderErrorHandler *errorHandler)
Definition: GrMtlUtil.mm:52
#define SkUNREACHABLE
Definition: SkAssert.h:135
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkTextureCompressionType
static constexpr GrColorFormatDesc MakeInvalid()
Definition: GrTypesPriv.h:756
static constexpr GrColorFormatDesc MakeRGBA(int rgba, GrColorTypeEncoding e)
Definition: GrTypesPriv.h:720
static constexpr GrColorFormatDesc MakeAlpha(int a, GrColorTypeEncoding e)
Definition: GrTypesPriv.h:736
static constexpr GrColorFormatDesc MakeRG(int rg, GrColorTypeEncoding e)
Definition: GrTypesPriv.h:744
static constexpr GrColorFormatDesc MakeRGB(int rgb, GrColorTypeEncoding e)
Definition: GrTypesPriv.h:728
static constexpr GrColorFormatDesc MakeR(int r, GrColorTypeEncoding e)
Definition: GrTypesPriv.h:740
id< MTLDevice > device() const
Definition: GrMtlGpu.h:49
id< MTLTexture > colorMTLTexture() const
GrMtlAttachment * resolveAttachment() const
int numSamples() const
void set(id compiledObject, NSError *error)
Definition: GrMtlUtil.mm:115
std::pair< id, NSError * > get()
Definition: GrMtlUtil.mm:120
T * get() const
Definition: SkRefCnt.h:303
virtual void compileError(const char *shader, const char *errors)
VkDevice device
Definition: main.cc:53
VkSurfaceKHR surface
Definition: main.cc:49
AtkStateType state
const uint8_t uint32_t uint32_t GError ** error
uint32_t uint32_t * format
size_t length
FlTexture * texture
static bool init()
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131