• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright 2021 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 "experimental/graphite/src/mtl/MtlUtils.h"
9
10#include "experimental/graphite/src/mtl/MtlGpu.h"
11#include "include/gpu/ShaderErrorHandler.h"
12#include "include/private/SkSLString.h"
13#include "src/core/SkTraceEvent.h"
14#include "src/sksl/SkSLCompiler.h"
15#include "src/utils/SkShaderUtils.h"
16
17#ifdef SK_BUILD_FOR_IOS
18#import <UIKit/UIApplication.h>
19#endif
20
21namespace skgpu::mtl {
22
23bool FormatIsDepthOrStencil(MTLPixelFormat format) {
24    switch (format) {
25        case MTLPixelFormatStencil8: // fallthrough
26        case MTLPixelFormatDepth32Float_Stencil8:
27            return true;
28        default:
29            return false;
30    }
31}
32
33bool FormatIsDepth(MTLPixelFormat format) {
34    switch (format) {
35        case MTLPixelFormatDepth32Float_Stencil8:
36            return true;
37        default:
38            return false;
39    }
40}
41
42bool FormatIsStencil(MTLPixelFormat format) {
43    switch (format) {
44        case MTLPixelFormatStencil8: // fallthrough
45        case MTLPixelFormatDepth32Float_Stencil8:
46            return true;
47        default:
48            return false;
49    }
50}
51
52MTLPixelFormat SkColorTypeToFormat(SkColorType colorType) {
53    switch (colorType) {
54        case kRGBA_8888_SkColorType:
55            return MTLPixelFormatRGBA8Unorm;
56        case kBGRA_8888_SkColorType:
57            return MTLPixelFormatBGRA8Unorm;
58        case kAlpha_8_SkColorType:
59            return MTLPixelFormatR8Unorm;
60        case kRGBA_F16_SkColorType:
61            return MTLPixelFormatRGBA16Float;
62        default:
63            // TODO: fill in the rest of the formats
64            SkUNREACHABLE;
65    }
66}
67
68MTLPixelFormat DepthStencilFlagsToFormat(Mask<DepthStencilFlags> mask) {
69    // TODO: Decide if we want to change this to always return a combined depth and stencil format
70    // to allow more sharing of depth stencil allocations.
71    if (mask == DepthStencilFlags::kDepth) {
72        // MTLPixelFormatDepth16Unorm is also a universally supported option here
73        return MTLPixelFormatDepth32Float;
74    } else if (mask == DepthStencilFlags::kStencil) {
75        return MTLPixelFormatStencil8;
76    } else if (mask == DepthStencilFlags::kDepthStencil) {
77        // MTLPixelFormatDepth24Unorm_Stencil8 is supported on Mac family GPUs.
78        return MTLPixelFormatDepth32Float_Stencil8;
79    }
80    SkASSERT(false);
81    return MTLPixelFormatInvalid;
82}
83
84// Print the source code for all shaders generated.
85static const bool gPrintSKSL = false;
86static const bool gPrintMSL = false;
87
88bool SkSLToMSL(const Gpu* gpu,
89               const std::string& sksl,
90               SkSL::ProgramKind programKind,
91               const SkSL::Program::Settings& settings,
92               std::string* msl,
93               SkSL::Program::Inputs* outInputs,
94               ShaderErrorHandler* errorHandler) {
95#ifdef SK_DEBUG
96    std::string src = SkShaderUtils::PrettyPrint(sksl);
97#else
98    const std::string& src = sksl;
99#endif
100    SkSL::Compiler* compiler = gpu->shaderCompiler();
101    std::unique_ptr<SkSL::Program> program =
102            gpu->shaderCompiler()->convertProgram(programKind,
103                                                  src,
104                                                  settings);
105    if (!program || !compiler->toMetal(*program, msl)) {
106        errorHandler->compileError(src.c_str(), compiler->errorText().c_str());
107        return false;
108    }
109
110    if (gPrintSKSL || gPrintMSL) {
111        SkShaderUtils::PrintShaderBanner(programKind);
112        if (gPrintSKSL) {
113            SkDebugf("SKSL:\n");
114            SkShaderUtils::PrintLineByLine(SkShaderUtils::PrettyPrint(sksl));
115        }
116        if (gPrintMSL) {
117            SkDebugf("MSL:\n");
118            SkShaderUtils::PrintLineByLine(SkShaderUtils::PrettyPrint(*msl));
119        }
120    }
121
122    *outInputs = program->fInputs;
123    return true;
124}
125
126sk_cfp<id<MTLLibrary>> CompileShaderLibrary(const Gpu* gpu,
127                                            const std::string& msl,
128                                            ShaderErrorHandler* errorHandler) {
129    TRACE_EVENT0("skia.shaders", "driver_compile_shader");
130    auto nsSource = [[NSString alloc] initWithBytesNoCopy:const_cast<char*>(msl.c_str())
131                                                   length:msl.size()
132                                                 encoding:NSUTF8StringEncoding
133                                             freeWhenDone:NO];
134    MTLCompileOptions* options = [[MTLCompileOptions alloc] init];
135    // array<> is supported in MSL 2.0 on MacOS 10.13+ and iOS 11+,
136    // and in MSL 1.2 on iOS 10+ (but not MacOS).
137    if (@available(macOS 10.13, iOS 11.0, *)) {
138        options.languageVersion = MTLLanguageVersion2_0;
139#if defined(SK_BUILD_FOR_IOS)
140    } else if (@available(macOS 10.12, iOS 10.0, *)) {
141        options.languageVersion = MTLLanguageVersion1_2;
142#endif
143    }
144
145    NSError* error = nil;
146    // TODO: do we need a version with a timeout?
147    sk_cfp<id<MTLLibrary>> compiledLibrary([gpu->device() newLibraryWithSource:nsSource
148                                                                       options:options
149                                                                         error:&error]);
150    if (!compiledLibrary) {
151        errorHandler->compileError(msl.c_str(), error.debugDescription.UTF8String);
152        return nil;
153    }
154
155    return compiledLibrary;
156}
157
158#ifdef SK_BUILD_FOR_IOS
159bool IsAppInBackground() {
160    return [NSThread isMainThread] &&
161           ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground);
162}
163#endif
164} // namespace skgpu::mtl
165