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/MtlResourceProvider.h" 9 10#include "experimental/graphite/include/BackendTexture.h" 11#include "experimental/graphite/src/GlobalCache.h" 12#include "experimental/graphite/src/GraphicsPipelineDesc.h" 13#include "experimental/graphite/src/mtl/MtlBuffer.h" 14#include "experimental/graphite/src/mtl/MtlCommandBuffer.h" 15#include "experimental/graphite/src/mtl/MtlGpu.h" 16#include "experimental/graphite/src/mtl/MtlGraphicsPipeline.h" 17#include "experimental/graphite/src/mtl/MtlSampler.h" 18#include "experimental/graphite/src/mtl/MtlTexture.h" 19 20#import <Metal/Metal.h> 21 22namespace skgpu::mtl { 23 24ResourceProvider::ResourceProvider(const skgpu::Gpu* gpu, 25 sk_sp<GlobalCache> globalCache, 26 SingleOwner* singleOwner) 27 : skgpu::ResourceProvider(gpu, std::move(globalCache), singleOwner) { 28} 29 30const Gpu* ResourceProvider::mtlGpu() { 31 return static_cast<const Gpu*>(fGpu); 32} 33 34sk_sp<skgpu::CommandBuffer> ResourceProvider::createCommandBuffer() { 35 return CommandBuffer::Make(this->mtlGpu()); 36} 37 38sk_sp<skgpu::GraphicsPipeline> ResourceProvider::onCreateGraphicsPipeline( 39 const GraphicsPipelineDesc& pipelineDesc, 40 const RenderPassDesc& renderPassDesc) { 41 return GraphicsPipeline::Make(this, 42 this->mtlGpu(), 43 pipelineDesc, 44 renderPassDesc); 45} 46 47sk_sp<skgpu::Texture> ResourceProvider::createTexture(SkISize dimensions, 48 const skgpu::TextureInfo& info) { 49 return Texture::Make(this->mtlGpu(), dimensions, info); 50} 51 52sk_sp<skgpu::Texture> ResourceProvider::createWrappedTexture(const BackendTexture& texture) { 53 mtl::Handle mtlHandleTexture = texture.getMtlTexture(); 54 if (!mtlHandleTexture) { 55 return nullptr; 56 } 57 sk_cfp<id<MTLTexture>> mtlTexture = sk_ret_cfp((id<MTLTexture>)mtlHandleTexture); 58 return Texture::MakeWrapped(this->mtlGpu(), 59 texture.dimensions(), 60 texture.info(), 61 std::move(mtlTexture)); 62} 63 64sk_sp<skgpu::Buffer> ResourceProvider::createBuffer(size_t size, 65 BufferType type, 66 PrioritizeGpuReads prioritizeGpuReads) { 67 return Buffer::Make(this->mtlGpu(), size, type, prioritizeGpuReads); 68} 69 70sk_sp<skgpu::Sampler> ResourceProvider::createSampler(const SkSamplingOptions& samplingOptions, 71 SkTileMode xTileMode, 72 SkTileMode yTileMode) { 73 return Sampler::Make(this->mtlGpu(), samplingOptions, xTileMode, yTileMode); 74} 75 76namespace { 77MTLCompareFunction compare_op_to_mtl(CompareOp op) { 78 switch (op) { 79 case CompareOp::kAlways: 80 return MTLCompareFunctionAlways; 81 case CompareOp::kNever: 82 return MTLCompareFunctionNever; 83 case CompareOp::kGreater: 84 return MTLCompareFunctionGreater; 85 case CompareOp::kGEqual: 86 return MTLCompareFunctionGreaterEqual; 87 case CompareOp::kLess: 88 return MTLCompareFunctionLess; 89 case CompareOp::kLEqual: 90 return MTLCompareFunctionLessEqual; 91 case CompareOp::kEqual: 92 return MTLCompareFunctionEqual; 93 case CompareOp::kNotEqual: 94 return MTLCompareFunctionNotEqual; 95 } 96} 97 98MTLStencilOperation stencil_op_to_mtl(StencilOp op) { 99 switch (op) { 100 case StencilOp::kKeep: 101 return MTLStencilOperationKeep; 102 case StencilOp::kZero: 103 return MTLStencilOperationZero; 104 case StencilOp::kReplace: 105 return MTLStencilOperationReplace; 106 case StencilOp::kInvert: 107 return MTLStencilOperationInvert; 108 case StencilOp::kIncWrap: 109 return MTLStencilOperationIncrementWrap; 110 case StencilOp::kDecWrap: 111 return MTLStencilOperationDecrementWrap; 112 case StencilOp::kIncClamp: 113 return MTLStencilOperationIncrementClamp; 114 case StencilOp::kDecClamp: 115 return MTLStencilOperationDecrementClamp; 116 } 117} 118 119MTLStencilDescriptor* stencil_face_to_mtl(DepthStencilSettings::Face face) { 120 MTLStencilDescriptor* result = [[MTLStencilDescriptor alloc] init]; 121 result.stencilCompareFunction = compare_op_to_mtl(face.fCompareOp); 122 result.readMask = face.fReadMask; 123 result.writeMask = face.fWriteMask; 124 result.depthStencilPassOperation = stencil_op_to_mtl(face.fDepthStencilPassOp); 125 result.stencilFailureOperation = stencil_op_to_mtl(face.fStencilFailOp); 126 return result; 127} 128} // anonymous namespace 129 130id<MTLDepthStencilState> ResourceProvider::findOrCreateCompatibleDepthStencilState( 131 const DepthStencilSettings& depthStencilSettings) { 132 sk_cfp<id<MTLDepthStencilState>>* depthStencilState; 133 depthStencilState = fDepthStencilStates.find(depthStencilSettings); 134 if (!depthStencilState) { 135 MTLDepthStencilDescriptor* desc = [[MTLDepthStencilDescriptor alloc] init]; 136 SkASSERT(depthStencilSettings.fDepthTestEnabled || 137 depthStencilSettings.fDepthCompareOp == CompareOp::kAlways); 138 desc.depthCompareFunction = compare_op_to_mtl(depthStencilSettings.fDepthCompareOp); 139 if (depthStencilSettings.fDepthTestEnabled) { 140 desc.depthWriteEnabled = depthStencilSettings.fDepthWriteEnabled; 141 } 142 if (depthStencilSettings.fStencilTestEnabled) { 143 desc.frontFaceStencil = stencil_face_to_mtl(depthStencilSettings.fFrontStencil); 144 desc.backFaceStencil = stencil_face_to_mtl(depthStencilSettings.fBackStencil); 145 } 146 147 sk_cfp<id<MTLDepthStencilState>> dss( 148 [this->mtlGpu()->device() newDepthStencilStateWithDescriptor: desc]); 149 depthStencilState = fDepthStencilStates.set(depthStencilSettings, std::move(dss)); 150 } 151 152 SkASSERT(depthStencilState); 153 return depthStencilState->get(); 154} 155 156} // namespace skgpu::mtl 157