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