• 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/GrContext.h"
11#include "src/core/SkReader32.h"
12#include "src/gpu/GrAutoLocaleSetter.h"
13#include "src/gpu/GrContextPriv.h"
14#include "src/gpu/GrPersistentCacheUtils.h"
15#include "src/gpu/GrRenderTargetPriv.h"
16#include "src/gpu/GrShaderUtils.h"
17
18#include "src/gpu/mtl/GrMtlGpu.h"
19#include "src/gpu/mtl/GrMtlPipelineState.h"
20#include "src/gpu/mtl/GrMtlUtil.h"
21
22#import <simd/simd.h>
23
24#if !__has_feature(objc_arc)
25#error This file must be compiled with Arc. Use -fobjc-arc flag
26#endif
27
28GrMtlPipelineState* GrMtlPipelineStateBuilder::CreatePipelineState(
29                                                                GrMtlGpu* gpu,
30                                                                GrRenderTarget* renderTarget,
31                                                                const GrProgramDesc& desc,
32                                                                const GrProgramInfo& programInfo) {
33    GrAutoLocaleSetter als("C");
34    GrMtlPipelineStateBuilder builder(gpu, renderTarget, desc, programInfo);
35
36    if (!builder.emitAndInstallProcs()) {
37        return nullptr;
38    }
39    return builder.finalize(renderTarget, desc, programInfo);
40}
41
42GrMtlPipelineStateBuilder::GrMtlPipelineStateBuilder(GrMtlGpu* gpu,
43                                                     GrRenderTarget* renderTarget,
44                                                     const GrProgramDesc& desc,
45                                                     const GrProgramInfo& programInfo)
46        : INHERITED(renderTarget, desc, programInfo)
47        , fGpu(gpu)
48        , fUniformHandler(this)
49        , fVaryingHandler(this) {
50}
51
52const GrCaps* GrMtlPipelineStateBuilder::caps() const {
53    return fGpu->caps();
54}
55
56void GrMtlPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) {
57    outputColor.addLayoutQualifier("location = 0, index = 0");
58}
59
60void GrMtlPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
61    outputColor.addLayoutQualifier("location = 0, index = 1");
62}
63
64static constexpr SkFourByteTag kMSL_Tag = SkSetFourByteTag('M', 'S', 'L', ' ');
65static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
66
67
68void GrMtlPipelineStateBuilder::loadShadersFromCache(SkReader32* cached,
69                                                     __strong id<MTLLibrary> outLibraries[]) {
70    SkSL::String shaders[kGrShaderTypeCount];
71    SkSL::Program::Inputs inputs[kGrShaderTypeCount];
72
73    GrPersistentCacheUtils::UnpackCachedShaders(cached, shaders, inputs, kGrShaderTypeCount);
74
75    outLibraries[kVertex_GrShaderType] = this->compileMtlShaderLibrary(
76                                              shaders[kVertex_GrShaderType],
77                                              inputs[kVertex_GrShaderType]);
78    outLibraries[kFragment_GrShaderType] = this->compileMtlShaderLibrary(
79                                                shaders[kFragment_GrShaderType],
80                                                inputs[kFragment_GrShaderType]);
81
82    // Geometry shaders are not supported
83    SkASSERT(shaders[kGeometry_GrShaderType].empty());
84
85    SkASSERT(outLibraries[kVertex_GrShaderType]);
86    SkASSERT(outLibraries[kFragment_GrShaderType]);
87}
88
89void GrMtlPipelineStateBuilder::storeShadersInCache(const SkSL::String shaders[],
90                                                    const SkSL::Program::Inputs inputs[],
91                                                    bool isSkSL) {
92    // Here we shear off the Mtl-specific portion of the Desc in order to create the
93    // persistent key. This is because Mtl only caches the MSL code, not the fully compiled
94    // program, and that only depends on the base GrProgramDesc data.
95    sk_sp<SkData> key = SkData::MakeWithoutCopy(this->desc().asKey(),
96                                                this->desc().initialKeyLength());
97    sk_sp<SkData> data = GrPersistentCacheUtils::PackCachedShaders(isSkSL ? kSKSL_Tag : kMSL_Tag,
98                                                                   shaders,
99                                                                   inputs, kGrShaderTypeCount);
100    fGpu->getContext()->priv().getPersistentCache()->store(*key, *data);
101}
102
103id<MTLLibrary> GrMtlPipelineStateBuilder::generateMtlShaderLibrary(
104        const SkSL::String& shader,
105        SkSL::Program::Kind kind,
106        const SkSL::Program::Settings& settings,
107        SkSL::String* msl,
108        SkSL::Program::Inputs* inputs) {
109    id<MTLLibrary> shaderLibrary = GrGenerateMtlShaderLibrary(fGpu, shader,
110                                                              kind, settings, msl, inputs);
111    if (shaderLibrary != nil && inputs->fRTHeight) {
112        this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
113    }
114    return shaderLibrary;
115}
116
117id<MTLLibrary> GrMtlPipelineStateBuilder::compileMtlShaderLibrary(const SkSL::String& shader,
118                                                                  SkSL::Program::Inputs inputs) {
119    id<MTLLibrary> shaderLibrary = GrCompileMtlShaderLibrary(fGpu, shader);
120    if (shaderLibrary != nil && inputs.fRTHeight) {
121        this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
122    }
123    return shaderLibrary;
124}
125
126static inline MTLVertexFormat attribute_type_to_mtlformat(GrVertexAttribType type) {
127    switch (type) {
128        case kFloat_GrVertexAttribType:
129            return MTLVertexFormatFloat;
130        case kFloat2_GrVertexAttribType:
131            return MTLVertexFormatFloat2;
132        case kFloat3_GrVertexAttribType:
133            return MTLVertexFormatFloat3;
134        case kFloat4_GrVertexAttribType:
135            return MTLVertexFormatFloat4;
136        case kHalf_GrVertexAttribType:
137            if (@available(macOS 10.13, iOS 11.0, *)) {
138                return MTLVertexFormatHalf;
139            } else {
140                return MTLVertexFormatInvalid;
141            }
142        case kHalf2_GrVertexAttribType:
143            return MTLVertexFormatHalf2;
144        case kHalf3_GrVertexAttribType:
145            return MTLVertexFormatHalf3;
146        case kHalf4_GrVertexAttribType:
147            return MTLVertexFormatHalf4;
148        case kInt2_GrVertexAttribType:
149            return MTLVertexFormatInt2;
150        case kInt3_GrVertexAttribType:
151            return MTLVertexFormatInt3;
152        case kInt4_GrVertexAttribType:
153            return MTLVertexFormatInt4;
154        case kByte_GrVertexAttribType:
155            if (@available(macOS 10.13, iOS 11.0, *)) {
156                return MTLVertexFormatChar;
157            } else {
158                return MTLVertexFormatInvalid;
159            }
160        case kByte2_GrVertexAttribType:
161            return MTLVertexFormatChar2;
162        case kByte3_GrVertexAttribType:
163            return MTLVertexFormatChar3;
164        case kByte4_GrVertexAttribType:
165            return MTLVertexFormatChar4;
166        case kUByte_GrVertexAttribType:
167            if (@available(macOS 10.13, iOS 11.0, *)) {
168                return MTLVertexFormatUChar;
169            } else {
170                return MTLVertexFormatInvalid;
171            }
172        case kUByte2_GrVertexAttribType:
173            return MTLVertexFormatUChar2;
174        case kUByte3_GrVertexAttribType:
175            return MTLVertexFormatUChar3;
176        case kUByte4_GrVertexAttribType:
177            return MTLVertexFormatUChar4;
178        case kUByte_norm_GrVertexAttribType:
179            if (@available(macOS 10.13, iOS 11.0, *)) {
180                return MTLVertexFormatUCharNormalized;
181            } else {
182                return MTLVertexFormatInvalid;
183            }
184        case kUByte4_norm_GrVertexAttribType:
185            return MTLVertexFormatUChar4Normalized;
186        case kShort2_GrVertexAttribType:
187            return MTLVertexFormatShort2;
188        case kShort4_GrVertexAttribType:
189            return MTLVertexFormatShort4;
190        case kUShort2_GrVertexAttribType:
191            return MTLVertexFormatUShort2;
192        case kUShort2_norm_GrVertexAttribType:
193            return MTLVertexFormatUShort2Normalized;
194        case kInt_GrVertexAttribType:
195            return MTLVertexFormatInt;
196        case kUint_GrVertexAttribType:
197            return MTLVertexFormatUInt;
198        case kUShort_norm_GrVertexAttribType:
199            if (@available(macOS 10.13, iOS 11.0, *)) {
200                return MTLVertexFormatUShortNormalized;
201            } else {
202                return MTLVertexFormatInvalid;
203            }
204        case kUShort4_norm_GrVertexAttribType:
205            return MTLVertexFormatUShort4Normalized;
206    }
207    SK_ABORT("Unknown vertex attribute type");
208}
209
210static MTLVertexDescriptor* create_vertex_descriptor(const GrPrimitiveProcessor& primProc) {
211    uint32_t vertexBinding = 0, instanceBinding = 0;
212
213    int nextBinding = GrMtlUniformHandler::kLastUniformBinding + 1;
214    if (primProc.hasVertexAttributes()) {
215        vertexBinding = nextBinding++;
216    }
217
218    if (primProc.hasInstanceAttributes()) {
219        instanceBinding = nextBinding;
220    }
221
222    auto vertexDescriptor = [[MTLVertexDescriptor alloc] init];
223    int attributeIndex = 0;
224
225    int vertexAttributeCount = primProc.numVertexAttributes();
226    size_t vertexAttributeOffset = 0;
227    for (const auto& attribute : primProc.vertexAttributes()) {
228        MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
229        mtlAttribute.format = attribute_type_to_mtlformat(attribute.cpuType());
230        SkASSERT(MTLVertexFormatInvalid != mtlAttribute.format);
231        mtlAttribute.offset = vertexAttributeOffset;
232        mtlAttribute.bufferIndex = vertexBinding;
233
234        vertexAttributeOffset += attribute.sizeAlign4();
235        attributeIndex++;
236    }
237    SkASSERT(vertexAttributeOffset == primProc.vertexStride());
238
239    if (vertexAttributeCount) {
240        MTLVertexBufferLayoutDescriptor* vertexBufferLayout =
241                vertexDescriptor.layouts[vertexBinding];
242        vertexBufferLayout.stepFunction = MTLVertexStepFunctionPerVertex;
243        vertexBufferLayout.stepRate = 1;
244        vertexBufferLayout.stride = vertexAttributeOffset;
245    }
246
247    int instanceAttributeCount = primProc.numInstanceAttributes();
248    size_t instanceAttributeOffset = 0;
249    for (const auto& attribute : primProc.instanceAttributes()) {
250        MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
251        mtlAttribute.format = attribute_type_to_mtlformat(attribute.cpuType());
252        mtlAttribute.offset = instanceAttributeOffset;
253        mtlAttribute.bufferIndex = instanceBinding;
254
255        instanceAttributeOffset += attribute.sizeAlign4();
256        attributeIndex++;
257    }
258    SkASSERT(instanceAttributeOffset == primProc.instanceStride());
259
260    if (instanceAttributeCount) {
261        MTLVertexBufferLayoutDescriptor* instanceBufferLayout =
262                vertexDescriptor.layouts[instanceBinding];
263        instanceBufferLayout.stepFunction = MTLVertexStepFunctionPerInstance;
264        instanceBufferLayout.stepRate = 1;
265        instanceBufferLayout.stride = instanceAttributeOffset;
266    }
267    return vertexDescriptor;
268}
269
270static MTLBlendFactor blend_coeff_to_mtl_blend(GrBlendCoeff coeff) {
271    switch (coeff) {
272        case kZero_GrBlendCoeff:
273            return MTLBlendFactorZero;
274        case kOne_GrBlendCoeff:
275            return MTLBlendFactorOne;
276        case kSC_GrBlendCoeff:
277            return MTLBlendFactorSourceColor;
278        case kISC_GrBlendCoeff:
279            return MTLBlendFactorOneMinusSourceColor;
280        case kDC_GrBlendCoeff:
281            return MTLBlendFactorDestinationColor;
282        case kIDC_GrBlendCoeff:
283            return MTLBlendFactorOneMinusDestinationColor;
284        case kSA_GrBlendCoeff:
285            return MTLBlendFactorSourceAlpha;
286        case kISA_GrBlendCoeff:
287            return MTLBlendFactorOneMinusSourceAlpha;
288        case kDA_GrBlendCoeff:
289            return MTLBlendFactorDestinationAlpha;
290        case kIDA_GrBlendCoeff:
291            return MTLBlendFactorOneMinusDestinationAlpha;
292        case kConstC_GrBlendCoeff:
293            return MTLBlendFactorBlendColor;
294        case kIConstC_GrBlendCoeff:
295            return MTLBlendFactorOneMinusBlendColor;
296        case kConstA_GrBlendCoeff:
297            return MTLBlendFactorBlendAlpha;
298        case kIConstA_GrBlendCoeff:
299            return MTLBlendFactorOneMinusBlendAlpha;
300        case kS2C_GrBlendCoeff:
301            if (@available(macOS 10.12, iOS 11.0, *)) {
302                return MTLBlendFactorSource1Color;
303            } else {
304                return MTLBlendFactorZero;
305            }
306        case kIS2C_GrBlendCoeff:
307            if (@available(macOS 10.12, iOS 11.0, *)) {
308                return MTLBlendFactorOneMinusSource1Color;
309            } else {
310                return MTLBlendFactorZero;
311            }
312        case kS2A_GrBlendCoeff:
313            if (@available(macOS 10.12, iOS 11.0, *)) {
314                return MTLBlendFactorSource1Alpha;
315            } else {
316                return MTLBlendFactorZero;
317            }
318        case kIS2A_GrBlendCoeff:
319            if (@available(macOS 10.12, iOS 11.0, *)) {
320                return MTLBlendFactorOneMinusSource1Alpha;
321            } else {
322                return MTLBlendFactorZero;
323            }
324        case kIllegal_GrBlendCoeff:
325            return MTLBlendFactorZero;
326    }
327
328    SK_ABORT("Unknown blend coefficient");
329}
330
331static MTLBlendOperation blend_equation_to_mtl_blend_op(GrBlendEquation equation) {
332    static const MTLBlendOperation gTable[] = {
333        MTLBlendOperationAdd,              // kAdd_GrBlendEquation
334        MTLBlendOperationSubtract,         // kSubtract_GrBlendEquation
335        MTLBlendOperationReverseSubtract,  // kReverseSubtract_GrBlendEquation
336    };
337    static_assert(SK_ARRAY_COUNT(gTable) == kFirstAdvancedGrBlendEquation);
338    static_assert(0 == kAdd_GrBlendEquation);
339    static_assert(1 == kSubtract_GrBlendEquation);
340    static_assert(2 == kReverseSubtract_GrBlendEquation);
341
342    SkASSERT((unsigned)equation < kGrBlendEquationCnt);
343    return gTable[equation];
344}
345
346static MTLRenderPipelineColorAttachmentDescriptor* create_color_attachment(
347        MTLPixelFormat format, const GrPipeline& pipeline) {
348    auto mtlColorAttachment = [[MTLRenderPipelineColorAttachmentDescriptor alloc] init];
349
350    // pixel format
351    mtlColorAttachment.pixelFormat = format;
352
353    // blending
354    const GrXferProcessor::BlendInfo& blendInfo = pipeline.getXferProcessor().getBlendInfo();
355
356    GrBlendEquation equation = blendInfo.fEquation;
357    GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
358    GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
359    bool blendOff = (kAdd_GrBlendEquation == equation || kSubtract_GrBlendEquation == equation) &&
360                    kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff;
361
362    mtlColorAttachment.blendingEnabled = !blendOff;
363    if (!blendOff) {
364        mtlColorAttachment.sourceRGBBlendFactor = blend_coeff_to_mtl_blend(srcCoeff);
365        mtlColorAttachment.destinationRGBBlendFactor = blend_coeff_to_mtl_blend(dstCoeff);
366        mtlColorAttachment.rgbBlendOperation = blend_equation_to_mtl_blend_op(equation);
367        mtlColorAttachment.sourceAlphaBlendFactor = blend_coeff_to_mtl_blend(srcCoeff);
368        mtlColorAttachment.destinationAlphaBlendFactor = blend_coeff_to_mtl_blend(dstCoeff);
369        mtlColorAttachment.alphaBlendOperation = blend_equation_to_mtl_blend_op(equation);
370    }
371
372    if (!blendInfo.fWriteColor) {
373        mtlColorAttachment.writeMask = MTLColorWriteMaskNone;
374    } else {
375        mtlColorAttachment.writeMask = MTLColorWriteMaskAll;
376    }
377    return mtlColorAttachment;
378}
379
380uint32_t buffer_size(uint32_t offset, uint32_t maxAlignment) {
381    // Metal expects the buffer to be padded at the end according to the alignment
382    // of the largest element in the buffer.
383    uint32_t offsetDiff = offset & maxAlignment;
384    if (offsetDiff != 0) {
385        offsetDiff = maxAlignment - offsetDiff + 1;
386    }
387    return offset + offsetDiff;
388}
389
390GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize(GrRenderTarget* renderTarget,
391                                                        const GrProgramDesc& desc,
392                                                        const GrProgramInfo& programInfo) {
393    auto pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
394    id<MTLLibrary> shaderLibraries[kGrShaderTypeCount];
395
396    fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
397    fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
398    fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
399    fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
400
401    this->finalizeShaders();
402
403    SkSL::Program::Settings settings;
404    settings.fCaps = this->caps()->shaderCaps();
405    settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
406    settings.fSharpenTextures = fGpu->getContext()->priv().options().fSharpenMipmappedTextures;
407    SkASSERT(!this->fragColorIsInOut());
408
409    sk_sp<SkData> cached;
410    SkReader32 reader;
411    SkFourByteTag shaderType = 0;
412    auto persistentCache = fGpu->getContext()->priv().getPersistentCache();
413    if (persistentCache) {
414        // Here we shear off the Mtl-specific portion of the Desc in order to create the
415        // persistent key. This is because Mtl only caches the MSL code, not the fully compiled
416        // program, and that only depends on the base GrProgramDesc data.
417        sk_sp<SkData> key = SkData::MakeWithoutCopy(desc.asKey(), desc.initialKeyLength());
418        cached = persistentCache->load(*key);
419        if (cached) {
420            reader.setMemory(cached->data(), cached->size());
421            shaderType = reader.readU32();
422        }
423    }
424
425    SkSL::String shaders[kGrShaderTypeCount];
426    if (kMSL_Tag == shaderType) {
427        this->loadShadersFromCache(&reader, shaderLibraries);
428    } else {
429        SkSL::Program::Inputs inputs[kGrShaderTypeCount];
430
431        SkSL::String* sksl[kGrShaderTypeCount] = {
432            &fVS.fCompilerString,
433            nullptr,              // geometry shaders not supported
434            &fFS.fCompilerString,
435        };
436        SkSL::String cached_sksl[kGrShaderTypeCount];
437        if (kSKSL_Tag == shaderType) {
438            GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, inputs,
439                                                        kGrShaderTypeCount);
440            for (int i = 0; i < kGrShaderTypeCount; ++i) {
441                sksl[i] = &cached_sksl[i];
442            }
443        }
444
445        shaderLibraries[kVertex_GrShaderType] = this->generateMtlShaderLibrary(
446                                                     *sksl[kVertex_GrShaderType],
447                                                     SkSL::Program::kVertex_Kind,
448                                                     settings,
449                                                     &shaders[kVertex_GrShaderType],
450                                                     &inputs[kVertex_GrShaderType]);
451        shaderLibraries[kFragment_GrShaderType] = this->generateMtlShaderLibrary(
452                                                       *sksl[kFragment_GrShaderType],
453                                                       SkSL::Program::kFragment_Kind,
454                                                       settings,
455                                                       &shaders[kFragment_GrShaderType],
456                                                       &inputs[kFragment_GrShaderType]);
457
458        // Geometry shaders are not supported
459        SkASSERT(!this->primitiveProcessor().willUseGeoShader());
460
461        if (!shaderLibraries[kVertex_GrShaderType] || !shaderLibraries[kFragment_GrShaderType]) {
462            return nullptr;
463        }
464
465        if (persistentCache && !cached) {
466            bool isSkSL = false;
467            if (fGpu->getContext()->priv().options().fShaderCacheStrategy ==
468                    GrContextOptions::ShaderCacheStrategy::kSkSL) {
469                for (int i = 0; i < kGrShaderTypeCount; ++i) {
470                    if (sksl[i]) {
471                        shaders[i] = GrShaderUtils::PrettyPrint(*sksl[i]);
472                    }
473                }
474                isSkSL = true;
475            }
476            this->storeShadersInCache(shaders, inputs, isSkSL);
477        }
478    }
479
480    id<MTLFunction> vertexFunction =
481            [shaderLibraries[kVertex_GrShaderType] newFunctionWithName: @"vertexMain"];
482    id<MTLFunction> fragmentFunction =
483            [shaderLibraries[kFragment_GrShaderType] newFunctionWithName: @"fragmentMain"];
484
485    if (vertexFunction == nil) {
486        SkDebugf("Couldn't find vertexMain() in library\n");
487        return nullptr;
488    }
489    if (fragmentFunction == nil) {
490        SkDebugf("Couldn't find fragmentMain() in library\n");
491        return nullptr;
492    }
493
494    pipelineDescriptor.vertexFunction = vertexFunction;
495    pipelineDescriptor.fragmentFunction = fragmentFunction;
496    pipelineDescriptor.vertexDescriptor = create_vertex_descriptor(programInfo.primProc());
497
498    MTLPixelFormat pixelFormat = GrBackendFormatAsMTLPixelFormat(renderTarget->backendFormat());
499    if (pixelFormat == MTLPixelFormatInvalid) {
500        return nullptr;
501    }
502
503    pipelineDescriptor.colorAttachments[0] = create_color_attachment(pixelFormat,
504                                                                     programInfo.pipeline());
505    pipelineDescriptor.sampleCount = programInfo.numRasterSamples();
506    bool hasStencilAttachment = SkToBool(renderTarget->renderTargetPriv().getStencilAttachment());
507    GrMtlCaps* mtlCaps = (GrMtlCaps*)this->caps();
508    pipelineDescriptor.stencilAttachmentPixelFormat =
509        hasStencilAttachment ? mtlCaps->preferredStencilFormat().fInternalFormat
510                             : MTLPixelFormatInvalid;
511
512    SkASSERT(pipelineDescriptor.vertexFunction);
513    SkASSERT(pipelineDescriptor.fragmentFunction);
514    SkASSERT(pipelineDescriptor.vertexDescriptor);
515    SkASSERT(pipelineDescriptor.colorAttachments[0]);
516
517    NSError* error = nil;
518#if defined(SK_BUILD_FOR_MAC)
519    id<MTLRenderPipelineState> pipelineState = GrMtlNewRenderPipelineStateWithDescriptor(
520                                                     fGpu->device(), pipelineDescriptor, &error);
521#else
522    id<MTLRenderPipelineState> pipelineState =
523            [fGpu->device() newRenderPipelineStateWithDescriptor: pipelineDescriptor
524                                                           error: &error];
525#endif
526    if (error) {
527        SkDebugf("Error creating pipeline: %s\n",
528                 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
529        return nullptr;
530    }
531    if (!pipelineState) {
532        return nullptr;
533    }
534
535    uint32_t bufferSize = buffer_size(fUniformHandler.fCurrentUBOOffset,
536                                      fUniformHandler.fCurrentUBOMaxAlignment);
537    return new GrMtlPipelineState(fGpu,
538                                  pipelineState,
539                                  pipelineDescriptor.colorAttachments[0].pixelFormat,
540                                  fUniformHandles,
541                                  fUniformHandler.fUniforms,
542                                  bufferSize,
543                                  (uint32_t)fUniformHandler.numSamplers(),
544                                  std::move(fGeometryProcessor),
545                                  std::move(fXferProcessor),
546                                  std::move(fFragmentProcessors),
547                                  fFragmentProcessorCnt);
548}
549
550//////////////////////////////////////////////////////////////////////////////
551
552