• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
8#include "src/gpu/mtl/GrMtlUtil.h"
9
10#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"
16
17#import <Metal/Metal.h>
18
19#if !__has_feature(objc_arc)
20#error This file must be compiled with Arc. Use -fobjc-arc flag
21#endif
22
23#define PRINT_MSL 0 // print out the MSL code generated
24
25bool 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;
37        case kRGB_888_GrPixelConfig:
38            *format = MTLPixelFormatRGBA8Unorm;
39            return true;
40        case kRGB_888X_GrPixelConfig:
41            *format = MTLPixelFormatRGBA8Unorm;
42            return true;
43        case kRG_88_GrPixelConfig:
44            *format = MTLPixelFormatRG8Unorm;
45            return true;
46        case kBGRA_8888_GrPixelConfig:
47            *format = MTLPixelFormatBGRA8Unorm;
48            return true;
49        case kSRGBA_8888_GrPixelConfig:
50            *format = MTLPixelFormatRGBA8Unorm_sRGB;
51            return true;
52        case kRGBA_1010102_GrPixelConfig:
53            *format = MTLPixelFormatRGB10A2Unorm;
54            return true;
55        case kRGB_565_GrPixelConfig:
56#ifdef SK_BUILD_FOR_IOS
57            *format = MTLPixelFormatB5G6R5Unorm;
58            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
69        case kAlpha_8_GrPixelConfig: // fall through
70        case kAlpha_8_as_Red_GrPixelConfig:
71            *format = MTLPixelFormatR8Unorm;
72            return true;
73        case kAlpha_8_as_Alpha_GrPixelConfig:
74            *format = MTLPixelFormatA8Unorm;
75            return true;
76        case kGray_8_GrPixelConfig: // fall through
77        case kGray_8_as_Red_GrPixelConfig:
78            *format = MTLPixelFormatR8Unorm;
79            return true;
80        case kGray_8_as_Lum_GrPixelConfig:
81            return false;
82        case kRGBA_float_GrPixelConfig:
83            *format = MTLPixelFormatRGBA32Float;
84            return true;
85        case kRGBA_half_GrPixelConfig:
86            *format = MTLPixelFormatRGBA16Float;
87            return true;
88        case kRGBA_half_Clamped_GrPixelConfig:
89            *format = MTLPixelFormatRGBA16Float;
90            return true;
91        case kAlpha_half_GrPixelConfig: // fall through
92        case kAlpha_half_as_Red_GrPixelConfig:
93            *format = MTLPixelFormatR16Float;
94            return true;
95        case kAlpha_half_as_Lum_GrPixelConfig:
96            return false;
97        case kRGB_ETC1_GrPixelConfig:
98#ifdef SK_BUILD_FOR_IOS
99            *format = MTLPixelFormatETC2_RGB8;
100            return true;
101#else
102            return false;
103#endif
104        case kR_16_GrPixelConfig:
105            *format = MTLPixelFormatR16Unorm;
106            return true;
107        case kRG_1616_GrPixelConfig:
108            *format = MTLPixelFormatRG16Unorm;
109            return true;
110
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;
118    }
119    SK_ABORT("Unexpected config");
120}
121
122MTLTextureDescriptor* 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}
135
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);
161        return nil;
162    }
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];
178#if defined(SK_BUILD_FOR_MAC) && defined(GR_USE_COMPLETION_HANDLER)
179    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
188    NSError* error = nil;
189    id<MTLLibrary> compiledLibrary = [gpu->device() newLibraryWithSource: mtlCode
190                                                                 options: defaultOptions
191                                                                   error: &error];
192    if (error) {
193        SkDebugf("Error compiling MSL shader: %s\n%s\n",
194                 code.c_str(),
195                 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
196        return nil;
197    }
198#endif
199    return compiledLibrary;
200}
201
202id<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) {
213                SkDebugf("Error compiling MSL shader: %s\n%s\n",
214                    mslCode,
215                    [[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
262id<MTLTexture> GrGetMTLTextureFromSurface(GrSurface* surface) {
263    id<MTLTexture> mtlTexture = nil;
264
265    GrMtlRenderTarget* renderTarget = static_cast<GrMtlRenderTarget*>(surface->asRenderTarget());
266    GrMtlTexture* texture;
267    if (renderTarget) {
268        // We should not be using this for multisampled rendertargets
269        if (renderTarget->numSamples() > 1) {
270            SkASSERT(false);
271            return nil;
272        }
273        mtlTexture = renderTarget->mtlColorTexture();
274    } else {
275        texture = static_cast<GrMtlTexture*>(surface->asTexture());
276        if (texture) {
277            mtlTexture = texture->mtlTexture();
278        }
279    }
280    return mtlTexture;
281}
282
283
284//////////////////////////////////////////////////////////////////////////////
285// CPP Utils
286
287GrMTLPixelFormat GrGetMTLPixelFormatFromMtlTextureInfo(const GrMtlTextureInfo& info) {
288    id<MTLTexture> mtlTexture = GrGetMTLTexture(info.fTexture.get());
289    return static_cast<GrMTLPixelFormat>(mtlTexture.pixelFormat);
290}
291
292size_t GrMtlBytesPerFormat(MTLPixelFormat format) {
293    switch (format) {
294        case MTLPixelFormatA8Unorm:
295        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");
328    }
329
330    SK_ABORT("Invalid Mtl format");
331}
332
333#if GR_TEST_UTILS
334const char* GrMtlFormatToStr(GrMTLPixelFormat mtlFormat) {
335    switch (mtlFormat) {
336        case MTLPixelFormatInvalid:         return "Invalid";
337        case MTLPixelFormatRGBA8Unorm:      return "RGBA8Unorm";
338        case MTLPixelFormatR8Unorm:         return "R8Unorm";
339        case MTLPixelFormatA8Unorm:         return "A8Unorm";
340        case MTLPixelFormatBGRA8Unorm:      return "BGRA8Unorm";
341#ifdef SK_BUILD_FOR_IOS
342        case MTLPixelFormatB5G6R5Unorm:     return "B5G6R5Unorm";
343#endif
344        case MTLPixelFormatRGBA16Float:     return "RGBA16Float";
345        case MTLPixelFormatR16Float:        return "R16Float";
346        case MTLPixelFormatRG8Unorm:        return "RG8Unorm";
347        case MTLPixelFormatRGB10A2Unorm:    return "RGB10A2Unorm";
348#ifdef SK_BUILD_FOR_IOS
349        case MTLPixelFormatABGR4Unorm:      return "ABGR4Unorm";
350#endif
351        case MTLPixelFormatRGBA32Float:     return "RGBA32Float";
352        case MTLPixelFormatRGBA8Unorm_sRGB: return "RGBA8Unorm_sRGB";
353        case MTLPixelFormatR16Unorm:        return "R16Unorm";
354        case MTLPixelFormatRG16Unorm:       return "RG16Unorm";
355#ifdef SK_BUILD_FOR_IOS
356        case MTLPixelFormatETC2_RGB8:      return "ETC2_RGB8";
357#endif
358        case MTLPixelFormatRGBA16Unorm:    return "RGBA16Unorm";
359        case MTLPixelFormatRG16Float:      return "RG16Float";
360
361        default:                           return "Unknown";
362    }
363}
364
365#endif
366
367
368
369