xref: /aosp_15_r20/external/skia/src/gpu/ganesh/mtl/GrMtlResourceProvider.mm (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker/*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2018 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/mtl/GrMtlResourceProvider.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/ganesh/GrContextOptions.h"
11*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/ganesh/GrDirectContext.h"
12*c8dee2aaSAndroid Build Coastguard Worker#include "src/core/SkTraceEvent.h"
13*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/GrDirectContextPriv.h"
14*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/GrProgramDesc.h"
15*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/mtl/GrMtlCommandBuffer.h"
16*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/mtl/GrMtlGpu.h"
17*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/mtl/GrMtlPipelineState.h"
18*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/mtl/GrMtlUtil.h"
19*c8dee2aaSAndroid Build Coastguard Worker
20*c8dee2aaSAndroid Build Coastguard Worker#include "src/sksl/SkSLCompiler.h"
21*c8dee2aaSAndroid Build Coastguard Worker
22*c8dee2aaSAndroid Build Coastguard Worker#if !__has_feature(objc_arc)
23*c8dee2aaSAndroid Build Coastguard Worker#error This file must be compiled with Arc. Use -fobjc-arc flag
24*c8dee2aaSAndroid Build Coastguard Worker#endif
25*c8dee2aaSAndroid Build Coastguard Worker
26*c8dee2aaSAndroid Build Coastguard WorkerGR_NORETAIN_BEGIN
27*c8dee2aaSAndroid Build Coastguard Worker
28*c8dee2aaSAndroid Build Coastguard WorkerGrMtlResourceProvider::GrMtlResourceProvider(GrMtlGpu* gpu)
29*c8dee2aaSAndroid Build Coastguard Worker    : fGpu(gpu) {
30*c8dee2aaSAndroid Build Coastguard Worker    fPipelineStateCache = std::make_unique<PipelineStateCache>(gpu);
31*c8dee2aaSAndroid Build Coastguard Worker}
32*c8dee2aaSAndroid Build Coastguard Worker
33*c8dee2aaSAndroid Build Coastguard WorkerGrMtlPipelineState* GrMtlResourceProvider::findOrCreateCompatiblePipelineState(
34*c8dee2aaSAndroid Build Coastguard Worker        const GrProgramDesc& programDesc,
35*c8dee2aaSAndroid Build Coastguard Worker        const GrProgramInfo& programInfo,
36*c8dee2aaSAndroid Build Coastguard Worker        GrThreadSafePipelineBuilder::Stats::ProgramCacheResult* stat) {
37*c8dee2aaSAndroid Build Coastguard Worker    return fPipelineStateCache->refPipelineState(programDesc, programInfo, stat);
38*c8dee2aaSAndroid Build Coastguard Worker}
39*c8dee2aaSAndroid Build Coastguard Worker
40*c8dee2aaSAndroid Build Coastguard Workerbool GrMtlResourceProvider::precompileShader(const SkData& key, const SkData& data) {
41*c8dee2aaSAndroid Build Coastguard Worker    return fPipelineStateCache->precompileShader(key, data);
42*c8dee2aaSAndroid Build Coastguard Worker}
43*c8dee2aaSAndroid Build Coastguard Worker
44*c8dee2aaSAndroid Build Coastguard Worker////////////////////////////////////////////////////////////////////////////////////////////////
45*c8dee2aaSAndroid Build Coastguard Worker
46*c8dee2aaSAndroid Build Coastguard WorkerGrMtlDepthStencil* GrMtlResourceProvider::findOrCreateCompatibleDepthStencilState(
47*c8dee2aaSAndroid Build Coastguard Worker        const GrStencilSettings& stencil, GrSurfaceOrigin origin) {
48*c8dee2aaSAndroid Build Coastguard Worker    GrMtlDepthStencil* depthStencilState;
49*c8dee2aaSAndroid Build Coastguard Worker    GrMtlDepthStencil::Key key = GrMtlDepthStencil::GenerateKey(stencil, origin);
50*c8dee2aaSAndroid Build Coastguard Worker    depthStencilState = fDepthStencilStates.find(key);
51*c8dee2aaSAndroid Build Coastguard Worker    if (!depthStencilState) {
52*c8dee2aaSAndroid Build Coastguard Worker        depthStencilState = GrMtlDepthStencil::Create(fGpu, stencil, origin);
53*c8dee2aaSAndroid Build Coastguard Worker        fDepthStencilStates.add(depthStencilState);
54*c8dee2aaSAndroid Build Coastguard Worker    }
55*c8dee2aaSAndroid Build Coastguard Worker    SkASSERT(depthStencilState);
56*c8dee2aaSAndroid Build Coastguard Worker    return depthStencilState;
57*c8dee2aaSAndroid Build Coastguard Worker}
58*c8dee2aaSAndroid Build Coastguard Worker
59*c8dee2aaSAndroid Build Coastguard WorkerGrMtlSampler* GrMtlResourceProvider::findOrCreateCompatibleSampler(GrSamplerState params) {
60*c8dee2aaSAndroid Build Coastguard Worker    GrMtlSampler* sampler;
61*c8dee2aaSAndroid Build Coastguard Worker    sampler = fSamplers.find(GrMtlSampler::GenerateKey(params));
62*c8dee2aaSAndroid Build Coastguard Worker    if (!sampler) {
63*c8dee2aaSAndroid Build Coastguard Worker        sampler = GrMtlSampler::Create(fGpu, params);
64*c8dee2aaSAndroid Build Coastguard Worker        fSamplers.add(sampler);
65*c8dee2aaSAndroid Build Coastguard Worker    }
66*c8dee2aaSAndroid Build Coastguard Worker    SkASSERT(sampler);
67*c8dee2aaSAndroid Build Coastguard Worker    return sampler;
68*c8dee2aaSAndroid Build Coastguard Worker}
69*c8dee2aaSAndroid Build Coastguard Worker
70*c8dee2aaSAndroid Build Coastguard Workerconst GrMtlRenderPipeline* GrMtlResourceProvider::findOrCreateMSAALoadPipeline(
71*c8dee2aaSAndroid Build Coastguard Worker        MTLPixelFormat colorFormat, int sampleCount, MTLPixelFormat stencilFormat) {
72*c8dee2aaSAndroid Build Coastguard Worker    if (!fMSAALoadLibrary) {
73*c8dee2aaSAndroid Build Coastguard Worker        TRACE_EVENT0("skia", TRACE_FUNC);
74*c8dee2aaSAndroid Build Coastguard Worker
75*c8dee2aaSAndroid Build Coastguard Worker        std::string shaderText;
76*c8dee2aaSAndroid Build Coastguard Worker        shaderText.append(
77*c8dee2aaSAndroid Build Coastguard Worker                "#include <metal_stdlib>\n"
78*c8dee2aaSAndroid Build Coastguard Worker                "#include <simd/simd.h>\n"
79*c8dee2aaSAndroid Build Coastguard Worker                "using namespace metal;\n"
80*c8dee2aaSAndroid Build Coastguard Worker                "\n"
81*c8dee2aaSAndroid Build Coastguard Worker                "typedef struct {\n"
82*c8dee2aaSAndroid Build Coastguard Worker                "    float4 position [[position]];\n"
83*c8dee2aaSAndroid Build Coastguard Worker                "} VertexOutput;\n"
84*c8dee2aaSAndroid Build Coastguard Worker                "\n"
85*c8dee2aaSAndroid Build Coastguard Worker                "typedef struct {\n"
86*c8dee2aaSAndroid Build Coastguard Worker                "    float4 uPosXform;\n"
87*c8dee2aaSAndroid Build Coastguard Worker                "    uint2 uTextureSize;\n"
88*c8dee2aaSAndroid Build Coastguard Worker                "} VertexUniforms;\n"
89*c8dee2aaSAndroid Build Coastguard Worker                "\n"
90*c8dee2aaSAndroid Build Coastguard Worker                "vertex VertexOutput vertexMain(constant VertexUniforms& uniforms [[buffer(0)]],\n"
91*c8dee2aaSAndroid Build Coastguard Worker                "                               uint vertexID [[vertex_id]]) {\n"
92*c8dee2aaSAndroid Build Coastguard Worker                "    VertexOutput out;\n"
93*c8dee2aaSAndroid Build Coastguard Worker                "    float2 position = float2(float(vertexID >> 1), float(vertexID & 1));\n"
94*c8dee2aaSAndroid Build Coastguard Worker                "    out.position.xy = position * uniforms.uPosXform.xy + uniforms.uPosXform.zw;\n"
95*c8dee2aaSAndroid Build Coastguard Worker                "    out.position.zw = float2(0.0, 1.0);\n"
96*c8dee2aaSAndroid Build Coastguard Worker                "    return out;\n"
97*c8dee2aaSAndroid Build Coastguard Worker                "}\n"
98*c8dee2aaSAndroid Build Coastguard Worker                "\n"
99*c8dee2aaSAndroid Build Coastguard Worker                "fragment float4 fragmentMain(VertexOutput in [[stage_in]],\n"
100*c8dee2aaSAndroid Build Coastguard Worker                "                             texture2d<half> colorMap [[texture(0)]]) {\n"
101*c8dee2aaSAndroid Build Coastguard Worker                "    uint2 coords = uint2(in.position.x, in.position.y);"
102*c8dee2aaSAndroid Build Coastguard Worker                "    half4 colorSample   = colorMap.read(coords);\n"
103*c8dee2aaSAndroid Build Coastguard Worker                "    return float4(colorSample);\n"
104*c8dee2aaSAndroid Build Coastguard Worker                "}"
105*c8dee2aaSAndroid Build Coastguard Worker        );
106*c8dee2aaSAndroid Build Coastguard Worker
107*c8dee2aaSAndroid Build Coastguard Worker        auto errorHandler = fGpu->getContext()->priv().getShaderErrorHandler();
108*c8dee2aaSAndroid Build Coastguard Worker        fMSAALoadLibrary = GrCompileMtlShaderLibrary(fGpu, shaderText, errorHandler);
109*c8dee2aaSAndroid Build Coastguard Worker        if (!fMSAALoadLibrary) {
110*c8dee2aaSAndroid Build Coastguard Worker            return nullptr;
111*c8dee2aaSAndroid Build Coastguard Worker        }
112*c8dee2aaSAndroid Build Coastguard Worker    }
113*c8dee2aaSAndroid Build Coastguard Worker
114*c8dee2aaSAndroid Build Coastguard Worker    for (int i = 0; i < fMSAALoadPipelines.size(); ++i) {
115*c8dee2aaSAndroid Build Coastguard Worker        if (fMSAALoadPipelines[i].fColorFormat == colorFormat &&
116*c8dee2aaSAndroid Build Coastguard Worker            fMSAALoadPipelines[i].fSampleCount == sampleCount &&
117*c8dee2aaSAndroid Build Coastguard Worker            fMSAALoadPipelines[i].fStencilFormat == stencilFormat) {
118*c8dee2aaSAndroid Build Coastguard Worker            return fMSAALoadPipelines[i].fPipeline.get();
119*c8dee2aaSAndroid Build Coastguard Worker        }
120*c8dee2aaSAndroid Build Coastguard Worker    }
121*c8dee2aaSAndroid Build Coastguard Worker
122*c8dee2aaSAndroid Build Coastguard Worker    auto pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
123*c8dee2aaSAndroid Build Coastguard Worker
124*c8dee2aaSAndroid Build Coastguard Worker    pipelineDescriptor.label = @"loadMSAAFromResolve";
125*c8dee2aaSAndroid Build Coastguard Worker
126*c8dee2aaSAndroid Build Coastguard Worker    pipelineDescriptor.vertexFunction =
127*c8dee2aaSAndroid Build Coastguard Worker            [fMSAALoadLibrary newFunctionWithName: @"vertexMain"];
128*c8dee2aaSAndroid Build Coastguard Worker    pipelineDescriptor.fragmentFunction =
129*c8dee2aaSAndroid Build Coastguard Worker            [fMSAALoadLibrary newFunctionWithName: @"fragmentMain"];
130*c8dee2aaSAndroid Build Coastguard Worker
131*c8dee2aaSAndroid Build Coastguard Worker    auto mtlColorAttachment = [[MTLRenderPipelineColorAttachmentDescriptor alloc] init];
132*c8dee2aaSAndroid Build Coastguard Worker
133*c8dee2aaSAndroid Build Coastguard Worker    mtlColorAttachment.pixelFormat = colorFormat;
134*c8dee2aaSAndroid Build Coastguard Worker    mtlColorAttachment.blendingEnabled = FALSE;
135*c8dee2aaSAndroid Build Coastguard Worker    mtlColorAttachment.writeMask = MTLColorWriteMaskAll;
136*c8dee2aaSAndroid Build Coastguard Worker
137*c8dee2aaSAndroid Build Coastguard Worker    pipelineDescriptor.colorAttachments[0] = mtlColorAttachment;
138*c8dee2aaSAndroid Build Coastguard Worker    pipelineDescriptor.rasterSampleCount = sampleCount;
139*c8dee2aaSAndroid Build Coastguard Worker
140*c8dee2aaSAndroid Build Coastguard Worker    pipelineDescriptor.stencilAttachmentPixelFormat = stencilFormat;
141*c8dee2aaSAndroid Build Coastguard Worker
142*c8dee2aaSAndroid Build Coastguard Worker    NSError* error;
143*c8dee2aaSAndroid Build Coastguard Worker    auto pso =
144*c8dee2aaSAndroid Build Coastguard Worker            [fGpu->device() newRenderPipelineStateWithDescriptor: pipelineDescriptor
145*c8dee2aaSAndroid Build Coastguard Worker                                                          error: &error];
146*c8dee2aaSAndroid Build Coastguard Worker    if (!pso) {
147*c8dee2aaSAndroid Build Coastguard Worker        SkDebugf("Error creating pipeline: %s\n",
148*c8dee2aaSAndroid Build Coastguard Worker                 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
149*c8dee2aaSAndroid Build Coastguard Worker    }
150*c8dee2aaSAndroid Build Coastguard Worker
151*c8dee2aaSAndroid Build Coastguard Worker    auto renderPipeline = GrMtlRenderPipeline::Make(pso);
152*c8dee2aaSAndroid Build Coastguard Worker
153*c8dee2aaSAndroid Build Coastguard Worker    fMSAALoadPipelines.push_back({renderPipeline, colorFormat, sampleCount, stencilFormat});
154*c8dee2aaSAndroid Build Coastguard Worker    return fMSAALoadPipelines[fMSAALoadPipelines.size()-1].fPipeline.get();
155*c8dee2aaSAndroid Build Coastguard Worker}
156*c8dee2aaSAndroid Build Coastguard Worker
157*c8dee2aaSAndroid Build Coastguard Workervoid GrMtlResourceProvider::destroyResources() {
158*c8dee2aaSAndroid Build Coastguard Worker    fMSAALoadLibrary = nil;
159*c8dee2aaSAndroid Build Coastguard Worker    fMSAALoadPipelines.clear();
160*c8dee2aaSAndroid Build Coastguard Worker
161*c8dee2aaSAndroid Build Coastguard Worker    fSamplers.foreach([&](GrMtlSampler* sampler) { sampler->unref(); });
162*c8dee2aaSAndroid Build Coastguard Worker    fSamplers.reset();
163*c8dee2aaSAndroid Build Coastguard Worker
164*c8dee2aaSAndroid Build Coastguard Worker    fDepthStencilStates.foreach([&](GrMtlDepthStencil* stencil) { stencil->unref(); });
165*c8dee2aaSAndroid Build Coastguard Worker    fDepthStencilStates.reset();
166*c8dee2aaSAndroid Build Coastguard Worker
167*c8dee2aaSAndroid Build Coastguard Worker    fPipelineStateCache->release();
168*c8dee2aaSAndroid Build Coastguard Worker}
169*c8dee2aaSAndroid Build Coastguard Worker
170*c8dee2aaSAndroid Build Coastguard Worker////////////////////////////////////////////////////////////////////////////////////////////////
171*c8dee2aaSAndroid Build Coastguard Worker
172*c8dee2aaSAndroid Build Coastguard Workerstruct GrMtlResourceProvider::PipelineStateCache::Entry {
173*c8dee2aaSAndroid Build Coastguard Worker    Entry(GrMtlPipelineState* pipelineState)
174*c8dee2aaSAndroid Build Coastguard Worker            : fPipelineState(pipelineState) {}
175*c8dee2aaSAndroid Build Coastguard Worker    Entry(const GrMtlPrecompiledLibraries& precompiledLibraries)
176*c8dee2aaSAndroid Build Coastguard Worker            : fPipelineState(nullptr)
177*c8dee2aaSAndroid Build Coastguard Worker            , fPrecompiledLibraries(precompiledLibraries) {}
178*c8dee2aaSAndroid Build Coastguard Worker
179*c8dee2aaSAndroid Build Coastguard Worker    std::unique_ptr<GrMtlPipelineState> fPipelineState;
180*c8dee2aaSAndroid Build Coastguard Worker
181*c8dee2aaSAndroid Build Coastguard Worker    // TODO: change to one library once we can build that
182*c8dee2aaSAndroid Build Coastguard Worker    GrMtlPrecompiledLibraries fPrecompiledLibraries;
183*c8dee2aaSAndroid Build Coastguard Worker};
184*c8dee2aaSAndroid Build Coastguard Worker
185*c8dee2aaSAndroid Build Coastguard WorkerGrMtlResourceProvider::PipelineStateCache::PipelineStateCache(GrMtlGpu* gpu)
186*c8dee2aaSAndroid Build Coastguard Worker    : fMap(gpu->getContext()->priv().options().fRuntimeProgramCacheSize)
187*c8dee2aaSAndroid Build Coastguard Worker    , fGpu(gpu) {}
188*c8dee2aaSAndroid Build Coastguard Worker
189*c8dee2aaSAndroid Build Coastguard WorkerGrMtlResourceProvider::PipelineStateCache::~PipelineStateCache() {
190*c8dee2aaSAndroid Build Coastguard Worker    SkASSERT(0 == fMap.count());
191*c8dee2aaSAndroid Build Coastguard Worker}
192*c8dee2aaSAndroid Build Coastguard Worker
193*c8dee2aaSAndroid Build Coastguard Workervoid GrMtlResourceProvider::PipelineStateCache::release() {
194*c8dee2aaSAndroid Build Coastguard Worker    fMap.reset();
195*c8dee2aaSAndroid Build Coastguard Worker}
196*c8dee2aaSAndroid Build Coastguard Worker
197*c8dee2aaSAndroid Build Coastguard WorkerGrMtlPipelineState* GrMtlResourceProvider::PipelineStateCache::refPipelineState(
198*c8dee2aaSAndroid Build Coastguard Worker        const GrProgramDesc& desc,
199*c8dee2aaSAndroid Build Coastguard Worker        const GrProgramInfo& programInfo,
200*c8dee2aaSAndroid Build Coastguard Worker        Stats::ProgramCacheResult* statPtr) {
201*c8dee2aaSAndroid Build Coastguard Worker
202*c8dee2aaSAndroid Build Coastguard Worker    if (!statPtr) {
203*c8dee2aaSAndroid Build Coastguard Worker        // If stat is NULL we are using inline compilation rather than through DDL,
204*c8dee2aaSAndroid Build Coastguard Worker        // so we need to track those stats as well.
205*c8dee2aaSAndroid Build Coastguard Worker        GrThreadSafePipelineBuilder::Stats::ProgramCacheResult stat;
206*c8dee2aaSAndroid Build Coastguard Worker        auto tmp = this->onRefPipelineState(desc, programInfo, &stat);
207*c8dee2aaSAndroid Build Coastguard Worker        if (!tmp) {
208*c8dee2aaSAndroid Build Coastguard Worker            fStats.incNumInlineCompilationFailures();
209*c8dee2aaSAndroid Build Coastguard Worker        } else {
210*c8dee2aaSAndroid Build Coastguard Worker            fStats.incNumInlineProgramCacheResult(stat);
211*c8dee2aaSAndroid Build Coastguard Worker        }
212*c8dee2aaSAndroid Build Coastguard Worker        return tmp;
213*c8dee2aaSAndroid Build Coastguard Worker    } else {
214*c8dee2aaSAndroid Build Coastguard Worker        return this->onRefPipelineState(desc, programInfo, statPtr);
215*c8dee2aaSAndroid Build Coastguard Worker    }
216*c8dee2aaSAndroid Build Coastguard Worker}
217*c8dee2aaSAndroid Build Coastguard Worker
218*c8dee2aaSAndroid Build Coastguard WorkerGrMtlPipelineState* GrMtlResourceProvider::PipelineStateCache::onRefPipelineState(
219*c8dee2aaSAndroid Build Coastguard Worker        const GrProgramDesc& desc,
220*c8dee2aaSAndroid Build Coastguard Worker        const GrProgramInfo& programInfo,
221*c8dee2aaSAndroid Build Coastguard Worker        Stats::ProgramCacheResult* stat) {
222*c8dee2aaSAndroid Build Coastguard Worker    *stat = Stats::ProgramCacheResult::kHit;
223*c8dee2aaSAndroid Build Coastguard Worker    std::unique_ptr<Entry>* entry = fMap.find(desc);
224*c8dee2aaSAndroid Build Coastguard Worker    if (entry && !(*entry)->fPipelineState) {
225*c8dee2aaSAndroid Build Coastguard Worker        // We've pre-compiled the MSL shaders but don't yet have the pipelineState
226*c8dee2aaSAndroid Build Coastguard Worker        const GrMtlPrecompiledLibraries* precompiledLibs = &((*entry)->fPrecompiledLibraries);
227*c8dee2aaSAndroid Build Coastguard Worker        SkASSERT(precompiledLibs->fVertexLibrary);
228*c8dee2aaSAndroid Build Coastguard Worker        SkASSERT(precompiledLibs->fFragmentLibrary);
229*c8dee2aaSAndroid Build Coastguard Worker        (*entry)->fPipelineState.reset(
230*c8dee2aaSAndroid Build Coastguard Worker                GrMtlPipelineStateBuilder::CreatePipelineState(fGpu, desc, programInfo,
231*c8dee2aaSAndroid Build Coastguard Worker                                                               precompiledLibs));
232*c8dee2aaSAndroid Build Coastguard Worker        if (!(*entry)->fPipelineState) {
233*c8dee2aaSAndroid Build Coastguard Worker            // Should we purge the precompiled shaders from the cache at this point?
234*c8dee2aaSAndroid Build Coastguard Worker            SkDEBUGFAIL("Couldn't create pipelineState from precompiled shaders");
235*c8dee2aaSAndroid Build Coastguard Worker            fStats.incNumCompilationFailures();
236*c8dee2aaSAndroid Build Coastguard Worker            return nullptr;
237*c8dee2aaSAndroid Build Coastguard Worker        }
238*c8dee2aaSAndroid Build Coastguard Worker        // release the libraries
239*c8dee2aaSAndroid Build Coastguard Worker        (*entry)->fPrecompiledLibraries.fVertexLibrary = nil;
240*c8dee2aaSAndroid Build Coastguard Worker        (*entry)->fPrecompiledLibraries.fFragmentLibrary = nil;
241*c8dee2aaSAndroid Build Coastguard Worker
242*c8dee2aaSAndroid Build Coastguard Worker        fStats.incNumPartialCompilationSuccesses();
243*c8dee2aaSAndroid Build Coastguard Worker        *stat = Stats::ProgramCacheResult::kPartial;
244*c8dee2aaSAndroid Build Coastguard Worker    } else if (!entry) {
245*c8dee2aaSAndroid Build Coastguard Worker        GrMtlPipelineState* pipelineState(
246*c8dee2aaSAndroid Build Coastguard Worker                GrMtlPipelineStateBuilder::CreatePipelineState(fGpu, desc, programInfo));
247*c8dee2aaSAndroid Build Coastguard Worker        if (!pipelineState) {
248*c8dee2aaSAndroid Build Coastguard Worker            fStats.incNumCompilationFailures();
249*c8dee2aaSAndroid Build Coastguard Worker           return nullptr;
250*c8dee2aaSAndroid Build Coastguard Worker        }
251*c8dee2aaSAndroid Build Coastguard Worker        fStats.incNumCompilationSuccesses();
252*c8dee2aaSAndroid Build Coastguard Worker        entry = fMap.insert(desc, std::make_unique<Entry>(pipelineState));
253*c8dee2aaSAndroid Build Coastguard Worker        *stat = Stats::ProgramCacheResult::kMiss;
254*c8dee2aaSAndroid Build Coastguard Worker        return (*entry)->fPipelineState.get();
255*c8dee2aaSAndroid Build Coastguard Worker    }
256*c8dee2aaSAndroid Build Coastguard Worker    return (*entry)->fPipelineState.get();
257*c8dee2aaSAndroid Build Coastguard Worker}
258*c8dee2aaSAndroid Build Coastguard Worker
259*c8dee2aaSAndroid Build Coastguard Workerbool GrMtlResourceProvider::PipelineStateCache::precompileShader(const SkData& key,
260*c8dee2aaSAndroid Build Coastguard Worker                                                                 const SkData& data) {
261*c8dee2aaSAndroid Build Coastguard Worker    GrProgramDesc desc;
262*c8dee2aaSAndroid Build Coastguard Worker    if (!GrProgramDesc::BuildFromData(&desc, key.data(), key.size())) {
263*c8dee2aaSAndroid Build Coastguard Worker        return false;
264*c8dee2aaSAndroid Build Coastguard Worker    }
265*c8dee2aaSAndroid Build Coastguard Worker
266*c8dee2aaSAndroid Build Coastguard Worker    std::unique_ptr<Entry>* entry = fMap.find(desc);
267*c8dee2aaSAndroid Build Coastguard Worker    if (entry) {
268*c8dee2aaSAndroid Build Coastguard Worker        // We've already seen/compiled this shader
269*c8dee2aaSAndroid Build Coastguard Worker        return true;
270*c8dee2aaSAndroid Build Coastguard Worker    }
271*c8dee2aaSAndroid Build Coastguard Worker
272*c8dee2aaSAndroid Build Coastguard Worker    GrMtlPrecompiledLibraries precompiledLibraries;
273*c8dee2aaSAndroid Build Coastguard Worker    if (!GrMtlPipelineStateBuilder::PrecompileShaders(fGpu, data, &precompiledLibraries)) {
274*c8dee2aaSAndroid Build Coastguard Worker        return false;
275*c8dee2aaSAndroid Build Coastguard Worker    }
276*c8dee2aaSAndroid Build Coastguard Worker
277*c8dee2aaSAndroid Build Coastguard Worker    fMap.insert(desc, std::make_unique<Entry>(precompiledLibraries));
278*c8dee2aaSAndroid Build Coastguard Worker    return true;
279*c8dee2aaSAndroid Build Coastguard Worker
280*c8dee2aaSAndroid Build Coastguard Worker}
281*c8dee2aaSAndroid Build Coastguard Worker
282*c8dee2aaSAndroid Build Coastguard WorkerGR_NORETAIN_END
283