blob: e0de7d599a7af9c2c3f28494ac9ebfe3fe26d8ab [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 case kRGBA_16161616_GrPixelConfig:
111 *format = MTLPixelFormatRGBA16Unorm;
112 return true;
113 case kRG_half_GrPixelConfig:
114 *format = MTLPixelFormatRG16Float;
115 return true;
Greg Daniel0576a452017-07-31 16:32:36 -0400116 }
Ben Wagnerb4aab9a2017-08-16 10:53:04 -0400117 SK_ABORT("Unexpected config");
Greg Daniel0576a452017-07-31 16:32:36 -0400118}
119
Timothy Liangff19c8f2018-07-11 13:27:21 -0400120MTLTextureDescriptor* GrGetMTLTextureDescriptor(id<MTLTexture> mtlTexture) {
121 MTLTextureDescriptor* texDesc = [[MTLTextureDescriptor alloc] init];
122 texDesc.textureType = mtlTexture.textureType;
123 texDesc.pixelFormat = mtlTexture.pixelFormat;
124 texDesc.width = mtlTexture.width;
125 texDesc.height = mtlTexture.height;
126 texDesc.depth = mtlTexture.depth;
127 texDesc.mipmapLevelCount = mtlTexture.mipmapLevelCount;
128 texDesc.arrayLength = mtlTexture.arrayLength;
129 texDesc.sampleCount = mtlTexture.sampleCount;
130 texDesc.usage = mtlTexture.usage;
131 return texDesc;
132}
Timothy Liange30739a2018-07-31 10:51:17 -0400133
134#if PRINT_MSL
135void print_msl(const char* source) {
136 SkTArray<SkString> lines;
137 SkStrSplit(source, "\n", kStrict_SkStrSplitMode, &lines);
138 for (int i = 0; i < lines.count(); i++) {
139 SkString& line = lines[i];
140 line.prependf("%4i\t", i + 1);
141 SkDebugf("%s\n", line.c_str());
142 }
143}
144#endif
145
146id<MTLLibrary> GrCompileMtlShaderLibrary(const GrMtlGpu* gpu,
147 const char* shaderString,
148 SkSL::Program::Kind kind,
149 const SkSL::Program::Settings& settings,
150 SkSL::Program::Inputs* outInputs) {
151 std::unique_ptr<SkSL::Program> program =
152 gpu->shaderCompiler()->convertProgram(kind,
153 SkSL::String(shaderString),
154 settings);
155
156 if (!program) {
157 SkDebugf("SkSL error:\n%s\n", gpu->shaderCompiler()->errorText().c_str());
158 SkASSERT(false);
Jim Van Verth0c9ac582019-07-24 15:41:54 -0400159 return nil;
Timothy Liange30739a2018-07-31 10:51:17 -0400160 }
161
162 *outInputs = program->fInputs;
163 SkSL::String code;
164 if (!gpu->shaderCompiler()->toMetal(*program, &code)) {
165 SkDebugf("%s\n", gpu->shaderCompiler()->errorText().c_str());
166 SkASSERT(false);
167 return nil;
168 }
169 NSString* mtlCode = [[NSString alloc] initWithCString: code.c_str()
170 encoding: NSASCIIStringEncoding];
171#if PRINT_MSL
172 print_msl([mtlCode cStringUsingEncoding: NSASCIIStringEncoding]);
173#endif
174
175 MTLCompileOptions* defaultOptions = [[MTLCompileOptions alloc] init];
Jim Van Verthccd895e2019-06-28 13:01:58 -0400176#if defined(SK_BUILD_FOR_MAC) && defined(GR_USE_COMPLETION_HANDLER)
Jim Van Vertha885b892019-06-24 15:09:57 -0400177 bool timedout;
178 id<MTLLibrary> compiledLibrary = GrMtlNewLibraryWithSource(gpu->device(), mtlCode,
179 defaultOptions, &timedout);
180 if (timedout) {
181 // try again
182 compiledLibrary = GrMtlNewLibraryWithSource(gpu->device(), mtlCode,
183 defaultOptions, &timedout);
184 }
185#else
Timothy Liange30739a2018-07-31 10:51:17 -0400186 NSError* error = nil;
187 id<MTLLibrary> compiledLibrary = [gpu->device() newLibraryWithSource: mtlCode
188 options: defaultOptions
189 error: &error];
190 if (error) {
Ethan Nicholasf931e402019-07-26 15:40:33 -0400191 SkDebugf("Error compiling MSL shader: %s\n%s\n",
192 code.c_str(),
Timothy Liange30739a2018-07-31 10:51:17 -0400193 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
194 return nil;
195 }
Jim Van Vertha885b892019-06-24 15:09:57 -0400196#endif
Timothy Liange30739a2018-07-31 10:51:17 -0400197 return compiledLibrary;
198}
199
Jim Van Vertha885b892019-06-24 15:09:57 -0400200id<MTLLibrary> GrMtlNewLibraryWithSource(id<MTLDevice> device, NSString* mslCode,
201 MTLCompileOptions* options, bool* timedout) {
202 dispatch_semaphore_t compilerSemaphore = dispatch_semaphore_create(0);
203
204 __block dispatch_semaphore_t semaphore = compilerSemaphore;
205 __block id<MTLLibrary> compiledLibrary;
206 [device newLibraryWithSource: mslCode
207 options: options
208 completionHandler:
209 ^(id<MTLLibrary> library, NSError* error) {
210 if (error) {
Ethan Nicholasf931e402019-07-26 15:40:33 -0400211 SkDebugf("Error compiling MSL shader: %s\n%s\n",
212 mslCode,
Jim Van Vertha885b892019-06-24 15:09:57 -0400213 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
214 }
215 compiledLibrary = library;
216 dispatch_semaphore_signal(semaphore);
217 }
218 ];
219
220 // Wait 100 ms for the compiler
221 if (dispatch_semaphore_wait(compilerSemaphore, dispatch_time(DISPATCH_TIME_NOW, 100000))) {
222 SkDebugf("Timeout compiling MSL shader\n");
223 *timedout = true;
224 return nil;
225 }
226
227 *timedout = false;
228 return compiledLibrary;
229}
230
231id<MTLRenderPipelineState> GrMtlNewRenderPipelineStateWithDescriptor(
232 id<MTLDevice> device, MTLRenderPipelineDescriptor* pipelineDescriptor, bool* timedout) {
233 dispatch_semaphore_t pipelineSemaphore = dispatch_semaphore_create(0);
234
235 __block dispatch_semaphore_t semaphore = pipelineSemaphore;
236 __block id<MTLRenderPipelineState> pipelineState;
237 [device newRenderPipelineStateWithDescriptor: pipelineDescriptor
238 completionHandler:
239 ^(id<MTLRenderPipelineState> state, NSError* error) {
240 if (error) {
241 SkDebugf("Error creating pipeline: %s\n",
242 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
243 }
244 pipelineState = state;
245 dispatch_semaphore_signal(semaphore);
246 }
247 ];
248
249 // Wait 500 ms for pipeline creation
250 if (dispatch_semaphore_wait(pipelineSemaphore, dispatch_time(DISPATCH_TIME_NOW, 500000))) {
251 SkDebugf("Timeout creating pipeline.\n");
252 *timedout = true;
253 return nil;
254 }
255
256 *timedout = false;
257 return pipelineState;
258}
259
Jim Van Verthd361e642019-07-11 15:40:53 -0400260id<MTLTexture> GrGetMTLTextureFromSurface(GrSurface* surface) {
Timothy Liange30739a2018-07-31 10:51:17 -0400261 id<MTLTexture> mtlTexture = nil;
262
263 GrMtlRenderTarget* renderTarget = static_cast<GrMtlRenderTarget*>(surface->asRenderTarget());
264 GrMtlTexture* texture;
265 if (renderTarget) {
Jim Van Verthd361e642019-07-11 15:40:53 -0400266 // We should not be using this for multisampled rendertargets
267 if (renderTarget->numSamples() > 1) {
Timothy Liange30739a2018-07-31 10:51:17 -0400268 SkASSERT(false);
Jim Van Verthd361e642019-07-11 15:40:53 -0400269 return nil;
Timothy Liange30739a2018-07-31 10:51:17 -0400270 }
Jim Van Verthd361e642019-07-11 15:40:53 -0400271 mtlTexture = renderTarget->mtlColorTexture();
Timothy Liange30739a2018-07-31 10:51:17 -0400272 } else {
273 texture = static_cast<GrMtlTexture*>(surface->asTexture());
274 if (texture) {
275 mtlTexture = texture->mtlTexture();
276 }
277 }
278 return mtlTexture;
279}
Brian Salomonf391d0f2018-12-14 09:18:50 -0500280
281
282//////////////////////////////////////////////////////////////////////////////
283// CPP Utils
284
285GrMTLPixelFormat GrGetMTLPixelFormatFromMtlTextureInfo(const GrMtlTextureInfo& info) {
Jim Van Verthdac1e552019-05-31 09:10:55 -0400286 id<MTLTexture> mtlTexture = GrGetMTLTexture(info.fTexture.get());
Brian Salomonf391d0f2018-12-14 09:18:50 -0500287 return static_cast<GrMTLPixelFormat>(mtlTexture.pixelFormat);
288}
Robert Phillips62221e72019-07-24 15:07:38 -0400289
290size_t GrMtlBytesPerFormat(MTLPixelFormat format) {
291 switch (format) {
Robert Phillipsb7f95d12019-07-26 11:13:19 -0400292 case MTLPixelFormatA8Unorm:
Robert Phillips62221e72019-07-24 15:07:38 -0400293 case MTLPixelFormatR8Unorm:
294 return 1;
295
296#ifdef SK_BUILD_FOR_IOS
297 case MTLPixelFormatB5G6R5Unorm:
298 case MTLPixelFormatABGR4Unorm:
299#endif
300 case MTLPixelFormatRG8Unorm:
301 case MTLPixelFormatR16Float:
302 case MTLPixelFormatR16Unorm:
303 return 2;
304
305 case MTLPixelFormatRGBA8Unorm:
306 case MTLPixelFormatBGRA8Unorm:
307 case MTLPixelFormatRGBA8Unorm_sRGB:
308 case MTLPixelFormatRGB10A2Unorm:
309 case MTLPixelFormatRG16Unorm:
310 case MTLPixelFormatRG16Float:
311 return 4;
312
313 case MTLPixelFormatRGBA16Float:
314 case MTLPixelFormatRGBA16Unorm:
315 return 8;
316
317 case MTLPixelFormatRGBA32Float:
318 return 16;
319
320#ifdef SK_BUILD_FOR_IOS
321 case MTLPixelFormatETC2_RGB8:
322 return 0;
323#endif
324 default:
325 SK_ABORT("Invalid Mtl format");
Robert Phillips62221e72019-07-24 15:07:38 -0400326 }
327
328 SK_ABORT("Invalid Mtl format");
Robert Phillips62221e72019-07-24 15:07:38 -0400329}
330
Jim Van Verthe3671012019-09-18 09:53:31 -0400331bool GrMtlFormatIsCompressed(MTLPixelFormat mtlFormat) {
332 switch (mtlFormat) {
333#ifdef SK_BUILD_FOR_IOS
334 case MTLPixelFormatETC2_RGB8:
335 return true;
336#endif
337 default:
338 return false;
339 }
340}
341
342bool GrMtlFormatToCompressionType(MTLPixelFormat mtlFormat,
343 SkImage::CompressionType* compressionType) {
344 switch (mtlFormat) {
345#ifdef SK_BUILD_FOR_IOS
346 case MTLPixelFormatETC2_RGB8:
347 *compressionType = SkImage::kETC1_CompressionType;
348 return true;
349#endif
350 default:
351 return false;
352 }
353}
354
Robert Phillipsbac46722019-08-01 15:09:17 -0400355#if GR_TEST_UTILS
Robert Phillips7f367982019-09-26 14:01:36 -0400356bool GrMtlFormatIsBGRA(GrMTLPixelFormat mtlFormat) {
357 return mtlFormat == MTLPixelFormatBGRA8Unorm;
358}
359
Robert Phillipsbac46722019-08-01 15:09:17 -0400360const char* GrMtlFormatToStr(GrMTLPixelFormat mtlFormat) {
361 switch (mtlFormat) {
362 case MTLPixelFormatInvalid: return "Invalid";
363 case MTLPixelFormatRGBA8Unorm: return "RGBA8Unorm";
364 case MTLPixelFormatR8Unorm: return "R8Unorm";
365 case MTLPixelFormatA8Unorm: return "A8Unorm";
366 case MTLPixelFormatBGRA8Unorm: return "BGRA8Unorm";
367#ifdef SK_BUILD_FOR_IOS
368 case MTLPixelFormatB5G6R5Unorm: return "B5G6R5Unorm";
369#endif
370 case MTLPixelFormatRGBA16Float: return "RGBA16Float";
371 case MTLPixelFormatR16Float: return "R16Float";
372 case MTLPixelFormatRG8Unorm: return "RG8Unorm";
373 case MTLPixelFormatRGB10A2Unorm: return "RGB10A2Unorm";
374#ifdef SK_BUILD_FOR_IOS
375 case MTLPixelFormatABGR4Unorm: return "ABGR4Unorm";
376#endif
377 case MTLPixelFormatRGBA32Float: return "RGBA32Float";
378 case MTLPixelFormatRGBA8Unorm_sRGB: return "RGBA8Unorm_sRGB";
379 case MTLPixelFormatR16Unorm: return "R16Unorm";
380 case MTLPixelFormatRG16Unorm: return "RG16Unorm";
381#ifdef SK_BUILD_FOR_IOS
382 case MTLPixelFormatETC2_RGB8: return "ETC2_RGB8";
383#endif
384 case MTLPixelFormatRGBA16Unorm: return "RGBA16Unorm";
385 case MTLPixelFormatRG16Float: return "RG16Float";
386
387 default: return "Unknown";
388 }
389}
390
391#endif
392
393
Robert Phillips62221e72019-07-24 15:07:38 -0400394