blob: fbe12aeb22bb0c29caf8b90b7a0319992ee6e7a5 [file] [log] [blame]
Greg Daniel0576a452017-07-31 16:32:36 -04001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/mtl/GrMtlUtil.h"
Greg Daniel0576a452017-07-31 16:32:36 -04009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/gpu/GrSurface.h"
11#include "include/private/GrTypesPriv.h"
12#include "src/gpu/mtl/GrMtlGpu.h"
13#include "src/gpu/mtl/GrMtlRenderTarget.h"
14#include "src/gpu/mtl/GrMtlTexture.h"
15#include "src/sksl/SkSLCompiler.h"
Timothy Liange30739a2018-07-31 10:51:17 -040016
17#import <Metal/Metal.h>
18
Jim Van Verthcf23f582019-05-22 09:46:57 -040019#if !__has_feature(objc_arc)
20#error This file must be compiled with Arc. Use -fobjc-arc flag
21#endif
22
Timothy Liange30739a2018-07-31 10:51:17 -040023#define PRINT_MSL 0 // print out the MSL code generated
Greg Danielef59d872017-11-17 16:47:21 -050024
Greg Daniel0576a452017-07-31 16:32:36 -040025bool GrPixelConfigToMTLFormat(GrPixelConfig config, MTLPixelFormat* format) {
26 MTLPixelFormat dontCare;
27 if (!format) {
28 format = &dontCare;
29 }
30
31 switch (config) {
32 case kUnknown_GrPixelConfig:
33 return false;
34 case kRGBA_8888_GrPixelConfig:
35 *format = MTLPixelFormatRGBA8Unorm;
36 return true;
Brian Salomon5fba7ad2018-03-22 10:01:16 -040037 case kRGB_888_GrPixelConfig:
Jim Van Vertha3407ab2019-03-15 15:22:39 -040038 *format = MTLPixelFormatRGBA8Unorm;
39 return true;
Greg Danielf259b8b2019-02-14 09:03:43 -050040 case kRGB_888X_GrPixelConfig:
41 *format = MTLPixelFormatRGBA8Unorm;
42 return true;
Jim Van Verth69e57852018-12-05 13:38:59 -050043 case kRG_88_GrPixelConfig:
Jim Van Verth46431bf2019-04-09 15:26:38 -040044 *format = MTLPixelFormatRG8Unorm;
45 return true;
Greg Daniel0576a452017-07-31 16:32:36 -040046 case kBGRA_8888_GrPixelConfig:
47 *format = MTLPixelFormatBGRA8Unorm;
48 return true;
49 case kSRGBA_8888_GrPixelConfig:
50 *format = MTLPixelFormatRGBA8Unorm_sRGB;
51 return true;
Brian Osman10fc6fd2018-03-02 11:01:10 -050052 case kRGBA_1010102_GrPixelConfig:
53 *format = MTLPixelFormatRGB10A2Unorm;
54 return true;
Greg Daniel0576a452017-07-31 16:32:36 -040055 case kRGB_565_GrPixelConfig:
56#ifdef SK_BUILD_FOR_IOS
Brian Osman10fc6fd2018-03-02 11:01:10 -050057 *format = MTLPixelFormatB5G6R5Unorm;
Greg Daniel0576a452017-07-31 16:32:36 -040058 return true;
59#else
60 return false;
61#endif
62 case kRGBA_4444_GrPixelConfig:
63#ifdef SK_BUILD_FOR_IOS
64 *format = MTLPixelFormatABGR4Unorm;
65 return true;
66#else
67 return false;
68#endif
Greg Danielef59d872017-11-17 16:47:21 -050069 case kAlpha_8_GrPixelConfig: // fall through
70 case kAlpha_8_as_Red_GrPixelConfig:
Greg Daniel0576a452017-07-31 16:32:36 -040071 *format = MTLPixelFormatR8Unorm;
72 return true;
Greg Danielef59d872017-11-17 16:47:21 -050073 case kAlpha_8_as_Alpha_GrPixelConfig:
Robert Phillipsffe27292019-08-01 10:08:07 -040074 *format = MTLPixelFormatA8Unorm;
75 return true;
Greg Daniel7af060a2017-12-05 16:27:11 -050076 case kGray_8_GrPixelConfig: // fall through
77 case kGray_8_as_Red_GrPixelConfig:
Greg Daniel0576a452017-07-31 16:32:36 -040078 *format = MTLPixelFormatR8Unorm;
79 return true;
Greg Daniel7af060a2017-12-05 16:27:11 -050080 case kGray_8_as_Lum_GrPixelConfig:
81 return false;
Greg Daniel0576a452017-07-31 16:32:36 -040082 case kRGBA_float_GrPixelConfig:
83 *format = MTLPixelFormatRGBA32Float;
84 return true;
Greg Daniel0576a452017-07-31 16:32:36 -040085 case kRGBA_half_GrPixelConfig:
86 *format = MTLPixelFormatRGBA16Float;
87 return true;
Brian Osmand0626aa2019-03-11 15:28:06 -040088 case kRGBA_half_Clamped_GrPixelConfig:
89 *format = MTLPixelFormatRGBA16Float;
90 return true;
Greg Danielef59d872017-11-17 16:47:21 -050091 case kAlpha_half_GrPixelConfig: // fall through
92 case kAlpha_half_as_Red_GrPixelConfig:
Greg Daniel0576a452017-07-31 16:32:36 -040093 *format = MTLPixelFormatR16Float;
94 return true;
Robert Phillipsebab03f2019-07-22 08:48:18 -040095 case kAlpha_half_as_Lum_GrPixelConfig:
96 return false;
Jim Van Verth1676cb92019-01-15 13:24:45 -050097 case kRGB_ETC1_GrPixelConfig:
98#ifdef SK_BUILD_FOR_IOS
99 *format = MTLPixelFormatETC2_RGB8;
100 return true;
101#else
102 return false;
103#endif
Robert Phillips429f0d32019-09-11 17:03:28 -0400104 case kAlpha_16_GrPixelConfig:
Robert Phillipsfe18de52019-06-06 17:21:50 -0400105 *format = MTLPixelFormatR16Unorm;
106 return true;
107 case kRG_1616_GrPixelConfig:
108 *format = MTLPixelFormatRG16Unorm;
109 return true;
Robert Phillips66a46032019-06-18 08:00:42 -0400110
111 // Experimental (for Y416 and mutant P016/P010)
112 case kRGBA_16161616_GrPixelConfig:
113 *format = MTLPixelFormatRGBA16Unorm;
114 return true;
115 case kRG_half_GrPixelConfig:
116 *format = MTLPixelFormatRG16Float;
117 return true;
Greg Daniel0576a452017-07-31 16:32:36 -0400118 }
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400119 SK_ABORT("Unexpected config");
Greg Daniel0576a452017-07-31 16:32:36 -0400120}
121
Timothy Liangff19c8f2018-07-11 13:27:21 -0400122MTLTextureDescriptor* GrGetMTLTextureDescriptor(id<MTLTexture> mtlTexture) {
123 MTLTextureDescriptor* texDesc = [[MTLTextureDescriptor alloc] init];
124 texDesc.textureType = mtlTexture.textureType;
125 texDesc.pixelFormat = mtlTexture.pixelFormat;
126 texDesc.width = mtlTexture.width;
127 texDesc.height = mtlTexture.height;
128 texDesc.depth = mtlTexture.depth;
129 texDesc.mipmapLevelCount = mtlTexture.mipmapLevelCount;
130 texDesc.arrayLength = mtlTexture.arrayLength;
131 texDesc.sampleCount = mtlTexture.sampleCount;
132 texDesc.usage = mtlTexture.usage;
133 return texDesc;
134}
Timothy Liange30739a2018-07-31 10:51:17 -0400135
136#if PRINT_MSL
137void print_msl(const char* source) {
138 SkTArray<SkString> lines;
139 SkStrSplit(source, "\n", kStrict_SkStrSplitMode, &lines);
140 for (int i = 0; i < lines.count(); i++) {
141 SkString& line = lines[i];
142 line.prependf("%4i\t", i + 1);
143 SkDebugf("%s\n", line.c_str());
144 }
145}
146#endif
147
148id<MTLLibrary> GrCompileMtlShaderLibrary(const GrMtlGpu* gpu,
149 const char* shaderString,
150 SkSL::Program::Kind kind,
151 const SkSL::Program::Settings& settings,
152 SkSL::Program::Inputs* outInputs) {
153 std::unique_ptr<SkSL::Program> program =
154 gpu->shaderCompiler()->convertProgram(kind,
155 SkSL::String(shaderString),
156 settings);
157
158 if (!program) {
159 SkDebugf("SkSL error:\n%s\n", gpu->shaderCompiler()->errorText().c_str());
160 SkASSERT(false);
Jim Van Verth0c9ac582019-07-24 15:41:54 -0400161 return nil;
Timothy Liange30739a2018-07-31 10:51:17 -0400162 }
163
164 *outInputs = program->fInputs;
165 SkSL::String code;
166 if (!gpu->shaderCompiler()->toMetal(*program, &code)) {
167 SkDebugf("%s\n", gpu->shaderCompiler()->errorText().c_str());
168 SkASSERT(false);
169 return nil;
170 }
171 NSString* mtlCode = [[NSString alloc] initWithCString: code.c_str()
172 encoding: NSASCIIStringEncoding];
173#if PRINT_MSL
174 print_msl([mtlCode cStringUsingEncoding: NSASCIIStringEncoding]);
175#endif
176
177 MTLCompileOptions* defaultOptions = [[MTLCompileOptions alloc] init];
Jim Van Verthccd895e2019-06-28 13:01:58 -0400178#if defined(SK_BUILD_FOR_MAC) && defined(GR_USE_COMPLETION_HANDLER)
Jim Van Vertha885b892019-06-24 15:09:57 -0400179 bool timedout;
180 id<MTLLibrary> compiledLibrary = GrMtlNewLibraryWithSource(gpu->device(), mtlCode,
181 defaultOptions, &timedout);
182 if (timedout) {
183 // try again
184 compiledLibrary = GrMtlNewLibraryWithSource(gpu->device(), mtlCode,
185 defaultOptions, &timedout);
186 }
187#else
Timothy Liange30739a2018-07-31 10:51:17 -0400188 NSError* error = nil;
189 id<MTLLibrary> compiledLibrary = [gpu->device() newLibraryWithSource: mtlCode
190 options: defaultOptions
191 error: &error];
192 if (error) {
Ethan Nicholasf931e402019-07-26 15:40:33 -0400193 SkDebugf("Error compiling MSL shader: %s\n%s\n",
194 code.c_str(),
Timothy Liange30739a2018-07-31 10:51:17 -0400195 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
196 return nil;
197 }
Jim Van Vertha885b892019-06-24 15:09:57 -0400198#endif
Timothy Liange30739a2018-07-31 10:51:17 -0400199 return compiledLibrary;
200}
201
Jim Van Vertha885b892019-06-24 15:09:57 -0400202id<MTLLibrary> GrMtlNewLibraryWithSource(id<MTLDevice> device, NSString* mslCode,
203 MTLCompileOptions* options, bool* timedout) {
204 dispatch_semaphore_t compilerSemaphore = dispatch_semaphore_create(0);
205
206 __block dispatch_semaphore_t semaphore = compilerSemaphore;
207 __block id<MTLLibrary> compiledLibrary;
208 [device newLibraryWithSource: mslCode
209 options: options
210 completionHandler:
211 ^(id<MTLLibrary> library, NSError* error) {
212 if (error) {
Ethan Nicholasf931e402019-07-26 15:40:33 -0400213 SkDebugf("Error compiling MSL shader: %s\n%s\n",
214 mslCode,
Jim Van Vertha885b892019-06-24 15:09:57 -0400215 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
216 }
217 compiledLibrary = library;
218 dispatch_semaphore_signal(semaphore);
219 }
220 ];
221
222 // Wait 100 ms for the compiler
223 if (dispatch_semaphore_wait(compilerSemaphore, dispatch_time(DISPATCH_TIME_NOW, 100000))) {
224 SkDebugf("Timeout compiling MSL shader\n");
225 *timedout = true;
226 return nil;
227 }
228
229 *timedout = false;
230 return compiledLibrary;
231}
232
233id<MTLRenderPipelineState> GrMtlNewRenderPipelineStateWithDescriptor(
234 id<MTLDevice> device, MTLRenderPipelineDescriptor* pipelineDescriptor, bool* timedout) {
235 dispatch_semaphore_t pipelineSemaphore = dispatch_semaphore_create(0);
236
237 __block dispatch_semaphore_t semaphore = pipelineSemaphore;
238 __block id<MTLRenderPipelineState> pipelineState;
239 [device newRenderPipelineStateWithDescriptor: pipelineDescriptor
240 completionHandler:
241 ^(id<MTLRenderPipelineState> state, NSError* error) {
242 if (error) {
243 SkDebugf("Error creating pipeline: %s\n",
244 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
245 }
246 pipelineState = state;
247 dispatch_semaphore_signal(semaphore);
248 }
249 ];
250
251 // Wait 500 ms for pipeline creation
252 if (dispatch_semaphore_wait(pipelineSemaphore, dispatch_time(DISPATCH_TIME_NOW, 500000))) {
253 SkDebugf("Timeout creating pipeline.\n");
254 *timedout = true;
255 return nil;
256 }
257
258 *timedout = false;
259 return pipelineState;
260}
261
Jim Van Verthd361e642019-07-11 15:40:53 -0400262id<MTLTexture> GrGetMTLTextureFromSurface(GrSurface* surface) {
Timothy Liange30739a2018-07-31 10:51:17 -0400263 id<MTLTexture> mtlTexture = nil;
264
265 GrMtlRenderTarget* renderTarget = static_cast<GrMtlRenderTarget*>(surface->asRenderTarget());
266 GrMtlTexture* texture;
267 if (renderTarget) {
Jim Van Verthd361e642019-07-11 15:40:53 -0400268 // We should not be using this for multisampled rendertargets
269 if (renderTarget->numSamples() > 1) {
Timothy Liange30739a2018-07-31 10:51:17 -0400270 SkASSERT(false);
Jim Van Verthd361e642019-07-11 15:40:53 -0400271 return nil;
Timothy Liange30739a2018-07-31 10:51:17 -0400272 }
Jim Van Verthd361e642019-07-11 15:40:53 -0400273 mtlTexture = renderTarget->mtlColorTexture();
Timothy Liange30739a2018-07-31 10:51:17 -0400274 } else {
275 texture = static_cast<GrMtlTexture*>(surface->asTexture());
276 if (texture) {
277 mtlTexture = texture->mtlTexture();
278 }
279 }
280 return mtlTexture;
281}
Brian Salomonf391d0f2018-12-14 09:18:50 -0500282
283
284//////////////////////////////////////////////////////////////////////////////
285// CPP Utils
286
287GrMTLPixelFormat GrGetMTLPixelFormatFromMtlTextureInfo(const GrMtlTextureInfo& info) {
Jim Van Verthdac1e552019-05-31 09:10:55 -0400288 id<MTLTexture> mtlTexture = GrGetMTLTexture(info.fTexture.get());
Brian Salomonf391d0f2018-12-14 09:18:50 -0500289 return static_cast<GrMTLPixelFormat>(mtlTexture.pixelFormat);
290}
Robert Phillips62221e72019-07-24 15:07:38 -0400291
292size_t GrMtlBytesPerFormat(MTLPixelFormat format) {
293 switch (format) {
Robert Phillipsb7f95d12019-07-26 11:13:19 -0400294 case MTLPixelFormatA8Unorm:
Robert Phillips62221e72019-07-24 15:07:38 -0400295 case MTLPixelFormatR8Unorm:
296 return 1;
297
298#ifdef SK_BUILD_FOR_IOS
299 case MTLPixelFormatB5G6R5Unorm:
300 case MTLPixelFormatABGR4Unorm:
301#endif
302 case MTLPixelFormatRG8Unorm:
303 case MTLPixelFormatR16Float:
304 case MTLPixelFormatR16Unorm:
305 return 2;
306
307 case MTLPixelFormatRGBA8Unorm:
308 case MTLPixelFormatBGRA8Unorm:
309 case MTLPixelFormatRGBA8Unorm_sRGB:
310 case MTLPixelFormatRGB10A2Unorm:
311 case MTLPixelFormatRG16Unorm:
312 case MTLPixelFormatRG16Float:
313 return 4;
314
315 case MTLPixelFormatRGBA16Float:
316 case MTLPixelFormatRGBA16Unorm:
317 return 8;
318
319 case MTLPixelFormatRGBA32Float:
320 return 16;
321
322#ifdef SK_BUILD_FOR_IOS
323 case MTLPixelFormatETC2_RGB8:
324 return 0;
325#endif
326 default:
327 SK_ABORT("Invalid Mtl format");
Robert Phillips62221e72019-07-24 15:07:38 -0400328 }
329
330 SK_ABORT("Invalid Mtl format");
Robert Phillips62221e72019-07-24 15:07:38 -0400331}
332
Jim Van Verthc25802d2019-09-16 13:57:37 -0400333bool GrMtlFormatIsCompressed(MTLPixelFormat mtlFormat) {
334 switch (mtlFormat) {
335#ifdef SK_BUILD_FOR_IOS
336 case MTLPixelFormatETC2_RGB8:
337 return true;
338#endif
339 default:
340 return false;
341 }
342}
343
344bool GrMtlFormatToCompressionType(MTLPixelFormat mtlFormat,
345 SkImage::CompressionType* compressionType) {
346 switch (mtlFormat) {
347#ifdef SK_BUILD_FOR_IOS
348 case MTLPixelFormatETC2_RGB8:
349 *compressionType = SkImage::kETC1_CompressionType;
350 return true;
351#endif
352 default:
353 return false;
354 }
355}
356
Robert Phillipsbac46722019-08-01 15:09:17 -0400357#if GR_TEST_UTILS
358const char* GrMtlFormatToStr(GrMTLPixelFormat mtlFormat) {
359 switch (mtlFormat) {
360 case MTLPixelFormatInvalid: return "Invalid";
361 case MTLPixelFormatRGBA8Unorm: return "RGBA8Unorm";
362 case MTLPixelFormatR8Unorm: return "R8Unorm";
363 case MTLPixelFormatA8Unorm: return "A8Unorm";
364 case MTLPixelFormatBGRA8Unorm: return "BGRA8Unorm";
365#ifdef SK_BUILD_FOR_IOS
366 case MTLPixelFormatB5G6R5Unorm: return "B5G6R5Unorm";
367#endif
368 case MTLPixelFormatRGBA16Float: return "RGBA16Float";
369 case MTLPixelFormatR16Float: return "R16Float";
370 case MTLPixelFormatRG8Unorm: return "RG8Unorm";
371 case MTLPixelFormatRGB10A2Unorm: return "RGB10A2Unorm";
372#ifdef SK_BUILD_FOR_IOS
373 case MTLPixelFormatABGR4Unorm: return "ABGR4Unorm";
374#endif
375 case MTLPixelFormatRGBA32Float: return "RGBA32Float";
376 case MTLPixelFormatRGBA8Unorm_sRGB: return "RGBA8Unorm_sRGB";
377 case MTLPixelFormatR16Unorm: return "R16Unorm";
378 case MTLPixelFormatRG16Unorm: return "RG16Unorm";
379#ifdef SK_BUILD_FOR_IOS
380 case MTLPixelFormatETC2_RGB8: return "ETC2_RGB8";
381#endif
382 case MTLPixelFormatRGBA16Unorm: return "RGBA16Unorm";
383 case MTLPixelFormatRG16Float: return "RG16Float";
384
385 default: return "Unknown";
386 }
387}
388
389#endif
390
391
Robert Phillips62221e72019-07-24 15:07:38 -0400392