xref: /aosp_15_r20/external/skia/src/gpu/ganesh/mtl/GrMtlPipelineStateBuilder.mm (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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/ganesh/GrDirectContext.h"
11#include "src/core/SkReadBuffer.h"
12#include "src/core/SkTraceEvent.h"
13#include "src/core/SkWriteBuffer.h"
14#include "src/gpu/SkSLToBackend.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/SkSLProgramKind.h"
20#include "src/sksl/SkSLProgramSettings.h"
21#include "src/utils/SkShaderUtils.h"
22
23#include "src/gpu/ganesh/mtl/GrMtlGpu.h"
24#include "src/gpu/ganesh/mtl/GrMtlPipelineState.h"
25#include "src/gpu/ganesh/mtl/GrMtlUtil.h"
26#include "src/gpu/mtl/MtlUtilsPriv.h"
27
28#import <simd/simd.h>
29
30#if !__has_feature(objc_arc)
31#error This file must be compiled with Arc. Use -fobjc-arc flag
32#endif
33
34GR_NORETAIN_BEGIN
35
36GrMtlPipelineState* GrMtlPipelineStateBuilder::CreatePipelineState(
37        GrMtlGpu* gpu, const GrProgramDesc& desc, const GrProgramInfo& programInfo,
38        const GrMtlPrecompiledLibraries* precompiledLibs) {
39    GrAutoLocaleSetter als("C");
40    GrMtlPipelineStateBuilder builder(gpu, desc, programInfo);
41
42    if (!builder.emitAndInstallProcs()) {
43        return nullptr;
44    }
45    return builder.finalize(desc, programInfo, precompiledLibs);
46}
47
48GrMtlPipelineStateBuilder::GrMtlPipelineStateBuilder(GrMtlGpu* gpu,
49                                                     const GrProgramDesc& desc,
50                                                     const GrProgramInfo& programInfo)
51        : INHERITED(desc, programInfo)
52        , fGpu(gpu)
53        , fUniformHandler(this)
54        , fVaryingHandler(this) {
55}
56
57const GrCaps* GrMtlPipelineStateBuilder::caps() const {
58    return fGpu->caps();
59}
60
61void GrMtlPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
62    outputColor.addLayoutQualifier("location = 0, index = 1");
63}
64
65static constexpr SkFourByteTag kMSL_Tag = SkSetFourByteTag('M', 'S', 'L', ' ');
66static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
67
68void GrMtlPipelineStateBuilder::storeShadersInCache(const std::string shaders[],
69                                                    const SkSL::Program::Interface interfaces[],
70                                                    SkSL::ProgramSettings* settings,
71                                                    sk_sp<SkData> pipelineData,
72                                                    bool isSkSL) {
73    sk_sp<SkData> key = SkData::MakeWithoutCopy(this->desc().asKey(),
74                                                this->desc().keyLength());
75    SkString description = GrProgramDesc::Describe(fProgramInfo, *this->caps());
76    // cache metadata to allow for a complete precompile in either case
77    GrPersistentCacheUtils::ShaderMetadata meta;
78    meta.fSettings = settings;
79    meta.fPlatformData = std::move(pipelineData);
80    SkFourByteTag tag = isSkSL ? kSKSL_Tag : kMSL_Tag;
81    sk_sp<SkData> data = GrPersistentCacheUtils::PackCachedShaders(tag, shaders, interfaces,
82                                                                   kGrShaderTypeCount, &meta);
83    fGpu->getContext()->priv().getPersistentCache()->store(*key, *data, description);
84}
85
86id<MTLLibrary> GrMtlPipelineStateBuilder::compileMtlShaderLibrary(
87        const std::string& shader,
88        SkSL::Program::Interface interface,
89        GrContextOptions::ShaderErrorHandler* errorHandler) {
90    id<MTLLibrary> shaderLibrary = GrCompileMtlShaderLibrary(fGpu, shader, errorHandler);
91    if (shaderLibrary != nil &&
92        interface.fRTFlipUniform != SkSL::Program::Interface::kRTFlip_None) {
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, tvOS 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, tvOS 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, tvOS 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, tvOS 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, tvOS 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; // Start after the uniforms.
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, tvOS 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, tvOS 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, tvOS 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, tvOS 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 = std::make_unique<SkBinaryWriteBuffer>(SkSerialProcs{});
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.rasterSampleCount = programInfo.numSamples();
518
519    const GrMtlCaps* mtlCaps = (const GrMtlCaps*)this->caps();
520    pipelineDescriptor.stencilAttachmentPixelFormat = mtlCaps->getStencilPixelFormat(desc);
521    if (writer) {
522        writer->writeInt(pipelineDescriptor.stencilAttachmentPixelFormat);
523    }
524    SkASSERT(pipelineDescriptor.vertexDescriptor);
525    SkASSERT(pipelineDescriptor.colorAttachments[0]);
526
527    if (precompiledLibs) {
528        SkASSERT(precompiledLibs->fVertexLibrary);
529        SkASSERT(precompiledLibs->fFragmentLibrary);
530        pipelineDescriptor.vertexFunction =
531                [precompiledLibs->fVertexLibrary newFunctionWithName: @"vertexMain"];
532        pipelineDescriptor.fragmentFunction =
533                [precompiledLibs->fFragmentLibrary newFunctionWithName: @"fragmentMain"];
534        SkASSERT(pipelineDescriptor.vertexFunction);
535        SkASSERT(pipelineDescriptor.fragmentFunction);
536        if (precompiledLibs->fRTFlip) {
537            this->addRTFlipUniform(SKSL_RTFLIP_NAME);
538        }
539    } else {
540        id<MTLLibrary> shaderLibraries[kGrShaderTypeCount];
541
542        this->finalizeShaders();
543
544        SkSL::ProgramSettings settings;
545        settings.fSharpenTextures = fGpu->getContext()->priv().options().fSharpenMipmappedTextures;
546        SkASSERT(!this->fragColorIsInOut());
547
548        SkReadBuffer reader;
549        SkFourByteTag shaderType = 0;
550        if (persistentCache && cached) {
551            reader.setMemory(cached->data(), cached->size());
552            shaderType = GrPersistentCacheUtils::GetType(&reader);
553        }
554
555        auto errorHandler = fGpu->getContext()->priv().getShaderErrorHandler();
556        std::string msl[kGrShaderTypeCount];
557        SkSL::Program::Interface interfaces[kGrShaderTypeCount];
558
559        // Unpack any stored shaders from the persistent cache
560        if (cached) {
561            switch (shaderType) {
562                case kMSL_Tag: {
563                    GrPersistentCacheUtils::UnpackCachedShaders(
564                            &reader, msl, interfaces, kGrShaderTypeCount);
565                    break;
566                }
567
568                case kSKSL_Tag: {
569                    std::string cached_sksl[kGrShaderTypeCount];
570                    if (GrPersistentCacheUtils::UnpackCachedShaders(
571                                &reader, cached_sksl, interfaces, kGrShaderTypeCount)) {
572                        bool success = skgpu::SkSLToMSL(mtlCaps->shaderCaps(),
573                                                        cached_sksl[kVertex_GrShaderType],
574                                                        SkSL::ProgramKind::kVertex,
575                                                        settings,
576                                                        &msl[kVertex_GrShaderType],
577                                                        &interfaces[kVertex_GrShaderType],
578                                                        errorHandler);
579                        success = success && skgpu::SkSLToMSL(mtlCaps->shaderCaps(),
580                                                              cached_sksl[kFragment_GrShaderType],
581                                                              SkSL::ProgramKind::kFragment,
582                                                              settings,
583                                                              &msl[kFragment_GrShaderType],
584                                                              &interfaces[kFragment_GrShaderType],
585                                                              errorHandler);
586                        if (!success) {
587                            return nullptr;
588                        }
589                    }
590                    break;
591                }
592
593                default: {
594                    break;
595                }
596            }
597        }
598
599        // Create any MSL shaders from pipeline data if necessary and cache
600        if (msl[kVertex_GrShaderType].empty() || msl[kFragment_GrShaderType].empty()) {
601            bool success = true;
602            if (msl[kVertex_GrShaderType].empty()) {
603                success = skgpu::SkSLToMSL(mtlCaps->shaderCaps(),
604                                           fVS.fCompilerString,
605                                           SkSL::ProgramKind::kVertex,
606                                           settings,
607                                           &msl[kVertex_GrShaderType],
608                                           &interfaces[kVertex_GrShaderType],
609                                           errorHandler);
610            }
611            if (success && msl[kFragment_GrShaderType].empty()) {
612                success = skgpu::SkSLToMSL(mtlCaps->shaderCaps(),
613                                           fFS.fCompilerString,
614                                           SkSL::ProgramKind::kFragment,
615                                           settings,
616                                           &msl[kFragment_GrShaderType],
617                                           &interfaces[kFragment_GrShaderType],
618                                           errorHandler);
619            }
620            if (!success) {
621                return nullptr;
622            }
623
624            if (persistentCache && !cached) {
625                sk_sp<SkData> pipelineData = writer->snapshotAsData();
626                if (fGpu->getContext()->priv().options().fShaderCacheStrategy ==
627                        GrContextOptions::ShaderCacheStrategy::kSkSL) {
628                    std::string sksl[kGrShaderTypeCount];
629                    sksl[kVertex_GrShaderType] = SkShaderUtils::PrettyPrint(fVS.fCompilerString);
630                    sksl[kFragment_GrShaderType] = SkShaderUtils::PrettyPrint(fFS.fCompilerString);
631                    this->storeShadersInCache(sksl, interfaces, &settings,
632                                              std::move(pipelineData), true);
633                } else {
634                    /*** dump pipeline data here */
635                    this->storeShadersInCache(msl, interfaces, nullptr,
636                                              std::move(pipelineData), false);
637                }
638            }
639        }
640
641        // Compile MSL to libraries
642        shaderLibraries[kVertex_GrShaderType] = this->compileMtlShaderLibrary(
643                                                        msl[kVertex_GrShaderType],
644                                                        interfaces[kVertex_GrShaderType],
645                                                        errorHandler);
646        shaderLibraries[kFragment_GrShaderType] = this->compileMtlShaderLibrary(
647                                                        msl[kFragment_GrShaderType],
648                                                        interfaces[kFragment_GrShaderType],
649                                                        errorHandler);
650        if (!shaderLibraries[kVertex_GrShaderType] || !shaderLibraries[kFragment_GrShaderType]) {
651            return nullptr;
652        }
653
654        pipelineDescriptor.vertexFunction =
655                [shaderLibraries[kVertex_GrShaderType] newFunctionWithName: @"vertexMain"];
656        pipelineDescriptor.fragmentFunction =
657                [shaderLibraries[kFragment_GrShaderType] newFunctionWithName: @"fragmentMain"];
658    }
659
660    if (pipelineDescriptor.vertexFunction == nil) {
661        SkDebugf("Couldn't find vertexMain() in library\n");
662        return nullptr;
663    }
664    if (pipelineDescriptor.fragmentFunction == nil) {
665        SkDebugf("Couldn't find fragmentMain() in library\n");
666        return nullptr;
667    }
668    SkASSERT(pipelineDescriptor.vertexFunction);
669    SkASSERT(pipelineDescriptor.fragmentFunction);
670
671    NSError* error = nil;
672    id<MTLRenderPipelineState> pipelineState;
673    {
674        TRACE_EVENT0("skia.shaders", "newRenderPipelineStateWithDescriptor");
675        if (@available(macOS 10.15, *)) {
676            pipelineState = [fGpu->device() newRenderPipelineStateWithDescriptor: pipelineDescriptor
677                                                                           error: &error];
678        } else {
679            pipelineState = GrMtlNewRenderPipelineStateWithDescriptor(
680                    fGpu->device(), pipelineDescriptor, &error);
681        }
682    }
683    if (error) {
684        SkDebugf("Error creating pipeline: %s\n",
685                 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
686        return nullptr;
687    }
688    if (!pipelineState) {
689        return nullptr;
690    }
691
692    sk_sp<GrMtlRenderPipeline> renderPipeline = GrMtlRenderPipeline::Make(pipelineState);
693
694    uint32_t bufferSize = buffer_size(fUniformHandler.fCurrentUBOOffset,
695                                      fUniformHandler.fCurrentUBOMaxAlignment);
696    return new GrMtlPipelineState(fGpu,
697                                  std::move(renderPipeline),
698                                  pipelineDescriptor.colorAttachments[0].pixelFormat,
699                                  fUniformHandles,
700                                  fUniformHandler.fUniforms,
701                                  bufferSize,
702                                  (uint32_t)fUniformHandler.numSamplers(),
703                                  std::move(fGPImpl),
704                                  std::move(fXPImpl),
705                                  std::move(fFPImpls));
706}
707
708//////////////////////////////////////////////////////////////////////////////
709
710bool GrMtlPipelineStateBuilder::PrecompileShaders(GrMtlGpu* gpu, const SkData& cachedData,
711                                                  GrMtlPrecompiledLibraries* precompiledLibs) {
712    SkASSERT(precompiledLibs);
713
714    SkReadBuffer reader(cachedData.data(), cachedData.size());
715    SkFourByteTag shaderType = GrPersistentCacheUtils::GetType(&reader);
716
717    auto errorHandler = gpu->getContext()->priv().getShaderErrorHandler();
718
719    SkSL::ProgramSettings settings;
720    settings.fSharpenTextures = gpu->getContext()->priv().options().fSharpenMipmappedTextures;
721    GrPersistentCacheUtils::ShaderMetadata meta;
722    meta.fSettings = &settings;
723
724    std::string shaders[kGrShaderTypeCount];
725    SkSL::Program::Interface interfaces[kGrShaderTypeCount];
726    if (!GrPersistentCacheUtils::UnpackCachedShaders(
727                &reader, shaders, interfaces, kGrShaderTypeCount, &meta)) {
728        return false;
729    }
730
731    // skip the size
732    reader.readUInt();
733    auto pipelineDescriptor = read_pipeline_data(&reader);
734    if (!reader.isValid()) {
735        return false;
736    }
737
738    switch (shaderType) {
739        case kMSL_Tag: {
740            precompiledLibs->fVertexLibrary =
741                    GrCompileMtlShaderLibrary(gpu, shaders[kVertex_GrShaderType], errorHandler);
742            precompiledLibs->fFragmentLibrary =
743                    GrCompileMtlShaderLibrary(gpu, shaders[kFragment_GrShaderType], errorHandler);
744            break;
745        }
746
747        case kSKSL_Tag: {
748            std::string msl[kGrShaderTypeCount];
749            if (!skgpu::SkSLToMSL(gpu->caps()->shaderCaps(),
750                                  shaders[kVertex_GrShaderType],
751                                  SkSL::ProgramKind::kVertex,
752                                  settings,
753                                  &msl[kVertex_GrShaderType],
754                                  &interfaces[kVertex_GrShaderType],
755                                  errorHandler)) {
756                return false;
757            }
758            if (!skgpu::SkSLToMSL(gpu->caps()->shaderCaps(),
759                                  shaders[kFragment_GrShaderType],
760                                  SkSL::ProgramKind::kFragment,
761                                  settings,
762                                  &msl[kFragment_GrShaderType],
763                                  &interfaces[kFragment_GrShaderType],
764                                  errorHandler)) {
765                return false;
766            }
767            precompiledLibs->fVertexLibrary =
768                    GrCompileMtlShaderLibrary(gpu, msl[kVertex_GrShaderType], errorHandler);
769            precompiledLibs->fFragmentLibrary =
770                    GrCompileMtlShaderLibrary(gpu, msl[kFragment_GrShaderType], errorHandler);
771            break;
772        }
773
774        default: {
775            return false;
776        }
777    }
778
779    pipelineDescriptor.vertexFunction =
780            [precompiledLibs->fVertexLibrary newFunctionWithName: @"vertexMain"];
781    pipelineDescriptor.fragmentFunction =
782            [precompiledLibs->fFragmentLibrary newFunctionWithName: @"fragmentMain"];
783
784    {
785        TRACE_EVENT0("skia.shaders", "newRenderPipelineStateWithDescriptor");
786        MTLNewRenderPipelineStateCompletionHandler completionHandler =
787                 ^(id<MTLRenderPipelineState> state, NSError* error) {
788                     if (error) {
789                         SkDebugf("Error creating pipeline: %s\n",
790                                  [[error localizedDescription]
791                                           cStringUsingEncoding: NSASCIIStringEncoding]);
792                     }
793                 };
794
795        // kick off asynchronous pipeline build and depend on Apple's cache to manage it
796        [gpu->device() newRenderPipelineStateWithDescriptor: pipelineDescriptor
797                                          completionHandler: completionHandler];
798    }
799
800    precompiledLibs->fRTFlip = (interfaces[kFragment_GrShaderType].fRTFlipUniform !=
801                                SkSL::Program::Interface::kRTFlip_None);
802    return true;
803}
804
805GR_NORETAIN_END
806