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.fRTHeight) {
95        this->addRTHeightUniform(SKSL_RTHEIGHT_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    // set up vertex descriptor
404    {
405        auto vertexDescriptor = [[MTLVertexDescriptor alloc] init];
406        uint32_t vertexBinding = reader->readUInt();
407        uint32_t instanceBinding = reader->readUInt();
408
409        int attributeIndex = 0;
410
411        // vertex attributes
412        int vertexAttributeCount = reader->readInt();
413        for (int i = 0; i < vertexAttributeCount; ++i) {
414            MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
415            mtlAttribute.format = (MTLVertexFormat) reader->readInt();
416            mtlAttribute.offset = reader->readUInt();
417            mtlAttribute.bufferIndex = reader->readUInt();
418            ++attributeIndex;
419        }
420        if (vertexAttributeCount) {
421            MTLVertexBufferLayoutDescriptor* vertexBufferLayout =
422                    vertexDescriptor.layouts[vertexBinding];
423            vertexBufferLayout.stepFunction = MTLVertexStepFunctionPerVertex;
424            vertexBufferLayout.stepRate = 1;
425            vertexBufferLayout.stride = reader->readUInt();
426        }
427
428        // instance attributes
429        int instanceAttributeCount = reader->readInt();
430        for (int i = 0; i < instanceAttributeCount; ++i) {
431            MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
432            mtlAttribute.format = (MTLVertexFormat) reader->readInt();
433            mtlAttribute.offset = reader->readUInt();
434            mtlAttribute.bufferIndex = reader->readUInt();
435            ++attributeIndex;
436        }
437        if (instanceAttributeCount) {
438            MTLVertexBufferLayoutDescriptor* instanceBufferLayout =
439                    vertexDescriptor.layouts[instanceBinding];
440            instanceBufferLayout.stepFunction = MTLVertexStepFunctionPerInstance;
441            instanceBufferLayout.stepRate = 1;
442            instanceBufferLayout.stride = reader->readUInt();
443        }
444        pipelineDescriptor.vertexDescriptor = vertexDescriptor;
445    }
446
447    // set up color attachments
448    {
449        auto mtlColorAttachment = [[MTLRenderPipelineColorAttachmentDescriptor alloc] init];
450
451        mtlColorAttachment.pixelFormat = (MTLPixelFormat) reader->readInt();
452        mtlColorAttachment.blendingEnabled = reader->readBool();
453        if (mtlColorAttachment.blendingEnabled) {
454            mtlColorAttachment.sourceRGBBlendFactor = (MTLBlendFactor) reader->readInt();
455            mtlColorAttachment.destinationRGBBlendFactor = (MTLBlendFactor) reader->readInt();
456            mtlColorAttachment.rgbBlendOperation = (MTLBlendOperation) reader->readInt();
457            mtlColorAttachment.sourceAlphaBlendFactor = (MTLBlendFactor) reader->readInt();
458            mtlColorAttachment.destinationAlphaBlendFactor = (MTLBlendFactor) reader->readInt();
459            mtlColorAttachment.alphaBlendOperation = (MTLBlendOperation) reader->readInt();
460        }
461        if (reader->readBool()) {
462            mtlColorAttachment.writeMask = MTLColorWriteMaskAll;
463        } else {
464            mtlColorAttachment.writeMask = MTLColorWriteMaskNone;
465        }
466
467        pipelineDescriptor.colorAttachments[0] = mtlColorAttachment;
468    }
469
470    pipelineDescriptor.stencilAttachmentPixelFormat = (MTLPixelFormat) reader->readInt();
471
472    return pipelineDescriptor;
473}
474
475GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize(
476        const GrProgramDesc& desc, const GrProgramInfo& programInfo,
477        const GrMtlPrecompiledLibraries* precompiledLibs) {
478    TRACE_EVENT0("skia.shaders", TRACE_FUNC);
479
480    // Geometry shaders are not supported
481    SkASSERT(!this->geometryProcessor().willUseGeoShader());
482
483    if (precompiledLibs) {
484        SkASSERT(precompiledLibs->fPipelineState);
485        if (precompiledLibs->fRTHeight) {
486            this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
487        }
488        uint32_t bufferSize = buffer_size(fUniformHandler.fCurrentUBOOffset,
489                                          fUniformHandler.fCurrentUBOMaxAlignment);
490        return new GrMtlPipelineState(fGpu,
491                                      precompiledLibs->fPipelineState,
492                                      GrBackendFormatAsMTLPixelFormat(programInfo.backendFormat()),
493                                      fUniformHandles,
494                                      fUniformHandler.fUniforms,
495                                      bufferSize,
496                                      (uint32_t)fUniformHandler.numSamplers(),
497                                      std::move(fGeometryProcessor),
498                                      std::move(fXferProcessor),
499                                      std::move(fFPImpls));
500    }
501
502    // build from scratch
503    std::unique_ptr<SkBinaryWriteBuffer> writer;
504
505    sk_sp<SkData> cached;
506    auto persistentCache = fGpu->getContext()->priv().getPersistentCache();
507    if (persistentCache) {
508        sk_sp<SkData> key = SkData::MakeWithoutCopy(desc.asKey(), desc.keyLength());
509        cached = persistentCache->load(*key);
510    }
511    if (persistentCache && !cached) {
512        writer.reset(new SkBinaryWriteBuffer());
513    }
514
515    // Ordering in how we set these matters. If it changes adjust read_pipeline_data, above.
516    auto pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
517    pipelineDescriptor.vertexDescriptor = create_vertex_descriptor(programInfo.geomProc(),
518                                                                   writer.get());
519
520    MTLPixelFormat pixelFormat = GrBackendFormatAsMTLPixelFormat(programInfo.backendFormat());
521    if (pixelFormat == MTLPixelFormatInvalid) {
522        return nullptr;
523    }
524
525    pipelineDescriptor.colorAttachments[0] = create_color_attachment(pixelFormat,
526                                                                     programInfo.pipeline(),
527                                                                     writer.get());
528    pipelineDescriptor.sampleCount = programInfo.numSamples();
529    GrMtlCaps* mtlCaps = (GrMtlCaps*)this->caps();
530    pipelineDescriptor.stencilAttachmentPixelFormat = mtlCaps->getStencilPixelFormat(desc);
531    if (writer) {
532        writer->writeInt(pipelineDescriptor.stencilAttachmentPixelFormat);
533    }
534    SkASSERT(pipelineDescriptor.vertexDescriptor);
535    SkASSERT(pipelineDescriptor.colorAttachments[0]);
536
537    id<MTLLibrary> shaderLibraries[kGrShaderTypeCount];
538
539    fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
540    fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
541    fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
542    fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
543
544    this->finalizeShaders();
545
546    SkSL::Program::Settings settings;
547    settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
548    settings.fSharpenTextures = fGpu->getContext()->priv().options().fSharpenMipmappedTextures;
549    SkASSERT(!this->fragColorIsInOut());
550
551    SkReadBuffer reader;
552    SkFourByteTag shaderType = 0;
553    if (persistentCache && cached) {
554        reader.setMemory(cached->data(), cached->size());
555        shaderType = GrPersistentCacheUtils::GetType(&reader);
556    }
557
558    auto errorHandler = fGpu->getContext()->priv().getShaderErrorHandler();
559    SkSL::String msl[kGrShaderTypeCount];
560    SkSL::Program::Inputs inputs[kGrShaderTypeCount];
561
562    // Unpack any stored shaders from the persistent cache
563    if (cached) {
564        switch (shaderType) {
565            case kMSL_Tag: {
566                GrPersistentCacheUtils::UnpackCachedShaders(&reader, msl, inputs,
567                                                            kGrShaderTypeCount);
568                break;
569            }
570
571            case kSKSL_Tag: {
572                SkSL::String cached_sksl[kGrShaderTypeCount];
573                if (GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, inputs,
574                                                                kGrShaderTypeCount)) {
575                    bool success = GrSkSLToMSL(fGpu,
576                                               cached_sksl[kVertex_GrShaderType],
577                                               SkSL::ProgramKind::kVertex,
578                                               settings,
579                                               &msl[kVertex_GrShaderType],
580                                               &inputs[kVertex_GrShaderType],
581                                               errorHandler);
582                    success = success && GrSkSLToMSL(fGpu,
583                                                     cached_sksl[kFragment_GrShaderType],
584                                                     SkSL::ProgramKind::kFragment,
585                                                     settings,
586                                                     &msl[kFragment_GrShaderType],
587                                                     &inputs[kFragment_GrShaderType],
588                                                     errorHandler);
589                    if (!success) {
590                        return nullptr;
591                    }
592                }
593                break;
594            }
595
596            default: {
597                break;
598            }
599        }
600    }
601
602    // Create any MSL shaders from pipeline data if necessary and cache
603    if (msl[kVertex_GrShaderType].empty() || msl[kFragment_GrShaderType].empty()) {
604        bool success = true;
605        if (msl[kVertex_GrShaderType].empty()) {
606            success = GrSkSLToMSL(fGpu,
607                                  fVS.fCompilerString,
608                                  SkSL::ProgramKind::kVertex,
609                                  settings,
610                                  &msl[kVertex_GrShaderType],
611                                  &inputs[kVertex_GrShaderType],
612                                  errorHandler);
613        }
614        if (success && msl[kFragment_GrShaderType].empty()) {
615            success = GrSkSLToMSL(fGpu,
616                                  fFS.fCompilerString,
617                                  SkSL::ProgramKind::kFragment,
618                                  settings,
619                                  &msl[kFragment_GrShaderType],
620                                  &inputs[kFragment_GrShaderType],
621                                  errorHandler);
622        }
623        if (!success) {
624            return nullptr;
625        }
626
627        if (persistentCache && !cached) {
628            sk_sp<SkData> pipelineData = writer->snapshotAsData();
629            if (fGpu->getContext()->priv().options().fShaderCacheStrategy ==
630                    GrContextOptions::ShaderCacheStrategy::kSkSL) {
631                SkSL::String sksl[kGrShaderTypeCount];
632                sksl[kVertex_GrShaderType] = GrShaderUtils::PrettyPrint(fVS.fCompilerString);
633                sksl[kFragment_GrShaderType] = GrShaderUtils::PrettyPrint(fFS.fCompilerString);
634                this->storeShadersInCache(sksl, inputs, &settings,
635                                          std::move(pipelineData), true);
636            } else {
637                /*** dump pipeline data here */
638                this->storeShadersInCache(msl, inputs, nullptr,
639                                          std::move(pipelineData), false);
640            }
641        }
642    }
643
644    // Compile MSL to libraries
645    shaderLibraries[kVertex_GrShaderType] = this->compileMtlShaderLibrary(
646                                                    msl[kVertex_GrShaderType],
647                                                    inputs[kVertex_GrShaderType],
648                                                    errorHandler);
649    shaderLibraries[kFragment_GrShaderType] = this->compileMtlShaderLibrary(
650                                                    msl[kFragment_GrShaderType],
651                                                    inputs[kFragment_GrShaderType],
652                                                    errorHandler);
653    if (!shaderLibraries[kVertex_GrShaderType] || !shaderLibraries[kFragment_GrShaderType]) {
654        return nullptr;
655    }
656
657    pipelineDescriptor.vertexFunction =
658            [shaderLibraries[kVertex_GrShaderType] newFunctionWithName: @"vertexMain"];
659    pipelineDescriptor.fragmentFunction =
660            [shaderLibraries[kFragment_GrShaderType] newFunctionWithName: @"fragmentMain"];
661
662    if (pipelineDescriptor.vertexFunction == nil) {
663        SkDebugf("Couldn't find vertexMain() in library\n");
664        return nullptr;
665    }
666    if (pipelineDescriptor.fragmentFunction == nil) {
667        SkDebugf("Couldn't find fragmentMain() in library\n");
668        return nullptr;
669    }
670    SkASSERT(pipelineDescriptor.vertexFunction);
671    SkASSERT(pipelineDescriptor.fragmentFunction);
672
673    NSError* error = nil;
674#if GR_METAL_SDK_VERSION >= 230
675    if (@available(macOS 11.0, iOS 14.0, *)) {
676        id<MTLBinaryArchive> archive = fGpu->binaryArchive();
677        if (archive) {
678            NSArray* archiveArray = [NSArray arrayWithObjects:archive, nil];
679            pipelineDescriptor.binaryArchives = archiveArray;
680            BOOL result;
681            {
682                TRACE_EVENT0("skia.shaders", "addRenderPipelineFunctionsWithDescriptor");
683                result = [archive addRenderPipelineFunctionsWithDescriptor: pipelineDescriptor
684                                                                            error: &error];
685            }
686            if (!result && error) {
687                SkDebugf("Error storing pipeline: %s\n",
688                        [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
689            }
690        }
691    }
692#endif
693    id<MTLRenderPipelineState> pipelineState;
694    {
695        TRACE_EVENT0("skia.shaders", "newRenderPipelineStateWithDescriptor");
696#if defined(SK_BUILD_FOR_MAC)
697        pipelineState = GrMtlNewRenderPipelineStateWithDescriptor(
698                                                     fGpu->device(), pipelineDescriptor, &error);
699#else
700        pipelineState =
701            [fGpu->device() newRenderPipelineStateWithDescriptor: pipelineDescriptor
702                                                           error: &error];
703#endif
704    }
705    if (error) {
706        SkDebugf("Error creating pipeline: %s\n",
707                 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
708        return nullptr;
709    }
710    if (!pipelineState) {
711        return nullptr;
712    }
713
714    uint32_t bufferSize = buffer_size(fUniformHandler.fCurrentUBOOffset,
715                                      fUniformHandler.fCurrentUBOMaxAlignment);
716    return new GrMtlPipelineState(fGpu,
717                                  pipelineState,
718                                  pipelineDescriptor.colorAttachments[0].pixelFormat,
719                                  fUniformHandles,
720                                  fUniformHandler.fUniforms,
721                                  bufferSize,
722                                  (uint32_t)fUniformHandler.numSamplers(),
723                                  std::move(fGeometryProcessor),
724                                  std::move(fXferProcessor),
725                                  std::move(fFPImpls));
726}
727
728//////////////////////////////////////////////////////////////////////////////
729
730bool GrMtlPipelineStateBuilder::PrecompileShaders(GrMtlGpu* gpu, const SkData& cachedData,
731                                                  GrMtlPrecompiledLibraries* precompiledLibs) {
732    SkASSERT(precompiledLibs);
733
734    SkReadBuffer reader(cachedData.data(), cachedData.size());
735    SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
736
737    auto errorHandler = gpu->getContext()->priv().getShaderErrorHandler();
738
739    SkSL::Program::Settings settings;
740    settings.fSharpenTextures = gpu->getContext()->priv().options().fSharpenMipmappedTextures;
741    GrPersistentCacheUtils::ShaderMetadata meta;
742    meta.fSettings = &settings;
743
744    SkSL::String shaders[kGrShaderTypeCount];
745    SkSL::Program::Inputs inputs[kGrShaderTypeCount];
746    if (!GrPersistentCacheUtils::UnpackCachedShaders(&reader, shaders, inputs, kGrShaderTypeCount,
747                                                     &meta)) {
748        return false;
749    }
750
751    // skip the size
752    reader.readUInt();
753    auto pipelineDescriptor = read_pipeline_data(&reader);
754    if (!reader.isValid()) {
755        return false;
756    }
757
758    id<MTLLibrary> vertexLibrary;
759    id<MTLLibrary> fragmentLibrary;
760    switch (shaderType) {
761        case kMSL_Tag: {
762            vertexLibrary =
763                    GrCompileMtlShaderLibrary(gpu, shaders[kVertex_GrShaderType], errorHandler);
764            fragmentLibrary =
765                    GrCompileMtlShaderLibrary(gpu, shaders[kFragment_GrShaderType], errorHandler);
766            break;
767        }
768
769        case kSKSL_Tag: {
770            SkSL::String msl[kGrShaderTypeCount];
771            if (!GrSkSLToMSL(gpu,
772                           shaders[kVertex_GrShaderType],
773                           SkSL::ProgramKind::kVertex,
774                           settings,
775                           &msl[kVertex_GrShaderType],
776                           &inputs[kVertex_GrShaderType],
777                           errorHandler)) {
778                return false;
779            }
780            if (!GrSkSLToMSL(gpu,
781                           shaders[kFragment_GrShaderType],
782                           SkSL::ProgramKind::kFragment,
783                           settings,
784                           &msl[kFragment_GrShaderType],
785                           &inputs[kFragment_GrShaderType],
786                           errorHandler)) {
787                return false;
788            }
789            vertexLibrary =
790                    GrCompileMtlShaderLibrary(gpu, msl[kVertex_GrShaderType], errorHandler);
791            fragmentLibrary =
792                    GrCompileMtlShaderLibrary(gpu, msl[kFragment_GrShaderType], errorHandler);
793            break;
794        }
795
796        default: {
797            return false;
798        }
799    }
800
801    pipelineDescriptor.vertexFunction =
802            [vertexLibrary newFunctionWithName: @"vertexMain"];
803    pipelineDescriptor.fragmentFunction =
804            [fragmentLibrary newFunctionWithName: @"fragmentMain"];
805
806    NSError* error = nil;
807#if GR_METAL_SDK_VERSION >= 230
808    if (@available(macOS 11.0, iOS 14.0, *)) {
809        id<MTLBinaryArchive> archive = gpu->binaryArchive();
810        if (archive) {
811            NSArray* archiveArray = [NSArray arrayWithObjects:archive, nil];
812            pipelineDescriptor.binaryArchives = archiveArray;
813            BOOL result;
814            {
815                TRACE_EVENT0("skia.shaders", "addRenderPipelineFunctionsWithDescriptor");
816                result = [archive addRenderPipelineFunctionsWithDescriptor: pipelineDescriptor
817                                                                            error: &error];
818            }
819            if (!result && error) {
820                SkDebugf("Error storing pipeline: %s\n",
821                        [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
822            }
823        }
824    }
825#endif
826    {
827        TRACE_EVENT0("skia.shaders", "newRenderPipelineStateWithDescriptor");
828#if defined(SK_BUILD_FOR_MAC)
829        precompiledLibs->fPipelineState =
830            GrMtlNewRenderPipelineStateWithDescriptor(gpu->device(), pipelineDescriptor, &error);
831#else
832        precompiledLibs->fPipelineState =
833            [gpu->device() newRenderPipelineStateWithDescriptor: pipelineDescriptor
834                                                           error: &error];
835#endif
836    }
837    if (error) {
838        SkDebugf("Error creating pipeline: %s\n",
839                 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
840        return false;
841    }
842
843    precompiledLibs->fRTHeight = inputs[kFragment_GrShaderType].fRTHeight;
844    return true;
845}
846
847GR_NORETAIN_END
848