1*c8dee2aaSAndroid Build Coastguard Worker/* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2021 Google LLC 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/mtl/MtlResourceProvider.h" 9*c8dee2aaSAndroid Build Coastguard Worker 10*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/ShaderErrorHandler.h" 11*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/graphite/BackendTexture.h" 12*c8dee2aaSAndroid Build Coastguard Worker#include "src/sksl/SkSLProgramKind.h" 13*c8dee2aaSAndroid Build Coastguard Worker 14*c8dee2aaSAndroid Build Coastguard Worker#include "src/core/SkSLTypeShared.h" 15*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/Blend.h" 16*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/Swizzle.h" 17*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/GlobalCache.h" 18*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/RenderPassDesc.h" 19*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/Renderer.h" 20*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/mtl/MtlBuffer.h" 21*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/mtl/MtlCommandBuffer.h" 22*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/mtl/MtlComputePipeline.h" 23*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/mtl/MtlGraphicsPipeline.h" 24*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/mtl/MtlSampler.h" 25*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/mtl/MtlSharedContext.h" 26*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/mtl/MtlTexture.h" 27*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/mtl/MtlUtilsPriv.h" 28*c8dee2aaSAndroid Build Coastguard Worker 29*c8dee2aaSAndroid Build Coastguard Worker#import <Metal/Metal.h> 30*c8dee2aaSAndroid Build Coastguard Worker 31*c8dee2aaSAndroid Build Coastguard Workernamespace skgpu::graphite { 32*c8dee2aaSAndroid Build Coastguard Worker 33*c8dee2aaSAndroid Build Coastguard WorkerMtlResourceProvider::MtlResourceProvider(SharedContext* sharedContext, 34*c8dee2aaSAndroid Build Coastguard Worker SingleOwner* singleOwner, 35*c8dee2aaSAndroid Build Coastguard Worker uint32_t recorderID, 36*c8dee2aaSAndroid Build Coastguard Worker size_t resourceBudget) 37*c8dee2aaSAndroid Build Coastguard Worker : ResourceProvider(sharedContext, singleOwner, recorderID, resourceBudget) {} 38*c8dee2aaSAndroid Build Coastguard Worker 39*c8dee2aaSAndroid Build Coastguard Workerconst MtlSharedContext* MtlResourceProvider::mtlSharedContext() { 40*c8dee2aaSAndroid Build Coastguard Worker return static_cast<const MtlSharedContext*>(fSharedContext); 41*c8dee2aaSAndroid Build Coastguard Worker} 42*c8dee2aaSAndroid Build Coastguard Worker 43*c8dee2aaSAndroid Build Coastguard Workersk_sp<MtlGraphicsPipeline> MtlResourceProvider::findOrCreateLoadMSAAPipeline( 44*c8dee2aaSAndroid Build Coastguard Worker const RenderPassDesc& renderPassDesc) { 45*c8dee2aaSAndroid Build Coastguard Worker uint64_t renderPassKey = 46*c8dee2aaSAndroid Build Coastguard Worker this->mtlSharedContext()->mtlCaps().getRenderPassDescKey(renderPassDesc); 47*c8dee2aaSAndroid Build Coastguard Worker sk_sp<MtlGraphicsPipeline> pipeline = fLoadMSAAPipelines[renderPassKey]; 48*c8dee2aaSAndroid Build Coastguard Worker if (!pipeline) { 49*c8dee2aaSAndroid Build Coastguard Worker pipeline = MtlGraphicsPipeline::MakeLoadMSAAPipeline(this->mtlSharedContext(), this, 50*c8dee2aaSAndroid Build Coastguard Worker renderPassDesc); 51*c8dee2aaSAndroid Build Coastguard Worker if (pipeline) { 52*c8dee2aaSAndroid Build Coastguard Worker fLoadMSAAPipelines.set(renderPassKey, pipeline); 53*c8dee2aaSAndroid Build Coastguard Worker } 54*c8dee2aaSAndroid Build Coastguard Worker } 55*c8dee2aaSAndroid Build Coastguard Worker 56*c8dee2aaSAndroid Build Coastguard Worker return pipeline; 57*c8dee2aaSAndroid Build Coastguard Worker} 58*c8dee2aaSAndroid Build Coastguard Worker 59*c8dee2aaSAndroid Build Coastguard Workersk_sp<GraphicsPipeline> MtlResourceProvider::createGraphicsPipeline( 60*c8dee2aaSAndroid Build Coastguard Worker const RuntimeEffectDictionary* runtimeDict, 61*c8dee2aaSAndroid Build Coastguard Worker const GraphicsPipelineDesc& pipelineDesc, 62*c8dee2aaSAndroid Build Coastguard Worker const RenderPassDesc& renderPassDesc, 63*c8dee2aaSAndroid Build Coastguard Worker SkEnumBitMask<PipelineCreationFlags> pipelineCreationFlags) { 64*c8dee2aaSAndroid Build Coastguard Worker return MtlGraphicsPipeline::Make(this->mtlSharedContext(), this, 65*c8dee2aaSAndroid Build Coastguard Worker runtimeDict, pipelineDesc, renderPassDesc, 66*c8dee2aaSAndroid Build Coastguard Worker pipelineCreationFlags); 67*c8dee2aaSAndroid Build Coastguard Worker} 68*c8dee2aaSAndroid Build Coastguard Worker 69*c8dee2aaSAndroid Build Coastguard Workersk_sp<ComputePipeline> MtlResourceProvider::createComputePipeline( 70*c8dee2aaSAndroid Build Coastguard Worker const ComputePipelineDesc& pipelineDesc) { 71*c8dee2aaSAndroid Build Coastguard Worker return MtlComputePipeline::Make(this->mtlSharedContext(), pipelineDesc); 72*c8dee2aaSAndroid Build Coastguard Worker} 73*c8dee2aaSAndroid Build Coastguard Worker 74*c8dee2aaSAndroid Build Coastguard Workersk_sp<Texture> MtlResourceProvider::createTexture(SkISize dimensions, 75*c8dee2aaSAndroid Build Coastguard Worker const TextureInfo& info, 76*c8dee2aaSAndroid Build Coastguard Worker skgpu::Budgeted budgeted) { 77*c8dee2aaSAndroid Build Coastguard Worker return MtlTexture::Make(this->mtlSharedContext(), dimensions, info, budgeted); 78*c8dee2aaSAndroid Build Coastguard Worker} 79*c8dee2aaSAndroid Build Coastguard Worker 80*c8dee2aaSAndroid Build Coastguard Workersk_sp<Texture> MtlResourceProvider::onCreateWrappedTexture(const BackendTexture& texture) { 81*c8dee2aaSAndroid Build Coastguard Worker CFTypeRef mtlHandleTexture = BackendTextures::GetMtlTexture(texture); 82*c8dee2aaSAndroid Build Coastguard Worker if (!mtlHandleTexture) { 83*c8dee2aaSAndroid Build Coastguard Worker return nullptr; 84*c8dee2aaSAndroid Build Coastguard Worker } 85*c8dee2aaSAndroid Build Coastguard Worker sk_cfp<id<MTLTexture>> mtlTexture = sk_ret_cfp((id<MTLTexture>)mtlHandleTexture); 86*c8dee2aaSAndroid Build Coastguard Worker return MtlTexture::MakeWrapped(this->mtlSharedContext(), texture.dimensions(), texture.info(), 87*c8dee2aaSAndroid Build Coastguard Worker std::move(mtlTexture)); 88*c8dee2aaSAndroid Build Coastguard Worker} 89*c8dee2aaSAndroid Build Coastguard Worker 90*c8dee2aaSAndroid Build Coastguard Workersk_sp<Buffer> MtlResourceProvider::createBuffer(size_t size, 91*c8dee2aaSAndroid Build Coastguard Worker BufferType type, 92*c8dee2aaSAndroid Build Coastguard Worker AccessPattern accessPattern) { 93*c8dee2aaSAndroid Build Coastguard Worker return MtlBuffer::Make(this->mtlSharedContext(), size, type, accessPattern); 94*c8dee2aaSAndroid Build Coastguard Worker} 95*c8dee2aaSAndroid Build Coastguard Worker 96*c8dee2aaSAndroid Build Coastguard Workersk_sp<Sampler> MtlResourceProvider::createSampler(const SamplerDesc& samplerDesc) { 97*c8dee2aaSAndroid Build Coastguard Worker return MtlSampler::Make(this->mtlSharedContext(), 98*c8dee2aaSAndroid Build Coastguard Worker samplerDesc.samplingOptions(), 99*c8dee2aaSAndroid Build Coastguard Worker samplerDesc.tileModeX(), 100*c8dee2aaSAndroid Build Coastguard Worker samplerDesc.tileModeY()); 101*c8dee2aaSAndroid Build Coastguard Worker} 102*c8dee2aaSAndroid Build Coastguard Worker 103*c8dee2aaSAndroid Build Coastguard Workernamespace { 104*c8dee2aaSAndroid Build Coastguard WorkerMTLCompareFunction compare_op_to_mtl(CompareOp op) { 105*c8dee2aaSAndroid Build Coastguard Worker switch (op) { 106*c8dee2aaSAndroid Build Coastguard Worker case CompareOp::kAlways: 107*c8dee2aaSAndroid Build Coastguard Worker return MTLCompareFunctionAlways; 108*c8dee2aaSAndroid Build Coastguard Worker case CompareOp::kNever: 109*c8dee2aaSAndroid Build Coastguard Worker return MTLCompareFunctionNever; 110*c8dee2aaSAndroid Build Coastguard Worker case CompareOp::kGreater: 111*c8dee2aaSAndroid Build Coastguard Worker return MTLCompareFunctionGreater; 112*c8dee2aaSAndroid Build Coastguard Worker case CompareOp::kGEqual: 113*c8dee2aaSAndroid Build Coastguard Worker return MTLCompareFunctionGreaterEqual; 114*c8dee2aaSAndroid Build Coastguard Worker case CompareOp::kLess: 115*c8dee2aaSAndroid Build Coastguard Worker return MTLCompareFunctionLess; 116*c8dee2aaSAndroid Build Coastguard Worker case CompareOp::kLEqual: 117*c8dee2aaSAndroid Build Coastguard Worker return MTLCompareFunctionLessEqual; 118*c8dee2aaSAndroid Build Coastguard Worker case CompareOp::kEqual: 119*c8dee2aaSAndroid Build Coastguard Worker return MTLCompareFunctionEqual; 120*c8dee2aaSAndroid Build Coastguard Worker case CompareOp::kNotEqual: 121*c8dee2aaSAndroid Build Coastguard Worker return MTLCompareFunctionNotEqual; 122*c8dee2aaSAndroid Build Coastguard Worker } 123*c8dee2aaSAndroid Build Coastguard Worker} 124*c8dee2aaSAndroid Build Coastguard Worker 125*c8dee2aaSAndroid Build Coastguard WorkerMTLStencilOperation stencil_op_to_mtl(StencilOp op) { 126*c8dee2aaSAndroid Build Coastguard Worker switch (op) { 127*c8dee2aaSAndroid Build Coastguard Worker case StencilOp::kKeep: 128*c8dee2aaSAndroid Build Coastguard Worker return MTLStencilOperationKeep; 129*c8dee2aaSAndroid Build Coastguard Worker case StencilOp::kZero: 130*c8dee2aaSAndroid Build Coastguard Worker return MTLStencilOperationZero; 131*c8dee2aaSAndroid Build Coastguard Worker case StencilOp::kReplace: 132*c8dee2aaSAndroid Build Coastguard Worker return MTLStencilOperationReplace; 133*c8dee2aaSAndroid Build Coastguard Worker case StencilOp::kInvert: 134*c8dee2aaSAndroid Build Coastguard Worker return MTLStencilOperationInvert; 135*c8dee2aaSAndroid Build Coastguard Worker case StencilOp::kIncWrap: 136*c8dee2aaSAndroid Build Coastguard Worker return MTLStencilOperationIncrementWrap; 137*c8dee2aaSAndroid Build Coastguard Worker case StencilOp::kDecWrap: 138*c8dee2aaSAndroid Build Coastguard Worker return MTLStencilOperationDecrementWrap; 139*c8dee2aaSAndroid Build Coastguard Worker case StencilOp::kIncClamp: 140*c8dee2aaSAndroid Build Coastguard Worker return MTLStencilOperationIncrementClamp; 141*c8dee2aaSAndroid Build Coastguard Worker case StencilOp::kDecClamp: 142*c8dee2aaSAndroid Build Coastguard Worker return MTLStencilOperationDecrementClamp; 143*c8dee2aaSAndroid Build Coastguard Worker } 144*c8dee2aaSAndroid Build Coastguard Worker} 145*c8dee2aaSAndroid Build Coastguard Worker 146*c8dee2aaSAndroid Build Coastguard WorkerMTLStencilDescriptor* stencil_face_to_mtl(DepthStencilSettings::Face face) { 147*c8dee2aaSAndroid Build Coastguard Worker MTLStencilDescriptor* result = [[MTLStencilDescriptor alloc] init]; 148*c8dee2aaSAndroid Build Coastguard Worker result.stencilCompareFunction = compare_op_to_mtl(face.fCompareOp); 149*c8dee2aaSAndroid Build Coastguard Worker result.readMask = face.fReadMask; 150*c8dee2aaSAndroid Build Coastguard Worker result.writeMask = face.fWriteMask; 151*c8dee2aaSAndroid Build Coastguard Worker result.depthStencilPassOperation = stencil_op_to_mtl(face.fDepthStencilPassOp); 152*c8dee2aaSAndroid Build Coastguard Worker result.stencilFailureOperation = stencil_op_to_mtl(face.fStencilFailOp); 153*c8dee2aaSAndroid Build Coastguard Worker return result; 154*c8dee2aaSAndroid Build Coastguard Worker} 155*c8dee2aaSAndroid Build Coastguard Worker} // anonymous namespace 156*c8dee2aaSAndroid Build Coastguard Worker 157*c8dee2aaSAndroid Build Coastguard Workersk_cfp<id<MTLDepthStencilState>> MtlResourceProvider::findOrCreateCompatibleDepthStencilState( 158*c8dee2aaSAndroid Build Coastguard Worker const DepthStencilSettings& depthStencilSettings) { 159*c8dee2aaSAndroid Build Coastguard Worker sk_cfp<id<MTLDepthStencilState>>* depthStencilState; 160*c8dee2aaSAndroid Build Coastguard Worker depthStencilState = fDepthStencilStates.find(depthStencilSettings); 161*c8dee2aaSAndroid Build Coastguard Worker if (!depthStencilState) { 162*c8dee2aaSAndroid Build Coastguard Worker MTLDepthStencilDescriptor* desc = [[MTLDepthStencilDescriptor alloc] init]; 163*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(depthStencilSettings.fDepthTestEnabled || 164*c8dee2aaSAndroid Build Coastguard Worker depthStencilSettings.fDepthCompareOp == CompareOp::kAlways); 165*c8dee2aaSAndroid Build Coastguard Worker desc.depthCompareFunction = compare_op_to_mtl(depthStencilSettings.fDepthCompareOp); 166*c8dee2aaSAndroid Build Coastguard Worker if (depthStencilSettings.fDepthTestEnabled) { 167*c8dee2aaSAndroid Build Coastguard Worker desc.depthWriteEnabled = depthStencilSettings.fDepthWriteEnabled; 168*c8dee2aaSAndroid Build Coastguard Worker } 169*c8dee2aaSAndroid Build Coastguard Worker if (depthStencilSettings.fStencilTestEnabled) { 170*c8dee2aaSAndroid Build Coastguard Worker desc.frontFaceStencil = stencil_face_to_mtl(depthStencilSettings.fFrontStencil); 171*c8dee2aaSAndroid Build Coastguard Worker desc.backFaceStencil = stencil_face_to_mtl(depthStencilSettings.fBackStencil); 172*c8dee2aaSAndroid Build Coastguard Worker } 173*c8dee2aaSAndroid Build Coastguard Worker 174*c8dee2aaSAndroid Build Coastguard Worker sk_cfp<id<MTLDepthStencilState>> dss( 175*c8dee2aaSAndroid Build Coastguard Worker [this->mtlSharedContext()->device() newDepthStencilStateWithDescriptor: desc]); 176*c8dee2aaSAndroid Build Coastguard Worker depthStencilState = fDepthStencilStates.set(depthStencilSettings, std::move(dss)); 177*c8dee2aaSAndroid Build Coastguard Worker } 178*c8dee2aaSAndroid Build Coastguard Worker 179*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(depthStencilState); 180*c8dee2aaSAndroid Build Coastguard Worker return *depthStencilState; 181*c8dee2aaSAndroid Build Coastguard Worker} 182*c8dee2aaSAndroid Build Coastguard Worker 183*c8dee2aaSAndroid Build Coastguard WorkerBackendTexture MtlResourceProvider::onCreateBackendTexture(SkISize dimensions, 184*c8dee2aaSAndroid Build Coastguard Worker const TextureInfo& info) { 185*c8dee2aaSAndroid Build Coastguard Worker sk_cfp<id<MTLTexture>> texture = MtlTexture::MakeMtlTexture(this->mtlSharedContext(), 186*c8dee2aaSAndroid Build Coastguard Worker dimensions, 187*c8dee2aaSAndroid Build Coastguard Worker info); 188*c8dee2aaSAndroid Build Coastguard Worker if (!texture) { 189*c8dee2aaSAndroid Build Coastguard Worker return {}; 190*c8dee2aaSAndroid Build Coastguard Worker } 191*c8dee2aaSAndroid Build Coastguard Worker return BackendTextures::MakeMetal(dimensions, (CFTypeRef)texture.release()); 192*c8dee2aaSAndroid Build Coastguard Worker} 193*c8dee2aaSAndroid Build Coastguard Worker 194*c8dee2aaSAndroid Build Coastguard Workervoid MtlResourceProvider::onDeleteBackendTexture(const BackendTexture& texture) { 195*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(texture.backend() == BackendApi::kMetal); 196*c8dee2aaSAndroid Build Coastguard Worker CFTypeRef texHandle = BackendTextures::GetMtlTexture(texture); 197*c8dee2aaSAndroid Build Coastguard Worker SkCFSafeRelease(texHandle); 198*c8dee2aaSAndroid Build Coastguard Worker} 199*c8dee2aaSAndroid Build Coastguard Worker 200*c8dee2aaSAndroid Build Coastguard Worker} // namespace skgpu::graphite 201