xref: /aosp_15_r20/external/skia/src/gpu/ganesh/mtl/GrMtlPipelineStateBuilder.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/GrMtlPipelineStateBuilder.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/ganesh/GrDirectContext.h"
11*c8dee2aaSAndroid Build Coastguard Worker#include "src/core/SkReadBuffer.h"
12*c8dee2aaSAndroid Build Coastguard Worker#include "src/core/SkTraceEvent.h"
13*c8dee2aaSAndroid Build Coastguard Worker#include "src/core/SkWriteBuffer.h"
14*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/SkSLToBackend.h"
15*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/GrAutoLocaleSetter.h"
16*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/GrDirectContextPriv.h"
17*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/GrPersistentCacheUtils.h"
18*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/GrRenderTarget.h"
19*c8dee2aaSAndroid Build Coastguard Worker#include "src/sksl/SkSLProgramKind.h"
20*c8dee2aaSAndroid Build Coastguard Worker#include "src/sksl/SkSLProgramSettings.h"
21*c8dee2aaSAndroid Build Coastguard Worker#include "src/utils/SkShaderUtils.h"
22*c8dee2aaSAndroid Build Coastguard Worker
23*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/mtl/GrMtlGpu.h"
24*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/mtl/GrMtlPipelineState.h"
25*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/mtl/GrMtlUtil.h"
26*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/mtl/MtlUtilsPriv.h"
27*c8dee2aaSAndroid Build Coastguard Worker
28*c8dee2aaSAndroid Build Coastguard Worker#import <simd/simd.h>
29*c8dee2aaSAndroid Build Coastguard Worker
30*c8dee2aaSAndroid Build Coastguard Worker#if !__has_feature(objc_arc)
31*c8dee2aaSAndroid Build Coastguard Worker#error This file must be compiled with Arc. Use -fobjc-arc flag
32*c8dee2aaSAndroid Build Coastguard Worker#endif
33*c8dee2aaSAndroid Build Coastguard Worker
34*c8dee2aaSAndroid Build Coastguard WorkerGR_NORETAIN_BEGIN
35*c8dee2aaSAndroid Build Coastguard Worker
36*c8dee2aaSAndroid Build Coastguard WorkerGrMtlPipelineState* GrMtlPipelineStateBuilder::CreatePipelineState(
37*c8dee2aaSAndroid Build Coastguard Worker        GrMtlGpu* gpu, const GrProgramDesc& desc, const GrProgramInfo& programInfo,
38*c8dee2aaSAndroid Build Coastguard Worker        const GrMtlPrecompiledLibraries* precompiledLibs) {
39*c8dee2aaSAndroid Build Coastguard Worker    GrAutoLocaleSetter als("C");
40*c8dee2aaSAndroid Build Coastguard Worker    GrMtlPipelineStateBuilder builder(gpu, desc, programInfo);
41*c8dee2aaSAndroid Build Coastguard Worker
42*c8dee2aaSAndroid Build Coastguard Worker    if (!builder.emitAndInstallProcs()) {
43*c8dee2aaSAndroid Build Coastguard Worker        return nullptr;
44*c8dee2aaSAndroid Build Coastguard Worker    }
45*c8dee2aaSAndroid Build Coastguard Worker    return builder.finalize(desc, programInfo, precompiledLibs);
46*c8dee2aaSAndroid Build Coastguard Worker}
47*c8dee2aaSAndroid Build Coastguard Worker
48*c8dee2aaSAndroid Build Coastguard WorkerGrMtlPipelineStateBuilder::GrMtlPipelineStateBuilder(GrMtlGpu* gpu,
49*c8dee2aaSAndroid Build Coastguard Worker                                                     const GrProgramDesc& desc,
50*c8dee2aaSAndroid Build Coastguard Worker                                                     const GrProgramInfo& programInfo)
51*c8dee2aaSAndroid Build Coastguard Worker        : INHERITED(desc, programInfo)
52*c8dee2aaSAndroid Build Coastguard Worker        , fGpu(gpu)
53*c8dee2aaSAndroid Build Coastguard Worker        , fUniformHandler(this)
54*c8dee2aaSAndroid Build Coastguard Worker        , fVaryingHandler(this) {
55*c8dee2aaSAndroid Build Coastguard Worker}
56*c8dee2aaSAndroid Build Coastguard Worker
57*c8dee2aaSAndroid Build Coastguard Workerconst GrCaps* GrMtlPipelineStateBuilder::caps() const {
58*c8dee2aaSAndroid Build Coastguard Worker    return fGpu->caps();
59*c8dee2aaSAndroid Build Coastguard Worker}
60*c8dee2aaSAndroid Build Coastguard Worker
61*c8dee2aaSAndroid Build Coastguard Workervoid GrMtlPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
62*c8dee2aaSAndroid Build Coastguard Worker    outputColor.addLayoutQualifier("location = 0, index = 1");
63*c8dee2aaSAndroid Build Coastguard Worker}
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Workerstatic constexpr SkFourByteTag kMSL_Tag = SkSetFourByteTag('M', 'S', 'L', ' ');
66*c8dee2aaSAndroid Build Coastguard Workerstatic constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
67*c8dee2aaSAndroid Build Coastguard Worker
68*c8dee2aaSAndroid Build Coastguard Workervoid GrMtlPipelineStateBuilder::storeShadersInCache(const std::string shaders[],
69*c8dee2aaSAndroid Build Coastguard Worker                                                    const SkSL::Program::Interface interfaces[],
70*c8dee2aaSAndroid Build Coastguard Worker                                                    SkSL::ProgramSettings* settings,
71*c8dee2aaSAndroid Build Coastguard Worker                                                    sk_sp<SkData> pipelineData,
72*c8dee2aaSAndroid Build Coastguard Worker                                                    bool isSkSL) {
73*c8dee2aaSAndroid Build Coastguard Worker    sk_sp<SkData> key = SkData::MakeWithoutCopy(this->desc().asKey(),
74*c8dee2aaSAndroid Build Coastguard Worker                                                this->desc().keyLength());
75*c8dee2aaSAndroid Build Coastguard Worker    SkString description = GrProgramDesc::Describe(fProgramInfo, *this->caps());
76*c8dee2aaSAndroid Build Coastguard Worker    // cache metadata to allow for a complete precompile in either case
77*c8dee2aaSAndroid Build Coastguard Worker    GrPersistentCacheUtils::ShaderMetadata meta;
78*c8dee2aaSAndroid Build Coastguard Worker    meta.fSettings = settings;
79*c8dee2aaSAndroid Build Coastguard Worker    meta.fPlatformData = std::move(pipelineData);
80*c8dee2aaSAndroid Build Coastguard Worker    SkFourByteTag tag = isSkSL ? kSKSL_Tag : kMSL_Tag;
81*c8dee2aaSAndroid Build Coastguard Worker    sk_sp<SkData> data = GrPersistentCacheUtils::PackCachedShaders(tag, shaders, interfaces,
82*c8dee2aaSAndroid Build Coastguard Worker                                                                   kGrShaderTypeCount, &meta);
83*c8dee2aaSAndroid Build Coastguard Worker    fGpu->getContext()->priv().getPersistentCache()->store(*key, *data, description);
84*c8dee2aaSAndroid Build Coastguard Worker}
85*c8dee2aaSAndroid Build Coastguard Worker
86*c8dee2aaSAndroid Build Coastguard Workerid<MTLLibrary> GrMtlPipelineStateBuilder::compileMtlShaderLibrary(
87*c8dee2aaSAndroid Build Coastguard Worker        const std::string& shader,
88*c8dee2aaSAndroid Build Coastguard Worker        SkSL::Program::Interface interface,
89*c8dee2aaSAndroid Build Coastguard Worker        GrContextOptions::ShaderErrorHandler* errorHandler) {
90*c8dee2aaSAndroid Build Coastguard Worker    id<MTLLibrary> shaderLibrary = GrCompileMtlShaderLibrary(fGpu, shader, errorHandler);
91*c8dee2aaSAndroid Build Coastguard Worker    if (shaderLibrary != nil &&
92*c8dee2aaSAndroid Build Coastguard Worker        interface.fRTFlipUniform != SkSL::Program::Interface::kRTFlip_None) {
93*c8dee2aaSAndroid Build Coastguard Worker        this->addRTFlipUniform(SKSL_RTFLIP_NAME);
94*c8dee2aaSAndroid Build Coastguard Worker    }
95*c8dee2aaSAndroid Build Coastguard Worker    return shaderLibrary;
96*c8dee2aaSAndroid Build Coastguard Worker}
97*c8dee2aaSAndroid Build Coastguard Worker
98*c8dee2aaSAndroid Build Coastguard Workerstatic inline MTLVertexFormat attribute_type_to_mtlformat(GrVertexAttribType type) {
99*c8dee2aaSAndroid Build Coastguard Worker    switch (type) {
100*c8dee2aaSAndroid Build Coastguard Worker        case kFloat_GrVertexAttribType:
101*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatFloat;
102*c8dee2aaSAndroid Build Coastguard Worker        case kFloat2_GrVertexAttribType:
103*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatFloat2;
104*c8dee2aaSAndroid Build Coastguard Worker        case kFloat3_GrVertexAttribType:
105*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatFloat3;
106*c8dee2aaSAndroid Build Coastguard Worker        case kFloat4_GrVertexAttribType:
107*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatFloat4;
108*c8dee2aaSAndroid Build Coastguard Worker        case kHalf_GrVertexAttribType:
109*c8dee2aaSAndroid Build Coastguard Worker            if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
110*c8dee2aaSAndroid Build Coastguard Worker                return MTLVertexFormatHalf;
111*c8dee2aaSAndroid Build Coastguard Worker            } else {
112*c8dee2aaSAndroid Build Coastguard Worker                return MTLVertexFormatInvalid;
113*c8dee2aaSAndroid Build Coastguard Worker            }
114*c8dee2aaSAndroid Build Coastguard Worker        case kHalf2_GrVertexAttribType:
115*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatHalf2;
116*c8dee2aaSAndroid Build Coastguard Worker        case kHalf4_GrVertexAttribType:
117*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatHalf4;
118*c8dee2aaSAndroid Build Coastguard Worker        case kInt2_GrVertexAttribType:
119*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatInt2;
120*c8dee2aaSAndroid Build Coastguard Worker        case kInt3_GrVertexAttribType:
121*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatInt3;
122*c8dee2aaSAndroid Build Coastguard Worker        case kInt4_GrVertexAttribType:
123*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatInt4;
124*c8dee2aaSAndroid Build Coastguard Worker        case kByte_GrVertexAttribType:
125*c8dee2aaSAndroid Build Coastguard Worker            if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
126*c8dee2aaSAndroid Build Coastguard Worker                return MTLVertexFormatChar;
127*c8dee2aaSAndroid Build Coastguard Worker            } else {
128*c8dee2aaSAndroid Build Coastguard Worker                return MTLVertexFormatInvalid;
129*c8dee2aaSAndroid Build Coastguard Worker            }
130*c8dee2aaSAndroid Build Coastguard Worker        case kByte2_GrVertexAttribType:
131*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatChar2;
132*c8dee2aaSAndroid Build Coastguard Worker        case kByte4_GrVertexAttribType:
133*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatChar4;
134*c8dee2aaSAndroid Build Coastguard Worker        case kUByte_GrVertexAttribType:
135*c8dee2aaSAndroid Build Coastguard Worker            if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
136*c8dee2aaSAndroid Build Coastguard Worker                return MTLVertexFormatUChar;
137*c8dee2aaSAndroid Build Coastguard Worker            } else {
138*c8dee2aaSAndroid Build Coastguard Worker                return MTLVertexFormatInvalid;
139*c8dee2aaSAndroid Build Coastguard Worker            }
140*c8dee2aaSAndroid Build Coastguard Worker        case kUByte2_GrVertexAttribType:
141*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatUChar2;
142*c8dee2aaSAndroid Build Coastguard Worker        case kUByte4_GrVertexAttribType:
143*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatUChar4;
144*c8dee2aaSAndroid Build Coastguard Worker        case kUByte_norm_GrVertexAttribType:
145*c8dee2aaSAndroid Build Coastguard Worker            if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
146*c8dee2aaSAndroid Build Coastguard Worker                return MTLVertexFormatUCharNormalized;
147*c8dee2aaSAndroid Build Coastguard Worker            } else {
148*c8dee2aaSAndroid Build Coastguard Worker                return MTLVertexFormatInvalid;
149*c8dee2aaSAndroid Build Coastguard Worker            }
150*c8dee2aaSAndroid Build Coastguard Worker        case kUByte4_norm_GrVertexAttribType:
151*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatUChar4Normalized;
152*c8dee2aaSAndroid Build Coastguard Worker        case kShort2_GrVertexAttribType:
153*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatShort2;
154*c8dee2aaSAndroid Build Coastguard Worker        case kShort4_GrVertexAttribType:
155*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatShort4;
156*c8dee2aaSAndroid Build Coastguard Worker        case kUShort2_GrVertexAttribType:
157*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatUShort2;
158*c8dee2aaSAndroid Build Coastguard Worker        case kUShort2_norm_GrVertexAttribType:
159*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatUShort2Normalized;
160*c8dee2aaSAndroid Build Coastguard Worker        case kInt_GrVertexAttribType:
161*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatInt;
162*c8dee2aaSAndroid Build Coastguard Worker        case kUInt_GrVertexAttribType:
163*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatUInt;
164*c8dee2aaSAndroid Build Coastguard Worker        case kUShort_norm_GrVertexAttribType:
165*c8dee2aaSAndroid Build Coastguard Worker            if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
166*c8dee2aaSAndroid Build Coastguard Worker                return MTLVertexFormatUShortNormalized;
167*c8dee2aaSAndroid Build Coastguard Worker            } else {
168*c8dee2aaSAndroid Build Coastguard Worker                return MTLVertexFormatInvalid;
169*c8dee2aaSAndroid Build Coastguard Worker            }
170*c8dee2aaSAndroid Build Coastguard Worker        case kUShort4_norm_GrVertexAttribType:
171*c8dee2aaSAndroid Build Coastguard Worker            return MTLVertexFormatUShort4Normalized;
172*c8dee2aaSAndroid Build Coastguard Worker    }
173*c8dee2aaSAndroid Build Coastguard Worker    SK_ABORT("Unknown vertex attribute type");
174*c8dee2aaSAndroid Build Coastguard Worker}
175*c8dee2aaSAndroid Build Coastguard Worker
176*c8dee2aaSAndroid Build Coastguard Workerstatic MTLVertexDescriptor* create_vertex_descriptor(const GrGeometryProcessor& geomProc,
177*c8dee2aaSAndroid Build Coastguard Worker                                                     SkBinaryWriteBuffer* writer) {
178*c8dee2aaSAndroid Build Coastguard Worker    uint32_t vertexBinding = 0, instanceBinding = 0;
179*c8dee2aaSAndroid Build Coastguard Worker
180*c8dee2aaSAndroid Build Coastguard Worker    int nextBinding = GrMtlUniformHandler::kLastUniformBinding + 1; // Start after the uniforms.
181*c8dee2aaSAndroid Build Coastguard Worker    if (geomProc.hasVertexAttributes()) {
182*c8dee2aaSAndroid Build Coastguard Worker        vertexBinding = nextBinding++;
183*c8dee2aaSAndroid Build Coastguard Worker    }
184*c8dee2aaSAndroid Build Coastguard Worker
185*c8dee2aaSAndroid Build Coastguard Worker    if (geomProc.hasInstanceAttributes()) {
186*c8dee2aaSAndroid Build Coastguard Worker        instanceBinding = nextBinding;
187*c8dee2aaSAndroid Build Coastguard Worker    }
188*c8dee2aaSAndroid Build Coastguard Worker    if (writer) {
189*c8dee2aaSAndroid Build Coastguard Worker        writer->writeUInt(vertexBinding);
190*c8dee2aaSAndroid Build Coastguard Worker        writer->writeUInt(instanceBinding);
191*c8dee2aaSAndroid Build Coastguard Worker    }
192*c8dee2aaSAndroid Build Coastguard Worker
193*c8dee2aaSAndroid Build Coastguard Worker    auto vertexDescriptor = [[MTLVertexDescriptor alloc] init];
194*c8dee2aaSAndroid Build Coastguard Worker    int attributeIndex = 0;
195*c8dee2aaSAndroid Build Coastguard Worker
196*c8dee2aaSAndroid Build Coastguard Worker    int vertexAttributeCount = geomProc.numVertexAttributes();
197*c8dee2aaSAndroid Build Coastguard Worker    if (writer) {
198*c8dee2aaSAndroid Build Coastguard Worker        writer->writeInt(vertexAttributeCount);
199*c8dee2aaSAndroid Build Coastguard Worker    }
200*c8dee2aaSAndroid Build Coastguard Worker    for (auto attribute : geomProc.vertexAttributes()) {
201*c8dee2aaSAndroid Build Coastguard Worker        MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
202*c8dee2aaSAndroid Build Coastguard Worker        MTLVertexFormat format = attribute_type_to_mtlformat(attribute.cpuType());
203*c8dee2aaSAndroid Build Coastguard Worker        SkASSERT(MTLVertexFormatInvalid != format);
204*c8dee2aaSAndroid Build Coastguard Worker        mtlAttribute.format = format;
205*c8dee2aaSAndroid Build Coastguard Worker        mtlAttribute.offset = *attribute.offset();
206*c8dee2aaSAndroid Build Coastguard Worker        mtlAttribute.bufferIndex = vertexBinding;
207*c8dee2aaSAndroid Build Coastguard Worker        if (writer) {
208*c8dee2aaSAndroid Build Coastguard Worker            writer->writeInt(format);
209*c8dee2aaSAndroid Build Coastguard Worker            writer->writeUInt(*attribute.offset());
210*c8dee2aaSAndroid Build Coastguard Worker            writer->writeUInt(vertexBinding);
211*c8dee2aaSAndroid Build Coastguard Worker        }
212*c8dee2aaSAndroid Build Coastguard Worker
213*c8dee2aaSAndroid Build Coastguard Worker        attributeIndex++;
214*c8dee2aaSAndroid Build Coastguard Worker    }
215*c8dee2aaSAndroid Build Coastguard Worker
216*c8dee2aaSAndroid Build Coastguard Worker    if (vertexAttributeCount) {
217*c8dee2aaSAndroid Build Coastguard Worker        MTLVertexBufferLayoutDescriptor* vertexBufferLayout =
218*c8dee2aaSAndroid Build Coastguard Worker                vertexDescriptor.layouts[vertexBinding];
219*c8dee2aaSAndroid Build Coastguard Worker        vertexBufferLayout.stepFunction = MTLVertexStepFunctionPerVertex;
220*c8dee2aaSAndroid Build Coastguard Worker        vertexBufferLayout.stepRate = 1;
221*c8dee2aaSAndroid Build Coastguard Worker        vertexBufferLayout.stride = geomProc.vertexStride();
222*c8dee2aaSAndroid Build Coastguard Worker        if (writer) {
223*c8dee2aaSAndroid Build Coastguard Worker            writer->writeUInt(geomProc.vertexStride());
224*c8dee2aaSAndroid Build Coastguard Worker        }
225*c8dee2aaSAndroid Build Coastguard Worker    }
226*c8dee2aaSAndroid Build Coastguard Worker
227*c8dee2aaSAndroid Build Coastguard Worker    int instanceAttributeCount = geomProc.numInstanceAttributes();
228*c8dee2aaSAndroid Build Coastguard Worker    if (writer) {
229*c8dee2aaSAndroid Build Coastguard Worker        writer->writeInt(instanceAttributeCount);
230*c8dee2aaSAndroid Build Coastguard Worker    }
231*c8dee2aaSAndroid Build Coastguard Worker    for (auto attribute : geomProc.instanceAttributes()) {
232*c8dee2aaSAndroid Build Coastguard Worker        MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
233*c8dee2aaSAndroid Build Coastguard Worker        MTLVertexFormat format = attribute_type_to_mtlformat(attribute.cpuType());
234*c8dee2aaSAndroid Build Coastguard Worker        SkASSERT(MTLVertexFormatInvalid != format);
235*c8dee2aaSAndroid Build Coastguard Worker        mtlAttribute.format = format;
236*c8dee2aaSAndroid Build Coastguard Worker        mtlAttribute.offset = *attribute.offset();
237*c8dee2aaSAndroid Build Coastguard Worker        mtlAttribute.bufferIndex = instanceBinding;
238*c8dee2aaSAndroid Build Coastguard Worker        if (writer) {
239*c8dee2aaSAndroid Build Coastguard Worker            writer->writeInt(format);
240*c8dee2aaSAndroid Build Coastguard Worker            writer->writeUInt(*attribute.offset());
241*c8dee2aaSAndroid Build Coastguard Worker            writer->writeUInt(instanceBinding);
242*c8dee2aaSAndroid Build Coastguard Worker        }
243*c8dee2aaSAndroid Build Coastguard Worker
244*c8dee2aaSAndroid Build Coastguard Worker        attributeIndex++;
245*c8dee2aaSAndroid Build Coastguard Worker    }
246*c8dee2aaSAndroid Build Coastguard Worker
247*c8dee2aaSAndroid Build Coastguard Worker    if (instanceAttributeCount) {
248*c8dee2aaSAndroid Build Coastguard Worker        MTLVertexBufferLayoutDescriptor* instanceBufferLayout =
249*c8dee2aaSAndroid Build Coastguard Worker                vertexDescriptor.layouts[instanceBinding];
250*c8dee2aaSAndroid Build Coastguard Worker        instanceBufferLayout.stepFunction = MTLVertexStepFunctionPerInstance;
251*c8dee2aaSAndroid Build Coastguard Worker        instanceBufferLayout.stepRate = 1;
252*c8dee2aaSAndroid Build Coastguard Worker        instanceBufferLayout.stride = geomProc.instanceStride();
253*c8dee2aaSAndroid Build Coastguard Worker        if (writer) {
254*c8dee2aaSAndroid Build Coastguard Worker            writer->writeUInt(geomProc.instanceStride());
255*c8dee2aaSAndroid Build Coastguard Worker        }
256*c8dee2aaSAndroid Build Coastguard Worker    }
257*c8dee2aaSAndroid Build Coastguard Worker    return vertexDescriptor;
258*c8dee2aaSAndroid Build Coastguard Worker}
259*c8dee2aaSAndroid Build Coastguard Worker
260*c8dee2aaSAndroid Build Coastguard Workerstatic MTLBlendFactor blend_coeff_to_mtl_blend(skgpu::BlendCoeff coeff) {
261*c8dee2aaSAndroid Build Coastguard Worker    switch (coeff) {
262*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kZero:
263*c8dee2aaSAndroid Build Coastguard Worker            return MTLBlendFactorZero;
264*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kOne:
265*c8dee2aaSAndroid Build Coastguard Worker            return MTLBlendFactorOne;
266*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kSC:
267*c8dee2aaSAndroid Build Coastguard Worker            return MTLBlendFactorSourceColor;
268*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kISC:
269*c8dee2aaSAndroid Build Coastguard Worker            return MTLBlendFactorOneMinusSourceColor;
270*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kDC:
271*c8dee2aaSAndroid Build Coastguard Worker            return MTLBlendFactorDestinationColor;
272*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kIDC:
273*c8dee2aaSAndroid Build Coastguard Worker            return MTLBlendFactorOneMinusDestinationColor;
274*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kSA:
275*c8dee2aaSAndroid Build Coastguard Worker            return MTLBlendFactorSourceAlpha;
276*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kISA:
277*c8dee2aaSAndroid Build Coastguard Worker            return MTLBlendFactorOneMinusSourceAlpha;
278*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kDA:
279*c8dee2aaSAndroid Build Coastguard Worker            return MTLBlendFactorDestinationAlpha;
280*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kIDA:
281*c8dee2aaSAndroid Build Coastguard Worker            return MTLBlendFactorOneMinusDestinationAlpha;
282*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kConstC:
283*c8dee2aaSAndroid Build Coastguard Worker            return MTLBlendFactorBlendColor;
284*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kIConstC:
285*c8dee2aaSAndroid Build Coastguard Worker            return MTLBlendFactorOneMinusBlendColor;
286*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kS2C:
287*c8dee2aaSAndroid Build Coastguard Worker            if (@available(macOS 10.12, iOS 11.0, tvOS 11.0, *)) {
288*c8dee2aaSAndroid Build Coastguard Worker                return MTLBlendFactorSource1Color;
289*c8dee2aaSAndroid Build Coastguard Worker            } else {
290*c8dee2aaSAndroid Build Coastguard Worker                return MTLBlendFactorZero;
291*c8dee2aaSAndroid Build Coastguard Worker            }
292*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kIS2C:
293*c8dee2aaSAndroid Build Coastguard Worker            if (@available(macOS 10.12, iOS 11.0, tvOS 11.0, *)) {
294*c8dee2aaSAndroid Build Coastguard Worker                return MTLBlendFactorOneMinusSource1Color;
295*c8dee2aaSAndroid Build Coastguard Worker            } else {
296*c8dee2aaSAndroid Build Coastguard Worker                return MTLBlendFactorZero;
297*c8dee2aaSAndroid Build Coastguard Worker            }
298*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kS2A:
299*c8dee2aaSAndroid Build Coastguard Worker            if (@available(macOS 10.12, iOS 11.0, tvOS 11.0, *)) {
300*c8dee2aaSAndroid Build Coastguard Worker                return MTLBlendFactorSource1Alpha;
301*c8dee2aaSAndroid Build Coastguard Worker            } else {
302*c8dee2aaSAndroid Build Coastguard Worker                return MTLBlendFactorZero;
303*c8dee2aaSAndroid Build Coastguard Worker            }
304*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kIS2A:
305*c8dee2aaSAndroid Build Coastguard Worker            if (@available(macOS 10.12, iOS 11.0, tvOS 11.0, *)) {
306*c8dee2aaSAndroid Build Coastguard Worker                return MTLBlendFactorOneMinusSource1Alpha;
307*c8dee2aaSAndroid Build Coastguard Worker            } else {
308*c8dee2aaSAndroid Build Coastguard Worker                return MTLBlendFactorZero;
309*c8dee2aaSAndroid Build Coastguard Worker            }
310*c8dee2aaSAndroid Build Coastguard Worker        case skgpu::BlendCoeff::kIllegal:
311*c8dee2aaSAndroid Build Coastguard Worker            return MTLBlendFactorZero;
312*c8dee2aaSAndroid Build Coastguard Worker    }
313*c8dee2aaSAndroid Build Coastguard Worker
314*c8dee2aaSAndroid Build Coastguard Worker    SK_ABORT("Unknown blend coefficient");
315*c8dee2aaSAndroid Build Coastguard Worker}
316*c8dee2aaSAndroid Build Coastguard Worker
317*c8dee2aaSAndroid Build Coastguard Workerstatic MTLBlendOperation blend_equation_to_mtl_blend_op(skgpu::BlendEquation equation) {
318*c8dee2aaSAndroid Build Coastguard Worker    static const MTLBlendOperation gTable[] = {
319*c8dee2aaSAndroid Build Coastguard Worker        MTLBlendOperationAdd,              // skgpu::BlendEquation::kAdd
320*c8dee2aaSAndroid Build Coastguard Worker        MTLBlendOperationSubtract,         // skgpu::BlendEquation::kSubtract
321*c8dee2aaSAndroid Build Coastguard Worker        MTLBlendOperationReverseSubtract,  // skgpu::BlendEquation::kReverseSubtract
322*c8dee2aaSAndroid Build Coastguard Worker    };
323*c8dee2aaSAndroid Build Coastguard Worker    static_assert(std::size(gTable) == (int)skgpu::BlendEquation::kFirstAdvanced);
324*c8dee2aaSAndroid Build Coastguard Worker    static_assert(0 == (int)skgpu::BlendEquation::kAdd);
325*c8dee2aaSAndroid Build Coastguard Worker    static_assert(1 == (int)skgpu::BlendEquation::kSubtract);
326*c8dee2aaSAndroid Build Coastguard Worker    static_assert(2 == (int)skgpu::BlendEquation::kReverseSubtract);
327*c8dee2aaSAndroid Build Coastguard Worker
328*c8dee2aaSAndroid Build Coastguard Worker    SkASSERT((unsigned)equation < skgpu::kBlendEquationCnt);
329*c8dee2aaSAndroid Build Coastguard Worker    return gTable[(int)equation];
330*c8dee2aaSAndroid Build Coastguard Worker}
331*c8dee2aaSAndroid Build Coastguard Worker
332*c8dee2aaSAndroid Build Coastguard Workerstatic MTLRenderPipelineColorAttachmentDescriptor* create_color_attachment(
333*c8dee2aaSAndroid Build Coastguard Worker        MTLPixelFormat format, const GrPipeline& pipeline, SkBinaryWriteBuffer* writer) {
334*c8dee2aaSAndroid Build Coastguard Worker    auto mtlColorAttachment = [[MTLRenderPipelineColorAttachmentDescriptor alloc] init];
335*c8dee2aaSAndroid Build Coastguard Worker
336*c8dee2aaSAndroid Build Coastguard Worker    // pixel format
337*c8dee2aaSAndroid Build Coastguard Worker    mtlColorAttachment.pixelFormat = format;
338*c8dee2aaSAndroid Build Coastguard Worker    if (writer) {
339*c8dee2aaSAndroid Build Coastguard Worker        writer->writeInt(format);
340*c8dee2aaSAndroid Build Coastguard Worker    }
341*c8dee2aaSAndroid Build Coastguard Worker
342*c8dee2aaSAndroid Build Coastguard Worker    // blending
343*c8dee2aaSAndroid Build Coastguard Worker    const skgpu::BlendInfo& blendInfo = pipeline.getXferProcessor().getBlendInfo();
344*c8dee2aaSAndroid Build Coastguard Worker
345*c8dee2aaSAndroid Build Coastguard Worker    skgpu::BlendEquation equation = blendInfo.fEquation;
346*c8dee2aaSAndroid Build Coastguard Worker    skgpu::BlendCoeff srcCoeff = blendInfo.fSrcBlend;
347*c8dee2aaSAndroid Build Coastguard Worker    skgpu::BlendCoeff dstCoeff = blendInfo.fDstBlend;
348*c8dee2aaSAndroid Build Coastguard Worker    bool blendOn = !skgpu::BlendShouldDisable(equation, srcCoeff, dstCoeff);
349*c8dee2aaSAndroid Build Coastguard Worker
350*c8dee2aaSAndroid Build Coastguard Worker    mtlColorAttachment.blendingEnabled = blendOn;
351*c8dee2aaSAndroid Build Coastguard Worker    if (writer) {
352*c8dee2aaSAndroid Build Coastguard Worker        writer->writeBool(blendOn);
353*c8dee2aaSAndroid Build Coastguard Worker    }
354*c8dee2aaSAndroid Build Coastguard Worker    if (blendOn) {
355*c8dee2aaSAndroid Build Coastguard Worker        mtlColorAttachment.sourceRGBBlendFactor = blend_coeff_to_mtl_blend(srcCoeff);
356*c8dee2aaSAndroid Build Coastguard Worker        mtlColorAttachment.destinationRGBBlendFactor = blend_coeff_to_mtl_blend(dstCoeff);
357*c8dee2aaSAndroid Build Coastguard Worker        mtlColorAttachment.rgbBlendOperation = blend_equation_to_mtl_blend_op(equation);
358*c8dee2aaSAndroid Build Coastguard Worker        mtlColorAttachment.sourceAlphaBlendFactor = blend_coeff_to_mtl_blend(srcCoeff);
359*c8dee2aaSAndroid Build Coastguard Worker        mtlColorAttachment.destinationAlphaBlendFactor = blend_coeff_to_mtl_blend(dstCoeff);
360*c8dee2aaSAndroid Build Coastguard Worker        mtlColorAttachment.alphaBlendOperation = blend_equation_to_mtl_blend_op(equation);
361*c8dee2aaSAndroid Build Coastguard Worker        if (writer) {
362*c8dee2aaSAndroid Build Coastguard Worker            writer->writeInt(mtlColorAttachment.sourceRGBBlendFactor);
363*c8dee2aaSAndroid Build Coastguard Worker            writer->writeInt(mtlColorAttachment.destinationRGBBlendFactor);
364*c8dee2aaSAndroid Build Coastguard Worker            writer->writeInt(mtlColorAttachment.rgbBlendOperation);
365*c8dee2aaSAndroid Build Coastguard Worker            writer->writeInt(mtlColorAttachment.sourceAlphaBlendFactor);
366*c8dee2aaSAndroid Build Coastguard Worker            writer->writeInt(mtlColorAttachment.destinationAlphaBlendFactor);
367*c8dee2aaSAndroid Build Coastguard Worker            writer->writeInt(mtlColorAttachment.alphaBlendOperation);
368*c8dee2aaSAndroid Build Coastguard Worker        }
369*c8dee2aaSAndroid Build Coastguard Worker    }
370*c8dee2aaSAndroid Build Coastguard Worker
371*c8dee2aaSAndroid Build Coastguard Worker    if (blendInfo.fWritesColor) {
372*c8dee2aaSAndroid Build Coastguard Worker        mtlColorAttachment.writeMask = MTLColorWriteMaskAll;
373*c8dee2aaSAndroid Build Coastguard Worker    } else {
374*c8dee2aaSAndroid Build Coastguard Worker        mtlColorAttachment.writeMask = MTLColorWriteMaskNone;
375*c8dee2aaSAndroid Build Coastguard Worker    }
376*c8dee2aaSAndroid Build Coastguard Worker    if (writer) {
377*c8dee2aaSAndroid Build Coastguard Worker        writer->writeBool(blendInfo.fWritesColor);
378*c8dee2aaSAndroid Build Coastguard Worker    }
379*c8dee2aaSAndroid Build Coastguard Worker    return mtlColorAttachment;
380*c8dee2aaSAndroid Build Coastguard Worker}
381*c8dee2aaSAndroid Build Coastguard Worker
382*c8dee2aaSAndroid Build Coastguard Workerstatic uint32_t buffer_size(uint32_t offset, uint32_t maxAlignment) {
383*c8dee2aaSAndroid Build Coastguard Worker    // Metal expects the buffer to be padded at the end according to the alignment
384*c8dee2aaSAndroid Build Coastguard Worker    // of the largest element in the buffer.
385*c8dee2aaSAndroid Build Coastguard Worker    uint32_t offsetDiff = offset & maxAlignment;
386*c8dee2aaSAndroid Build Coastguard Worker    if (offsetDiff != 0) {
387*c8dee2aaSAndroid Build Coastguard Worker        offsetDiff = maxAlignment - offsetDiff + 1;
388*c8dee2aaSAndroid Build Coastguard Worker    }
389*c8dee2aaSAndroid Build Coastguard Worker    return offset + offsetDiff;
390*c8dee2aaSAndroid Build Coastguard Worker}
391*c8dee2aaSAndroid Build Coastguard Worker
392*c8dee2aaSAndroid Build Coastguard Workerstatic MTLRenderPipelineDescriptor* read_pipeline_data(SkReadBuffer* reader) {
393*c8dee2aaSAndroid Build Coastguard Worker    auto pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
394*c8dee2aaSAndroid Build Coastguard Worker
395*c8dee2aaSAndroid Build Coastguard Worker#ifdef SK_ENABLE_MTL_DEBUG_INFO
396*c8dee2aaSAndroid Build Coastguard Worker    // set label
397*c8dee2aaSAndroid Build Coastguard Worker    {
398*c8dee2aaSAndroid Build Coastguard Worker        SkString description;
399*c8dee2aaSAndroid Build Coastguard Worker        reader->readString(&description);
400*c8dee2aaSAndroid Build Coastguard Worker        pipelineDescriptor.label = @(description.c_str());
401*c8dee2aaSAndroid Build Coastguard Worker    }
402*c8dee2aaSAndroid Build Coastguard Worker#endif
403*c8dee2aaSAndroid Build Coastguard Worker
404*c8dee2aaSAndroid Build Coastguard Worker    // set up vertex descriptor
405*c8dee2aaSAndroid Build Coastguard Worker    {
406*c8dee2aaSAndroid Build Coastguard Worker        auto vertexDescriptor = [[MTLVertexDescriptor alloc] init];
407*c8dee2aaSAndroid Build Coastguard Worker        uint32_t vertexBinding = reader->readUInt();
408*c8dee2aaSAndroid Build Coastguard Worker        uint32_t instanceBinding = reader->readUInt();
409*c8dee2aaSAndroid Build Coastguard Worker
410*c8dee2aaSAndroid Build Coastguard Worker        int attributeIndex = 0;
411*c8dee2aaSAndroid Build Coastguard Worker
412*c8dee2aaSAndroid Build Coastguard Worker        // vertex attributes
413*c8dee2aaSAndroid Build Coastguard Worker        int vertexAttributeCount = reader->readInt();
414*c8dee2aaSAndroid Build Coastguard Worker        for (int i = 0; i < vertexAttributeCount; ++i) {
415*c8dee2aaSAndroid Build Coastguard Worker            MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
416*c8dee2aaSAndroid Build Coastguard Worker            mtlAttribute.format = (MTLVertexFormat) reader->readInt();
417*c8dee2aaSAndroid Build Coastguard Worker            mtlAttribute.offset = reader->readUInt();
418*c8dee2aaSAndroid Build Coastguard Worker            mtlAttribute.bufferIndex = reader->readUInt();
419*c8dee2aaSAndroid Build Coastguard Worker            ++attributeIndex;
420*c8dee2aaSAndroid Build Coastguard Worker        }
421*c8dee2aaSAndroid Build Coastguard Worker        if (vertexAttributeCount) {
422*c8dee2aaSAndroid Build Coastguard Worker            MTLVertexBufferLayoutDescriptor* vertexBufferLayout =
423*c8dee2aaSAndroid Build Coastguard Worker                    vertexDescriptor.layouts[vertexBinding];
424*c8dee2aaSAndroid Build Coastguard Worker            vertexBufferLayout.stepFunction = MTLVertexStepFunctionPerVertex;
425*c8dee2aaSAndroid Build Coastguard Worker            vertexBufferLayout.stepRate = 1;
426*c8dee2aaSAndroid Build Coastguard Worker            vertexBufferLayout.stride = reader->readUInt();
427*c8dee2aaSAndroid Build Coastguard Worker        }
428*c8dee2aaSAndroid Build Coastguard Worker
429*c8dee2aaSAndroid Build Coastguard Worker        // instance attributes
430*c8dee2aaSAndroid Build Coastguard Worker        int instanceAttributeCount = reader->readInt();
431*c8dee2aaSAndroid Build Coastguard Worker        for (int i = 0; i < instanceAttributeCount; ++i) {
432*c8dee2aaSAndroid Build Coastguard Worker            MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
433*c8dee2aaSAndroid Build Coastguard Worker            mtlAttribute.format = (MTLVertexFormat) reader->readInt();
434*c8dee2aaSAndroid Build Coastguard Worker            mtlAttribute.offset = reader->readUInt();
435*c8dee2aaSAndroid Build Coastguard Worker            mtlAttribute.bufferIndex = reader->readUInt();
436*c8dee2aaSAndroid Build Coastguard Worker            ++attributeIndex;
437*c8dee2aaSAndroid Build Coastguard Worker        }
438*c8dee2aaSAndroid Build Coastguard Worker        if (instanceAttributeCount) {
439*c8dee2aaSAndroid Build Coastguard Worker            MTLVertexBufferLayoutDescriptor* instanceBufferLayout =
440*c8dee2aaSAndroid Build Coastguard Worker                    vertexDescriptor.layouts[instanceBinding];
441*c8dee2aaSAndroid Build Coastguard Worker            instanceBufferLayout.stepFunction = MTLVertexStepFunctionPerInstance;
442*c8dee2aaSAndroid Build Coastguard Worker            instanceBufferLayout.stepRate = 1;
443*c8dee2aaSAndroid Build Coastguard Worker            instanceBufferLayout.stride = reader->readUInt();
444*c8dee2aaSAndroid Build Coastguard Worker        }
445*c8dee2aaSAndroid Build Coastguard Worker        pipelineDescriptor.vertexDescriptor = vertexDescriptor;
446*c8dee2aaSAndroid Build Coastguard Worker    }
447*c8dee2aaSAndroid Build Coastguard Worker
448*c8dee2aaSAndroid Build Coastguard Worker    // set up color attachments
449*c8dee2aaSAndroid Build Coastguard Worker    {
450*c8dee2aaSAndroid Build Coastguard Worker        auto mtlColorAttachment = [[MTLRenderPipelineColorAttachmentDescriptor alloc] init];
451*c8dee2aaSAndroid Build Coastguard Worker
452*c8dee2aaSAndroid Build Coastguard Worker        mtlColorAttachment.pixelFormat = (MTLPixelFormat) reader->readInt();
453*c8dee2aaSAndroid Build Coastguard Worker        mtlColorAttachment.blendingEnabled = reader->readBool();
454*c8dee2aaSAndroid Build Coastguard Worker        if (mtlColorAttachment.blendingEnabled) {
455*c8dee2aaSAndroid Build Coastguard Worker            mtlColorAttachment.sourceRGBBlendFactor = (MTLBlendFactor) reader->readInt();
456*c8dee2aaSAndroid Build Coastguard Worker            mtlColorAttachment.destinationRGBBlendFactor = (MTLBlendFactor) reader->readInt();
457*c8dee2aaSAndroid Build Coastguard Worker            mtlColorAttachment.rgbBlendOperation = (MTLBlendOperation) reader->readInt();
458*c8dee2aaSAndroid Build Coastguard Worker            mtlColorAttachment.sourceAlphaBlendFactor = (MTLBlendFactor) reader->readInt();
459*c8dee2aaSAndroid Build Coastguard Worker            mtlColorAttachment.destinationAlphaBlendFactor = (MTLBlendFactor) reader->readInt();
460*c8dee2aaSAndroid Build Coastguard Worker            mtlColorAttachment.alphaBlendOperation = (MTLBlendOperation) reader->readInt();
461*c8dee2aaSAndroid Build Coastguard Worker        }
462*c8dee2aaSAndroid Build Coastguard Worker        if (reader->readBool()) {
463*c8dee2aaSAndroid Build Coastguard Worker            mtlColorAttachment.writeMask = MTLColorWriteMaskAll;
464*c8dee2aaSAndroid Build Coastguard Worker        } else {
465*c8dee2aaSAndroid Build Coastguard Worker            mtlColorAttachment.writeMask = MTLColorWriteMaskNone;
466*c8dee2aaSAndroid Build Coastguard Worker        }
467*c8dee2aaSAndroid Build Coastguard Worker
468*c8dee2aaSAndroid Build Coastguard Worker        pipelineDescriptor.colorAttachments[0] = mtlColorAttachment;
469*c8dee2aaSAndroid Build Coastguard Worker    }
470*c8dee2aaSAndroid Build Coastguard Worker
471*c8dee2aaSAndroid Build Coastguard Worker    pipelineDescriptor.stencilAttachmentPixelFormat = (MTLPixelFormat) reader->readInt();
472*c8dee2aaSAndroid Build Coastguard Worker
473*c8dee2aaSAndroid Build Coastguard Worker    return pipelineDescriptor;
474*c8dee2aaSAndroid Build Coastguard Worker}
475*c8dee2aaSAndroid Build Coastguard Worker
476*c8dee2aaSAndroid Build Coastguard WorkerGrMtlPipelineState* GrMtlPipelineStateBuilder::finalize(
477*c8dee2aaSAndroid Build Coastguard Worker        const GrProgramDesc& desc, const GrProgramInfo& programInfo,
478*c8dee2aaSAndroid Build Coastguard Worker        const GrMtlPrecompiledLibraries* precompiledLibs) {
479*c8dee2aaSAndroid Build Coastguard Worker    TRACE_EVENT0("skia.shaders", TRACE_FUNC);
480*c8dee2aaSAndroid Build Coastguard Worker
481*c8dee2aaSAndroid Build Coastguard Worker    // Set up for cache if needed
482*c8dee2aaSAndroid Build Coastguard Worker    std::unique_ptr<SkBinaryWriteBuffer> writer;
483*c8dee2aaSAndroid Build Coastguard Worker
484*c8dee2aaSAndroid Build Coastguard Worker    sk_sp<SkData> cached;
485*c8dee2aaSAndroid Build Coastguard Worker    auto persistentCache = fGpu->getContext()->priv().getPersistentCache();
486*c8dee2aaSAndroid Build Coastguard Worker    if (persistentCache && !precompiledLibs) {
487*c8dee2aaSAndroid Build Coastguard Worker        sk_sp<SkData> key = SkData::MakeWithoutCopy(desc.asKey(), desc.keyLength());
488*c8dee2aaSAndroid Build Coastguard Worker        cached = persistentCache->load(*key);
489*c8dee2aaSAndroid Build Coastguard Worker    }
490*c8dee2aaSAndroid Build Coastguard Worker    if (persistentCache && !cached) {
491*c8dee2aaSAndroid Build Coastguard Worker        writer = std::make_unique<SkBinaryWriteBuffer>(SkSerialProcs{});
492*c8dee2aaSAndroid Build Coastguard Worker    }
493*c8dee2aaSAndroid Build Coastguard Worker
494*c8dee2aaSAndroid Build Coastguard Worker    // Ordering in how we set these matters. If it changes adjust read_pipeline_data, above.
495*c8dee2aaSAndroid Build Coastguard Worker    auto pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
496*c8dee2aaSAndroid Build Coastguard Worker#ifdef SK_ENABLE_MTL_DEBUG_INFO
497*c8dee2aaSAndroid Build Coastguard Worker    SkString description = GrProgramDesc::Describe(programInfo, *fGpu->caps());
498*c8dee2aaSAndroid Build Coastguard Worker    int split = description.find("\n");
499*c8dee2aaSAndroid Build Coastguard Worker    description.resize(split);
500*c8dee2aaSAndroid Build Coastguard Worker    pipelineDescriptor.label = @(description.c_str());
501*c8dee2aaSAndroid Build Coastguard Worker    if (writer) {
502*c8dee2aaSAndroid Build Coastguard Worker        writer->writeString(description.c_str());
503*c8dee2aaSAndroid Build Coastguard Worker    }
504*c8dee2aaSAndroid Build Coastguard Worker#endif
505*c8dee2aaSAndroid Build Coastguard Worker
506*c8dee2aaSAndroid Build Coastguard Worker    pipelineDescriptor.vertexDescriptor = create_vertex_descriptor(programInfo.geomProc(),
507*c8dee2aaSAndroid Build Coastguard Worker                                                                   writer.get());
508*c8dee2aaSAndroid Build Coastguard Worker
509*c8dee2aaSAndroid Build Coastguard Worker    MTLPixelFormat pixelFormat = GrBackendFormatAsMTLPixelFormat(programInfo.backendFormat());
510*c8dee2aaSAndroid Build Coastguard Worker    if (pixelFormat == MTLPixelFormatInvalid) {
511*c8dee2aaSAndroid Build Coastguard Worker        return nullptr;
512*c8dee2aaSAndroid Build Coastguard Worker    }
513*c8dee2aaSAndroid Build Coastguard Worker
514*c8dee2aaSAndroid Build Coastguard Worker    pipelineDescriptor.colorAttachments[0] = create_color_attachment(pixelFormat,
515*c8dee2aaSAndroid Build Coastguard Worker                                                                     programInfo.pipeline(),
516*c8dee2aaSAndroid Build Coastguard Worker                                                                     writer.get());
517*c8dee2aaSAndroid Build Coastguard Worker    pipelineDescriptor.rasterSampleCount = programInfo.numSamples();
518*c8dee2aaSAndroid Build Coastguard Worker
519*c8dee2aaSAndroid Build Coastguard Worker    const GrMtlCaps* mtlCaps = (const GrMtlCaps*)this->caps();
520*c8dee2aaSAndroid Build Coastguard Worker    pipelineDescriptor.stencilAttachmentPixelFormat = mtlCaps->getStencilPixelFormat(desc);
521*c8dee2aaSAndroid Build Coastguard Worker    if (writer) {
522*c8dee2aaSAndroid Build Coastguard Worker        writer->writeInt(pipelineDescriptor.stencilAttachmentPixelFormat);
523*c8dee2aaSAndroid Build Coastguard Worker    }
524*c8dee2aaSAndroid Build Coastguard Worker    SkASSERT(pipelineDescriptor.vertexDescriptor);
525*c8dee2aaSAndroid Build Coastguard Worker    SkASSERT(pipelineDescriptor.colorAttachments[0]);
526*c8dee2aaSAndroid Build Coastguard Worker
527*c8dee2aaSAndroid Build Coastguard Worker    if (precompiledLibs) {
528*c8dee2aaSAndroid Build Coastguard Worker        SkASSERT(precompiledLibs->fVertexLibrary);
529*c8dee2aaSAndroid Build Coastguard Worker        SkASSERT(precompiledLibs->fFragmentLibrary);
530*c8dee2aaSAndroid Build Coastguard Worker        pipelineDescriptor.vertexFunction =
531*c8dee2aaSAndroid Build Coastguard Worker                [precompiledLibs->fVertexLibrary newFunctionWithName: @"vertexMain"];
532*c8dee2aaSAndroid Build Coastguard Worker        pipelineDescriptor.fragmentFunction =
533*c8dee2aaSAndroid Build Coastguard Worker                [precompiledLibs->fFragmentLibrary newFunctionWithName: @"fragmentMain"];
534*c8dee2aaSAndroid Build Coastguard Worker        SkASSERT(pipelineDescriptor.vertexFunction);
535*c8dee2aaSAndroid Build Coastguard Worker        SkASSERT(pipelineDescriptor.fragmentFunction);
536*c8dee2aaSAndroid Build Coastguard Worker        if (precompiledLibs->fRTFlip) {
537*c8dee2aaSAndroid Build Coastguard Worker            this->addRTFlipUniform(SKSL_RTFLIP_NAME);
538*c8dee2aaSAndroid Build Coastguard Worker        }
539*c8dee2aaSAndroid Build Coastguard Worker    } else {
540*c8dee2aaSAndroid Build Coastguard Worker        id<MTLLibrary> shaderLibraries[kGrShaderTypeCount];
541*c8dee2aaSAndroid Build Coastguard Worker
542*c8dee2aaSAndroid Build Coastguard Worker        this->finalizeShaders();
543*c8dee2aaSAndroid Build Coastguard Worker
544*c8dee2aaSAndroid Build Coastguard Worker        SkSL::ProgramSettings settings;
545*c8dee2aaSAndroid Build Coastguard Worker        settings.fSharpenTextures = fGpu->getContext()->priv().options().fSharpenMipmappedTextures;
546*c8dee2aaSAndroid Build Coastguard Worker        SkASSERT(!this->fragColorIsInOut());
547*c8dee2aaSAndroid Build Coastguard Worker
548*c8dee2aaSAndroid Build Coastguard Worker        SkReadBuffer reader;
549*c8dee2aaSAndroid Build Coastguard Worker        SkFourByteTag shaderType = 0;
550*c8dee2aaSAndroid Build Coastguard Worker        if (persistentCache && cached) {
551*c8dee2aaSAndroid Build Coastguard Worker            reader.setMemory(cached->data(), cached->size());
552*c8dee2aaSAndroid Build Coastguard Worker            shaderType = GrPersistentCacheUtils::GetType(&reader);
553*c8dee2aaSAndroid Build Coastguard Worker        }
554*c8dee2aaSAndroid Build Coastguard Worker
555*c8dee2aaSAndroid Build Coastguard Worker        auto errorHandler = fGpu->getContext()->priv().getShaderErrorHandler();
556*c8dee2aaSAndroid Build Coastguard Worker        std::string msl[kGrShaderTypeCount];
557*c8dee2aaSAndroid Build Coastguard Worker        SkSL::Program::Interface interfaces[kGrShaderTypeCount];
558*c8dee2aaSAndroid Build Coastguard Worker
559*c8dee2aaSAndroid Build Coastguard Worker        // Unpack any stored shaders from the persistent cache
560*c8dee2aaSAndroid Build Coastguard Worker        if (cached) {
561*c8dee2aaSAndroid Build Coastguard Worker            switch (shaderType) {
562*c8dee2aaSAndroid Build Coastguard Worker                case kMSL_Tag: {
563*c8dee2aaSAndroid Build Coastguard Worker                    GrPersistentCacheUtils::UnpackCachedShaders(
564*c8dee2aaSAndroid Build Coastguard Worker                            &reader, msl, interfaces, kGrShaderTypeCount);
565*c8dee2aaSAndroid Build Coastguard Worker                    break;
566*c8dee2aaSAndroid Build Coastguard Worker                }
567*c8dee2aaSAndroid Build Coastguard Worker
568*c8dee2aaSAndroid Build Coastguard Worker                case kSKSL_Tag: {
569*c8dee2aaSAndroid Build Coastguard Worker                    std::string cached_sksl[kGrShaderTypeCount];
570*c8dee2aaSAndroid Build Coastguard Worker                    if (GrPersistentCacheUtils::UnpackCachedShaders(
571*c8dee2aaSAndroid Build Coastguard Worker                                &reader, cached_sksl, interfaces, kGrShaderTypeCount)) {
572*c8dee2aaSAndroid Build Coastguard Worker                        bool success = skgpu::SkSLToMSL(mtlCaps->shaderCaps(),
573*c8dee2aaSAndroid Build Coastguard Worker                                                        cached_sksl[kVertex_GrShaderType],
574*c8dee2aaSAndroid Build Coastguard Worker                                                        SkSL::ProgramKind::kVertex,
575*c8dee2aaSAndroid Build Coastguard Worker                                                        settings,
576*c8dee2aaSAndroid Build Coastguard Worker                                                        &msl[kVertex_GrShaderType],
577*c8dee2aaSAndroid Build Coastguard Worker                                                        &interfaces[kVertex_GrShaderType],
578*c8dee2aaSAndroid Build Coastguard Worker                                                        errorHandler);
579*c8dee2aaSAndroid Build Coastguard Worker                        success = success && skgpu::SkSLToMSL(mtlCaps->shaderCaps(),
580*c8dee2aaSAndroid Build Coastguard Worker                                                              cached_sksl[kFragment_GrShaderType],
581*c8dee2aaSAndroid Build Coastguard Worker                                                              SkSL::ProgramKind::kFragment,
582*c8dee2aaSAndroid Build Coastguard Worker                                                              settings,
583*c8dee2aaSAndroid Build Coastguard Worker                                                              &msl[kFragment_GrShaderType],
584*c8dee2aaSAndroid Build Coastguard Worker                                                              &interfaces[kFragment_GrShaderType],
585*c8dee2aaSAndroid Build Coastguard Worker                                                              errorHandler);
586*c8dee2aaSAndroid Build Coastguard Worker                        if (!success) {
587*c8dee2aaSAndroid Build Coastguard Worker                            return nullptr;
588*c8dee2aaSAndroid Build Coastguard Worker                        }
589*c8dee2aaSAndroid Build Coastguard Worker                    }
590*c8dee2aaSAndroid Build Coastguard Worker                    break;
591*c8dee2aaSAndroid Build Coastguard Worker                }
592*c8dee2aaSAndroid Build Coastguard Worker
593*c8dee2aaSAndroid Build Coastguard Worker                default: {
594*c8dee2aaSAndroid Build Coastguard Worker                    break;
595*c8dee2aaSAndroid Build Coastguard Worker                }
596*c8dee2aaSAndroid Build Coastguard Worker            }
597*c8dee2aaSAndroid Build Coastguard Worker        }
598*c8dee2aaSAndroid Build Coastguard Worker
599*c8dee2aaSAndroid Build Coastguard Worker        // Create any MSL shaders from pipeline data if necessary and cache
600*c8dee2aaSAndroid Build Coastguard Worker        if (msl[kVertex_GrShaderType].empty() || msl[kFragment_GrShaderType].empty()) {
601*c8dee2aaSAndroid Build Coastguard Worker            bool success = true;
602*c8dee2aaSAndroid Build Coastguard Worker            if (msl[kVertex_GrShaderType].empty()) {
603*c8dee2aaSAndroid Build Coastguard Worker                success = skgpu::SkSLToMSL(mtlCaps->shaderCaps(),
604*c8dee2aaSAndroid Build Coastguard Worker                                           fVS.fCompilerString,
605*c8dee2aaSAndroid Build Coastguard Worker                                           SkSL::ProgramKind::kVertex,
606*c8dee2aaSAndroid Build Coastguard Worker                                           settings,
607*c8dee2aaSAndroid Build Coastguard Worker                                           &msl[kVertex_GrShaderType],
608*c8dee2aaSAndroid Build Coastguard Worker                                           &interfaces[kVertex_GrShaderType],
609*c8dee2aaSAndroid Build Coastguard Worker                                           errorHandler);
610*c8dee2aaSAndroid Build Coastguard Worker            }
611*c8dee2aaSAndroid Build Coastguard Worker            if (success && msl[kFragment_GrShaderType].empty()) {
612*c8dee2aaSAndroid Build Coastguard Worker                success = skgpu::SkSLToMSL(mtlCaps->shaderCaps(),
613*c8dee2aaSAndroid Build Coastguard Worker                                           fFS.fCompilerString,
614*c8dee2aaSAndroid Build Coastguard Worker                                           SkSL::ProgramKind::kFragment,
615*c8dee2aaSAndroid Build Coastguard Worker                                           settings,
616*c8dee2aaSAndroid Build Coastguard Worker                                           &msl[kFragment_GrShaderType],
617*c8dee2aaSAndroid Build Coastguard Worker                                           &interfaces[kFragment_GrShaderType],
618*c8dee2aaSAndroid Build Coastguard Worker                                           errorHandler);
619*c8dee2aaSAndroid Build Coastguard Worker            }
620*c8dee2aaSAndroid Build Coastguard Worker            if (!success) {
621*c8dee2aaSAndroid Build Coastguard Worker                return nullptr;
622*c8dee2aaSAndroid Build Coastguard Worker            }
623*c8dee2aaSAndroid Build Coastguard Worker
624*c8dee2aaSAndroid Build Coastguard Worker            if (persistentCache && !cached) {
625*c8dee2aaSAndroid Build Coastguard Worker                sk_sp<SkData> pipelineData = writer->snapshotAsData();
626*c8dee2aaSAndroid Build Coastguard Worker                if (fGpu->getContext()->priv().options().fShaderCacheStrategy ==
627*c8dee2aaSAndroid Build Coastguard Worker                        GrContextOptions::ShaderCacheStrategy::kSkSL) {
628*c8dee2aaSAndroid Build Coastguard Worker                    std::string sksl[kGrShaderTypeCount];
629*c8dee2aaSAndroid Build Coastguard Worker                    sksl[kVertex_GrShaderType] = SkShaderUtils::PrettyPrint(fVS.fCompilerString);
630*c8dee2aaSAndroid Build Coastguard Worker                    sksl[kFragment_GrShaderType] = SkShaderUtils::PrettyPrint(fFS.fCompilerString);
631*c8dee2aaSAndroid Build Coastguard Worker                    this->storeShadersInCache(sksl, interfaces, &settings,
632*c8dee2aaSAndroid Build Coastguard Worker                                              std::move(pipelineData), true);
633*c8dee2aaSAndroid Build Coastguard Worker                } else {
634*c8dee2aaSAndroid Build Coastguard Worker                    /*** dump pipeline data here */
635*c8dee2aaSAndroid Build Coastguard Worker                    this->storeShadersInCache(msl, interfaces, nullptr,
636*c8dee2aaSAndroid Build Coastguard Worker                                              std::move(pipelineData), false);
637*c8dee2aaSAndroid Build Coastguard Worker                }
638*c8dee2aaSAndroid Build Coastguard Worker            }
639*c8dee2aaSAndroid Build Coastguard Worker        }
640*c8dee2aaSAndroid Build Coastguard Worker
641*c8dee2aaSAndroid Build Coastguard Worker        // Compile MSL to libraries
642*c8dee2aaSAndroid Build Coastguard Worker        shaderLibraries[kVertex_GrShaderType] = this->compileMtlShaderLibrary(
643*c8dee2aaSAndroid Build Coastguard Worker                                                        msl[kVertex_GrShaderType],
644*c8dee2aaSAndroid Build Coastguard Worker                                                        interfaces[kVertex_GrShaderType],
645*c8dee2aaSAndroid Build Coastguard Worker                                                        errorHandler);
646*c8dee2aaSAndroid Build Coastguard Worker        shaderLibraries[kFragment_GrShaderType] = this->compileMtlShaderLibrary(
647*c8dee2aaSAndroid Build Coastguard Worker                                                        msl[kFragment_GrShaderType],
648*c8dee2aaSAndroid Build Coastguard Worker                                                        interfaces[kFragment_GrShaderType],
649*c8dee2aaSAndroid Build Coastguard Worker                                                        errorHandler);
650*c8dee2aaSAndroid Build Coastguard Worker        if (!shaderLibraries[kVertex_GrShaderType] || !shaderLibraries[kFragment_GrShaderType]) {
651*c8dee2aaSAndroid Build Coastguard Worker            return nullptr;
652*c8dee2aaSAndroid Build Coastguard Worker        }
653*c8dee2aaSAndroid Build Coastguard Worker
654*c8dee2aaSAndroid Build Coastguard Worker        pipelineDescriptor.vertexFunction =
655*c8dee2aaSAndroid Build Coastguard Worker                [shaderLibraries[kVertex_GrShaderType] newFunctionWithName: @"vertexMain"];
656*c8dee2aaSAndroid Build Coastguard Worker        pipelineDescriptor.fragmentFunction =
657*c8dee2aaSAndroid Build Coastguard Worker                [shaderLibraries[kFragment_GrShaderType] newFunctionWithName: @"fragmentMain"];
658*c8dee2aaSAndroid Build Coastguard Worker    }
659*c8dee2aaSAndroid Build Coastguard Worker
660*c8dee2aaSAndroid Build Coastguard Worker    if (pipelineDescriptor.vertexFunction == nil) {
661*c8dee2aaSAndroid Build Coastguard Worker        SkDebugf("Couldn't find vertexMain() in library\n");
662*c8dee2aaSAndroid Build Coastguard Worker        return nullptr;
663*c8dee2aaSAndroid Build Coastguard Worker    }
664*c8dee2aaSAndroid Build Coastguard Worker    if (pipelineDescriptor.fragmentFunction == nil) {
665*c8dee2aaSAndroid Build Coastguard Worker        SkDebugf("Couldn't find fragmentMain() in library\n");
666*c8dee2aaSAndroid Build Coastguard Worker        return nullptr;
667*c8dee2aaSAndroid Build Coastguard Worker    }
668*c8dee2aaSAndroid Build Coastguard Worker    SkASSERT(pipelineDescriptor.vertexFunction);
669*c8dee2aaSAndroid Build Coastguard Worker    SkASSERT(pipelineDescriptor.fragmentFunction);
670*c8dee2aaSAndroid Build Coastguard Worker
671*c8dee2aaSAndroid Build Coastguard Worker    NSError* error = nil;
672*c8dee2aaSAndroid Build Coastguard Worker    id<MTLRenderPipelineState> pipelineState;
673*c8dee2aaSAndroid Build Coastguard Worker    {
674*c8dee2aaSAndroid Build Coastguard Worker        TRACE_EVENT0("skia.shaders", "newRenderPipelineStateWithDescriptor");
675*c8dee2aaSAndroid Build Coastguard Worker        if (@available(macOS 10.15, *)) {
676*c8dee2aaSAndroid Build Coastguard Worker            pipelineState = [fGpu->device() newRenderPipelineStateWithDescriptor: pipelineDescriptor
677*c8dee2aaSAndroid Build Coastguard Worker                                                                           error: &error];
678*c8dee2aaSAndroid Build Coastguard Worker        } else {
679*c8dee2aaSAndroid Build Coastguard Worker            pipelineState = GrMtlNewRenderPipelineStateWithDescriptor(
680*c8dee2aaSAndroid Build Coastguard Worker                    fGpu->device(), pipelineDescriptor, &error);
681*c8dee2aaSAndroid Build Coastguard Worker        }
682*c8dee2aaSAndroid Build Coastguard Worker    }
683*c8dee2aaSAndroid Build Coastguard Worker    if (error) {
684*c8dee2aaSAndroid Build Coastguard Worker        SkDebugf("Error creating pipeline: %s\n",
685*c8dee2aaSAndroid Build Coastguard Worker                 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
686*c8dee2aaSAndroid Build Coastguard Worker        return nullptr;
687*c8dee2aaSAndroid Build Coastguard Worker    }
688*c8dee2aaSAndroid Build Coastguard Worker    if (!pipelineState) {
689*c8dee2aaSAndroid Build Coastguard Worker        return nullptr;
690*c8dee2aaSAndroid Build Coastguard Worker    }
691*c8dee2aaSAndroid Build Coastguard Worker
692*c8dee2aaSAndroid Build Coastguard Worker    sk_sp<GrMtlRenderPipeline> renderPipeline = GrMtlRenderPipeline::Make(pipelineState);
693*c8dee2aaSAndroid Build Coastguard Worker
694*c8dee2aaSAndroid Build Coastguard Worker    uint32_t bufferSize = buffer_size(fUniformHandler.fCurrentUBOOffset,
695*c8dee2aaSAndroid Build Coastguard Worker                                      fUniformHandler.fCurrentUBOMaxAlignment);
696*c8dee2aaSAndroid Build Coastguard Worker    return new GrMtlPipelineState(fGpu,
697*c8dee2aaSAndroid Build Coastguard Worker                                  std::move(renderPipeline),
698*c8dee2aaSAndroid Build Coastguard Worker                                  pipelineDescriptor.colorAttachments[0].pixelFormat,
699*c8dee2aaSAndroid Build Coastguard Worker                                  fUniformHandles,
700*c8dee2aaSAndroid Build Coastguard Worker                                  fUniformHandler.fUniforms,
701*c8dee2aaSAndroid Build Coastguard Worker                                  bufferSize,
702*c8dee2aaSAndroid Build Coastguard Worker                                  (uint32_t)fUniformHandler.numSamplers(),
703*c8dee2aaSAndroid Build Coastguard Worker                                  std::move(fGPImpl),
704*c8dee2aaSAndroid Build Coastguard Worker                                  std::move(fXPImpl),
705*c8dee2aaSAndroid Build Coastguard Worker                                  std::move(fFPImpls));
706*c8dee2aaSAndroid Build Coastguard Worker}
707*c8dee2aaSAndroid Build Coastguard Worker
708*c8dee2aaSAndroid Build Coastguard Worker//////////////////////////////////////////////////////////////////////////////
709*c8dee2aaSAndroid Build Coastguard Worker
710*c8dee2aaSAndroid Build Coastguard Workerbool GrMtlPipelineStateBuilder::PrecompileShaders(GrMtlGpu* gpu, const SkData& cachedData,
711*c8dee2aaSAndroid Build Coastguard Worker                                                  GrMtlPrecompiledLibraries* precompiledLibs) {
712*c8dee2aaSAndroid Build Coastguard Worker    SkASSERT(precompiledLibs);
713*c8dee2aaSAndroid Build Coastguard Worker
714*c8dee2aaSAndroid Build Coastguard Worker    SkReadBuffer reader(cachedData.data(), cachedData.size());
715*c8dee2aaSAndroid Build Coastguard Worker    SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
716*c8dee2aaSAndroid Build Coastguard Worker
717*c8dee2aaSAndroid Build Coastguard Worker    auto errorHandler = gpu->getContext()->priv().getShaderErrorHandler();
718*c8dee2aaSAndroid Build Coastguard Worker
719*c8dee2aaSAndroid Build Coastguard Worker    SkSL::ProgramSettings settings;
720*c8dee2aaSAndroid Build Coastguard Worker    settings.fSharpenTextures = gpu->getContext()->priv().options().fSharpenMipmappedTextures;
721*c8dee2aaSAndroid Build Coastguard Worker    GrPersistentCacheUtils::ShaderMetadata meta;
722*c8dee2aaSAndroid Build Coastguard Worker    meta.fSettings = &settings;
723*c8dee2aaSAndroid Build Coastguard Worker
724*c8dee2aaSAndroid Build Coastguard Worker    std::string shaders[kGrShaderTypeCount];
725*c8dee2aaSAndroid Build Coastguard Worker    SkSL::Program::Interface interfaces[kGrShaderTypeCount];
726*c8dee2aaSAndroid Build Coastguard Worker    if (!GrPersistentCacheUtils::UnpackCachedShaders(
727*c8dee2aaSAndroid Build Coastguard Worker                &reader, shaders, interfaces, kGrShaderTypeCount, &meta)) {
728*c8dee2aaSAndroid Build Coastguard Worker        return false;
729*c8dee2aaSAndroid Build Coastguard Worker    }
730*c8dee2aaSAndroid Build Coastguard Worker
731*c8dee2aaSAndroid Build Coastguard Worker    // skip the size
732*c8dee2aaSAndroid Build Coastguard Worker    reader.readUInt();
733*c8dee2aaSAndroid Build Coastguard Worker    auto pipelineDescriptor = read_pipeline_data(&reader);
734*c8dee2aaSAndroid Build Coastguard Worker    if (!reader.isValid()) {
735*c8dee2aaSAndroid Build Coastguard Worker        return false;
736*c8dee2aaSAndroid Build Coastguard Worker    }
737*c8dee2aaSAndroid Build Coastguard Worker
738*c8dee2aaSAndroid Build Coastguard Worker    switch (shaderType) {
739*c8dee2aaSAndroid Build Coastguard Worker        case kMSL_Tag: {
740*c8dee2aaSAndroid Build Coastguard Worker            precompiledLibs->fVertexLibrary =
741*c8dee2aaSAndroid Build Coastguard Worker                    GrCompileMtlShaderLibrary(gpu, shaders[kVertex_GrShaderType], errorHandler);
742*c8dee2aaSAndroid Build Coastguard Worker            precompiledLibs->fFragmentLibrary =
743*c8dee2aaSAndroid Build Coastguard Worker                    GrCompileMtlShaderLibrary(gpu, shaders[kFragment_GrShaderType], errorHandler);
744*c8dee2aaSAndroid Build Coastguard Worker            break;
745*c8dee2aaSAndroid Build Coastguard Worker        }
746*c8dee2aaSAndroid Build Coastguard Worker
747*c8dee2aaSAndroid Build Coastguard Worker        case kSKSL_Tag: {
748*c8dee2aaSAndroid Build Coastguard Worker            std::string msl[kGrShaderTypeCount];
749*c8dee2aaSAndroid Build Coastguard Worker            if (!skgpu::SkSLToMSL(gpu->caps()->shaderCaps(),
750*c8dee2aaSAndroid Build Coastguard Worker                                  shaders[kVertex_GrShaderType],
751*c8dee2aaSAndroid Build Coastguard Worker                                  SkSL::ProgramKind::kVertex,
752*c8dee2aaSAndroid Build Coastguard Worker                                  settings,
753*c8dee2aaSAndroid Build Coastguard Worker                                  &msl[kVertex_GrShaderType],
754*c8dee2aaSAndroid Build Coastguard Worker                                  &interfaces[kVertex_GrShaderType],
755*c8dee2aaSAndroid Build Coastguard Worker                                  errorHandler)) {
756*c8dee2aaSAndroid Build Coastguard Worker                return false;
757*c8dee2aaSAndroid Build Coastguard Worker            }
758*c8dee2aaSAndroid Build Coastguard Worker            if (!skgpu::SkSLToMSL(gpu->caps()->shaderCaps(),
759*c8dee2aaSAndroid Build Coastguard Worker                                  shaders[kFragment_GrShaderType],
760*c8dee2aaSAndroid Build Coastguard Worker                                  SkSL::ProgramKind::kFragment,
761*c8dee2aaSAndroid Build Coastguard Worker                                  settings,
762*c8dee2aaSAndroid Build Coastguard Worker                                  &msl[kFragment_GrShaderType],
763*c8dee2aaSAndroid Build Coastguard Worker                                  &interfaces[kFragment_GrShaderType],
764*c8dee2aaSAndroid Build Coastguard Worker                                  errorHandler)) {
765*c8dee2aaSAndroid Build Coastguard Worker                return false;
766*c8dee2aaSAndroid Build Coastguard Worker            }
767*c8dee2aaSAndroid Build Coastguard Worker            precompiledLibs->fVertexLibrary =
768*c8dee2aaSAndroid Build Coastguard Worker                    GrCompileMtlShaderLibrary(gpu, msl[kVertex_GrShaderType], errorHandler);
769*c8dee2aaSAndroid Build Coastguard Worker            precompiledLibs->fFragmentLibrary =
770*c8dee2aaSAndroid Build Coastguard Worker                    GrCompileMtlShaderLibrary(gpu, msl[kFragment_GrShaderType], errorHandler);
771*c8dee2aaSAndroid Build Coastguard Worker            break;
772*c8dee2aaSAndroid Build Coastguard Worker        }
773*c8dee2aaSAndroid Build Coastguard Worker
774*c8dee2aaSAndroid Build Coastguard Worker        default: {
775*c8dee2aaSAndroid Build Coastguard Worker            return false;
776*c8dee2aaSAndroid Build Coastguard Worker        }
777*c8dee2aaSAndroid Build Coastguard Worker    }
778*c8dee2aaSAndroid Build Coastguard Worker
779*c8dee2aaSAndroid Build Coastguard Worker    pipelineDescriptor.vertexFunction =
780*c8dee2aaSAndroid Build Coastguard Worker            [precompiledLibs->fVertexLibrary newFunctionWithName: @"vertexMain"];
781*c8dee2aaSAndroid Build Coastguard Worker    pipelineDescriptor.fragmentFunction =
782*c8dee2aaSAndroid Build Coastguard Worker            [precompiledLibs->fFragmentLibrary newFunctionWithName: @"fragmentMain"];
783*c8dee2aaSAndroid Build Coastguard Worker
784*c8dee2aaSAndroid Build Coastguard Worker    {
785*c8dee2aaSAndroid Build Coastguard Worker        TRACE_EVENT0("skia.shaders", "newRenderPipelineStateWithDescriptor");
786*c8dee2aaSAndroid Build Coastguard Worker        MTLNewRenderPipelineStateCompletionHandler completionHandler =
787*c8dee2aaSAndroid Build Coastguard Worker                 ^(id<MTLRenderPipelineState> state, NSError* error) {
788*c8dee2aaSAndroid Build Coastguard Worker                     if (error) {
789*c8dee2aaSAndroid Build Coastguard Worker                         SkDebugf("Error creating pipeline: %s\n",
790*c8dee2aaSAndroid Build Coastguard Worker                                  [[error localizedDescription]
791*c8dee2aaSAndroid Build Coastguard Worker                                           cStringUsingEncoding: NSASCIIStringEncoding]);
792*c8dee2aaSAndroid Build Coastguard Worker                     }
793*c8dee2aaSAndroid Build Coastguard Worker                 };
794*c8dee2aaSAndroid Build Coastguard Worker
795*c8dee2aaSAndroid Build Coastguard Worker        // kick off asynchronous pipeline build and depend on Apple's cache to manage it
796*c8dee2aaSAndroid Build Coastguard Worker        [gpu->device() newRenderPipelineStateWithDescriptor: pipelineDescriptor
797*c8dee2aaSAndroid Build Coastguard Worker                                          completionHandler: completionHandler];
798*c8dee2aaSAndroid Build Coastguard Worker    }
799*c8dee2aaSAndroid Build Coastguard Worker
800*c8dee2aaSAndroid Build Coastguard Worker    precompiledLibs->fRTFlip = (interfaces[kFragment_GrShaderType].fRTFlipUniform !=
801*c8dee2aaSAndroid Build Coastguard Worker                                SkSL::Program::Interface::kRTFlip_None);
802*c8dee2aaSAndroid Build Coastguard Worker    return true;
803*c8dee2aaSAndroid Build Coastguard Worker}
804*c8dee2aaSAndroid Build Coastguard Worker
805*c8dee2aaSAndroid Build Coastguard WorkerGR_NORETAIN_END
806