Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
#define SK_GUARDED_BY(x)
static constexpr GrColorFormatDesc MakeInvalid()
static constexpr GrColorFormatDesc MakeRGBA(int rgba, GrColorTypeEncoding e)
static constexpr GrColorFormatDesc MakeAlpha(int a, GrColorTypeEncoding e)
static constexpr GrColorFormatDesc MakeRG(int rg, GrColorTypeEncoding e)
static constexpr GrColorFormatDesc MakeRGB(int rgb, GrColorTypeEncoding e)
static constexpr GrColorFormatDesc MakeR(int r, GrColorTypeEncoding e)
id< MTLDevice > device() const
Definition GrMtlGpu.h:49
id< MTLTexture > colorMTLTexture() const
GrMtlAttachment * resolveAttachment() const
id< MTLTexture > mtlTexture() 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
#define TRACE_EVENT0(category_group, name)