• 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 "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