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