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