xref: /aosp_15_r20/external/skia/src/gpu/graphite/mtl/MtlGraphiteUtils.mm (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 "include/gpu/graphite/mtl/MtlGraphiteUtils.h"
9#include "src/gpu/graphite/mtl/MtlGraphiteUtilsPriv.h"
10
11#include "include/gpu/ShaderErrorHandler.h"
12#include "include/gpu/graphite/Context.h"
13#include "src/core/SkTraceEvent.h"
14#include "src/gpu/graphite/ContextPriv.h"
15#include "src/gpu/graphite/mtl/MtlQueueManager.h"
16#include "src/gpu/graphite/mtl/MtlSharedContext.h"
17#include "src/gpu/mtl/MtlUtilsPriv.h"
18
19namespace skgpu::graphite {
20
21namespace ContextFactory {
22
23std::unique_ptr<Context> MakeMetal(const MtlBackendContext& backendContext,
24                                   const ContextOptions& options) {
25    sk_sp<SharedContext> sharedContext = MtlSharedContext::Make(backendContext, options);
26    if (!sharedContext) {
27        return nullptr;
28    }
29
30    sk_cfp<id<MTLCommandQueue>> queue =
31            sk_ret_cfp((id<MTLCommandQueue>)(backendContext.fQueue.get()));
32    auto queueManager = std::make_unique<MtlQueueManager>(std::move(queue), sharedContext.get());
33    if (!queueManager) {
34        return nullptr;
35    }
36
37    return ContextCtorAccessor::MakeContext(std::move(sharedContext),
38                                            std::move(queueManager),
39                                            options);
40}
41
42} // namespace ContextFactory
43
44sk_cfp<id<MTLLibrary>> MtlCompileShaderLibrary(const MtlSharedContext* sharedContext,
45                                               std::string_view label,
46                                               std::string_view msl,
47                                               ShaderErrorHandler* errorHandler) {
48    TRACE_EVENT0("skia.shaders", "driver_compile_shader");
49    NSString* nsSource = [[NSString alloc] initWithBytesNoCopy:const_cast<char*>(msl.data())
50                                                        length:msl.size()
51                                                      encoding:NSUTF8StringEncoding
52                                                  freeWhenDone:NO];
53    if (!nsSource) {
54        return nil;
55    }
56    MTLCompileOptions* options = [[MTLCompileOptions alloc] init];
57
58    // Framebuffer fetch is supported in MSL 2.3 in MacOS 11+.
59    if (@available(macOS 11.0, iOS 14.0, tvOS 14.0, *)) {
60        options.languageVersion = MTLLanguageVersion2_3;
61
62    // array<> is supported in MSL 2.0 on MacOS 10.13+ and iOS 11+,
63    // and in MSL 1.2 on iOS 10+ (but not MacOS).
64    } else if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
65        options.languageVersion = MTLLanguageVersion2_0;
66#if defined(SK_BUILD_FOR_IOS)
67    } else if (@available(macOS 10.12, iOS 10.0, tvOS 10.0, *)) {
68        options.languageVersion = MTLLanguageVersion1_2;
69#endif
70    }
71
72    NSError* error = nil;
73    // TODO: do we need a version with a timeout?
74    sk_cfp<id<MTLLibrary>> compiledLibrary(
75            [sharedContext->device() newLibraryWithSource:(NSString* _Nonnull)nsSource
76                                                  options:options
77                                                    error:&error]);
78    if (!compiledLibrary) {
79        std::string mslStr(msl);
80        errorHandler->compileError(
81                mslStr.c_str(), error.debugDescription.UTF8String, /*shaderWasCached=*/false);
82        return nil;
83    }
84
85    NSString* nsLabel = [[NSString alloc] initWithBytesNoCopy:const_cast<char*>(label.data())
86                                                       length:label.size()
87                                                     encoding:NSUTF8StringEncoding
88                                                 freeWhenDone:NO];
89    compiledLibrary.get().label = nsLabel;
90    return compiledLibrary;
91}
92
93} // namespace skgpu::graphite
94