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