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