• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright 2021 Google LLC
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/MtlGpu.h"
9
10#include "experimental/graphite/include/BackendTexture.h"
11#include "experimental/graphite/include/TextureInfo.h"
12#include "experimental/graphite/src/Caps.h"
13#include "experimental/graphite/src/GlobalCache.h"
14#include "experimental/graphite/src/Log.h"
15#include "experimental/graphite/src/mtl/MtlCommandBuffer.h"
16#include "experimental/graphite/src/mtl/MtlResourceProvider.h"
17#include "experimental/graphite/src/mtl/MtlTexture.h"
18
19namespace skgpu::mtl {
20
21sk_sp<skgpu::Gpu> Gpu::Make(const BackendContext& context) {
22    // TODO: This was taken from GrMtlGpu.mm's Make, does graphite deserve a higher version?
23    if (@available(macOS 10.14, iOS 11.0, *)) {
24        // no warning needed
25    } else {
26        SKGPU_LOG_E("Skia's Graphite backend no longer supports this OS version.");
27#ifdef SK_BUILD_FOR_IOS
28        SKGPU_LOG_E("Minimum supported version is iOS 11.0.");
29#else
30        SKGPU_LOG_E("Minimum supported version is MacOS 10.14.");
31#endif
32        return nullptr;
33    }
34
35    sk_cfp<id<MTLDevice>> device = sk_ret_cfp((id<MTLDevice>)(context.fDevice.get()));
36    sk_cfp<id<MTLCommandQueue>> queue = sk_ret_cfp((id<MTLCommandQueue>)(context.fQueue.get()));
37
38    sk_sp<const Caps> caps(new Caps(device.get()));
39
40    return sk_sp<skgpu::Gpu>(new Gpu(std::move(device), std::move(queue), std::move(caps)));
41}
42
43Gpu::Gpu(sk_cfp<id<MTLDevice>> device, sk_cfp<id<MTLCommandQueue>> queue, sk_sp<const Caps> caps)
44    : skgpu::Gpu(std::move(caps))
45    , fDevice(std::move(device))
46    , fQueue(std::move(queue)) {
47    this->initCompiler();
48}
49
50Gpu::~Gpu() {
51}
52
53std::unique_ptr<skgpu::ResourceProvider> Gpu::makeResourceProvider(
54        sk_sp<GlobalCache> globalCache, SingleOwner* singleOwner) const {
55    return std::unique_ptr<skgpu::ResourceProvider>(new ResourceProvider(this,
56                                                                         std::move(globalCache),
57                                                                         singleOwner));
58}
59
60class WorkSubmission final : public skgpu::GpuWorkSubmission {
61public:
62    WorkSubmission(sk_sp<CommandBuffer> cmdBuffer)
63        : fCommandBuffer(std::move(cmdBuffer)) {}
64    ~WorkSubmission() override {}
65
66    bool isFinished() override {
67        return fCommandBuffer->isFinished();
68    }
69    void waitUntilFinished(const skgpu::Gpu*) override {
70        return fCommandBuffer->waitUntilFinished();
71    }
72
73private:
74    sk_sp<CommandBuffer> fCommandBuffer;
75};
76
77bool Gpu::onSubmit(sk_sp<skgpu::CommandBuffer> commandBuffer) {
78    SkASSERT(commandBuffer);
79    sk_sp<CommandBuffer>& mtlCmdBuffer = (sk_sp<CommandBuffer>&)(commandBuffer);
80    if (!mtlCmdBuffer->commit()) {
81        return false;
82    }
83
84    std::unique_ptr<WorkSubmission> submission(new WorkSubmission(mtlCmdBuffer));
85    new (fOutstandingSubmissions.push_back()) OutstandingSubmission(std::move(submission));
86
87    return true;
88}
89
90BackendTexture Gpu::onCreateBackendTexture(SkISize dimensions, const skgpu::TextureInfo& info) {
91    sk_cfp<id<MTLTexture>> texture = Texture::MakeMtlTexture(this, dimensions, info);
92    if (!texture) {
93        return {};
94    }
95    return BackendTexture(dimensions, (Handle)texture.release());
96}
97
98void Gpu::onDeleteBackendTexture(BackendTexture& texture) {
99    SkASSERT(texture.backend() == BackendApi::kMetal);
100    Handle texHandle = texture.getMtlTexture();
101    SkCFSafeRelease(texHandle);
102}
103
104#if GRAPHITE_TEST_UTILS
105void Gpu::testingOnly_startCapture() {
106    if (@available(macOS 10.13, iOS 11.0, *)) {
107        // TODO: add newer Metal interface as well
108        MTLCaptureManager* captureManager = [MTLCaptureManager sharedCaptureManager];
109        if (captureManager.isCapturing) {
110            return;
111        }
112        if (@available(macOS 10.15, iOS 13.0, *)) {
113            MTLCaptureDescriptor* captureDescriptor = [[MTLCaptureDescriptor alloc] init];
114            captureDescriptor.captureObject = fQueue.get();
115
116            NSError *error;
117            if (![captureManager startCaptureWithDescriptor: captureDescriptor error:&error])
118            {
119                NSLog(@"Failed to start capture, error %@", error);
120            }
121        } else {
122            [captureManager startCaptureWithCommandQueue: fQueue.get()];
123        }
124     }
125}
126
127void Gpu::testingOnly_endCapture() {
128    if (@available(macOS 10.13, iOS 11.0, *)) {
129        MTLCaptureManager* captureManager = [MTLCaptureManager sharedCaptureManager];
130        if (captureManager.isCapturing) {
131            [captureManager stopCapture];
132        }
133    }
134}
135#endif
136
137} // namespace skgpu::mtl
138