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/src/Caps.h" 11#include "experimental/graphite/src/mtl/MtlCommandBuffer.h" 12#include "experimental/graphite/src/mtl/MtlResourceProvider.h" 13 14namespace skgpu::mtl { 15 16sk_sp<skgpu::Gpu> Gpu::Make(const BackendContext& context) { 17 sk_cfp<id<MTLDevice>> device = sk_ret_cfp((id<MTLDevice>)(context.fDevice.get())); 18 sk_cfp<id<MTLCommandQueue>> queue = sk_ret_cfp((id<MTLCommandQueue>)(context.fQueue.get())); 19 20 sk_sp<const Caps> caps(new Caps(device.get())); 21 22 return sk_sp<skgpu::Gpu>(new Gpu(std::move(device), std::move(queue), std::move(caps))); 23} 24 25Gpu::Gpu(sk_cfp<id<MTLDevice>> device, sk_cfp<id<MTLCommandQueue>> queue, sk_sp<const Caps> caps) 26 : skgpu::Gpu(std::move(caps)) 27 , fDevice(std::move(device)) 28 , fQueue(std::move(queue)) { 29 fResourceProvider.reset(new ResourceProvider(this)); 30} 31 32Gpu::~Gpu() { 33} 34 35class WorkSubmission final : public skgpu::GpuWorkSubmission { 36public: 37 WorkSubmission(sk_sp<CommandBuffer> cmdBuffer) 38 : fCommandBuffer(std::move(cmdBuffer)) {} 39 ~WorkSubmission() override {} 40 41 bool isFinished() override { 42 return fCommandBuffer->isFinished(); 43 } 44 void waitUntilFinished(const skgpu::Gpu*) override { 45 return fCommandBuffer->waitUntilFinished(); 46 } 47 48private: 49 sk_sp<CommandBuffer> fCommandBuffer; 50}; 51 52bool Gpu::onSubmit(sk_sp<skgpu::CommandBuffer> commandBuffer) { 53 SkASSERT(commandBuffer); 54 sk_sp<CommandBuffer>& mtlCmdBuffer = (sk_sp<CommandBuffer>&)(commandBuffer); 55 if (!mtlCmdBuffer->commit()) { 56 return false; 57 } 58 59 std::unique_ptr<WorkSubmission> submission(new WorkSubmission(mtlCmdBuffer)); 60 new (fOutstandingSubmissions.push_back()) OutstandingSubmission(std::move(submission)); 61 62 return true; 63} 64 65#if GRAPHITE_TEST_UTILS 66void Gpu::testingOnly_startCapture() { 67 if (@available(macOS 10.13, iOS 11.0, *)) { 68 // TODO: add newer Metal interface as well 69 MTLCaptureManager* captureManager = [MTLCaptureManager sharedCaptureManager]; 70 if (captureManager.isCapturing) { 71 return; 72 } 73 if (@available(macOS 10.15, iOS 13.0, *)) { 74 MTLCaptureDescriptor* captureDescriptor = [[MTLCaptureDescriptor alloc] init]; 75 captureDescriptor.captureObject = fQueue.get(); 76 77 NSError *error; 78 if (![captureManager startCaptureWithDescriptor: captureDescriptor error:&error]) 79 { 80 NSLog(@"Failed to start capture, error %@", error); 81 } 82 } else { 83 [captureManager startCaptureWithCommandQueue: fQueue.get()]; 84 } 85 } 86} 87 88void Gpu::testingOnly_endCapture() { 89 if (@available(macOS 10.13, iOS 11.0, *)) { 90 MTLCaptureManager* captureManager = [MTLCaptureManager sharedCaptureManager]; 91 if (captureManager.isCapturing) { 92 [captureManager stopCapture]; 93 } 94 } 95} 96#endif 97 98} // namespace skgpu::mtl 99