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