• 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/MtlGraphiteTypesUtils.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                                                  skgpu::Budgeted budgeted) {
80    return MtlTexture::Make(this->mtlSharedContext(), dimensions, info, budgeted);
81}
82
83sk_sp<Texture> MtlResourceProvider::onCreateWrappedTexture(const BackendTexture& texture) {
84    CFTypeRef mtlHandleTexture = BackendTextures::GetMtlTexture(texture);
85    if (!mtlHandleTexture) {
86        return nullptr;
87    }
88    sk_cfp<id<MTLTexture>> mtlTexture = sk_ret_cfp((id<MTLTexture>)mtlHandleTexture);
89    return MtlTexture::MakeWrapped(this->mtlSharedContext(), texture.dimensions(), texture.info(),
90                                   std::move(mtlTexture));
91}
92
93sk_sp<Buffer> MtlResourceProvider::createBuffer(size_t size,
94                                                BufferType type,
95                                                AccessPattern accessPattern) {
96    return MtlBuffer::Make(this->mtlSharedContext(), size, type, accessPattern);
97}
98
99sk_sp<Sampler> MtlResourceProvider::createSampler(const SamplerDesc& samplerDesc) {
100    return MtlSampler::Make(this->mtlSharedContext(),
101                            samplerDesc.samplingOptions(),
102                            samplerDesc.tileModeX(),
103                            samplerDesc.tileModeY());
104}
105
106namespace {
107MTLCompareFunction compare_op_to_mtl(CompareOp op) {
108    switch (op) {
109        case CompareOp::kAlways:
110            return MTLCompareFunctionAlways;
111        case CompareOp::kNever:
112            return MTLCompareFunctionNever;
113        case CompareOp::kGreater:
114            return MTLCompareFunctionGreater;
115        case CompareOp::kGEqual:
116            return MTLCompareFunctionGreaterEqual;
117        case CompareOp::kLess:
118            return MTLCompareFunctionLess;
119        case CompareOp::kLEqual:
120            return MTLCompareFunctionLessEqual;
121        case CompareOp::kEqual:
122            return MTLCompareFunctionEqual;
123        case CompareOp::kNotEqual:
124            return MTLCompareFunctionNotEqual;
125    }
126}
127
128MTLStencilOperation stencil_op_to_mtl(StencilOp op) {
129    switch (op) {
130        case StencilOp::kKeep:
131            return MTLStencilOperationKeep;
132        case StencilOp::kZero:
133            return MTLStencilOperationZero;
134        case StencilOp::kReplace:
135            return MTLStencilOperationReplace;
136        case StencilOp::kInvert:
137            return MTLStencilOperationInvert;
138        case StencilOp::kIncWrap:
139            return MTLStencilOperationIncrementWrap;
140        case StencilOp::kDecWrap:
141            return MTLStencilOperationDecrementWrap;
142        case StencilOp::kIncClamp:
143            return MTLStencilOperationIncrementClamp;
144        case StencilOp::kDecClamp:
145            return MTLStencilOperationDecrementClamp;
146    }
147}
148
149MTLStencilDescriptor* stencil_face_to_mtl(DepthStencilSettings::Face face) {
150    MTLStencilDescriptor* result = [[MTLStencilDescriptor alloc] init];
151    result.stencilCompareFunction = compare_op_to_mtl(face.fCompareOp);
152    result.readMask = face.fReadMask;
153    result.writeMask = face.fWriteMask;
154    result.depthStencilPassOperation = stencil_op_to_mtl(face.fDepthStencilPassOp);
155    result.stencilFailureOperation = stencil_op_to_mtl(face.fStencilFailOp);
156    return result;
157}
158}  // anonymous namespace
159
160sk_cfp<id<MTLDepthStencilState>> MtlResourceProvider::findOrCreateCompatibleDepthStencilState(
161            const DepthStencilSettings& depthStencilSettings) {
162    sk_cfp<id<MTLDepthStencilState>>* depthStencilState;
163    depthStencilState = fDepthStencilStates.find(depthStencilSettings);
164    if (!depthStencilState) {
165        MTLDepthStencilDescriptor* desc = [[MTLDepthStencilDescriptor alloc] init];
166        SkASSERT(depthStencilSettings.fDepthTestEnabled ||
167                 depthStencilSettings.fDepthCompareOp == CompareOp::kAlways);
168        desc.depthCompareFunction = compare_op_to_mtl(depthStencilSettings.fDepthCompareOp);
169        if (depthStencilSettings.fDepthTestEnabled) {
170            desc.depthWriteEnabled = depthStencilSettings.fDepthWriteEnabled;
171        }
172        if (depthStencilSettings.fStencilTestEnabled) {
173            desc.frontFaceStencil = stencil_face_to_mtl(depthStencilSettings.fFrontStencil);
174            desc.backFaceStencil = stencil_face_to_mtl(depthStencilSettings.fBackStencil);
175        }
176
177        sk_cfp<id<MTLDepthStencilState>> dss(
178                [this->mtlSharedContext()->device() newDepthStencilStateWithDescriptor: desc]);
179        depthStencilState = fDepthStencilStates.set(depthStencilSettings, std::move(dss));
180    }
181
182    SkASSERT(depthStencilState);
183    return *depthStencilState;
184}
185
186BackendTexture MtlResourceProvider::onCreateBackendTexture(SkISize dimensions,
187                                                           const TextureInfo& info) {
188    sk_cfp<id<MTLTexture>> texture = MtlTexture::MakeMtlTexture(this->mtlSharedContext(),
189                                                                dimensions,
190                                                                info);
191    if (!texture) {
192        return {};
193    }
194    return BackendTextures::MakeMetal(dimensions, (CFTypeRef)texture.release());
195}
196
197void MtlResourceProvider::onDeleteBackendTexture(const BackendTexture& texture) {
198    SkASSERT(texture.backend() == BackendApi::kMetal);
199    CFTypeRef texHandle = BackendTextures::GetMtlTexture(texture);
200    SkCFSafeRelease(texHandle);
201}
202
203} // namespace skgpu::graphite
204