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 "GrMtlPipelineStateBuilder.h" 9 10#include "GrContext.h" 11#include "GrContextPriv.h" 12 13#include "GrMtlGpu.h" 14#include "GrMtlPipelineState.h" 15#include "GrMtlUtil.h" 16 17#include "GrRenderTargetPriv.h" 18 19#import <simd/simd.h> 20 21GrMtlPipelineState* GrMtlPipelineStateBuilder::CreatePipelineState( 22 GrMtlGpu* gpu, 23 GrRenderTarget* renderTarget, GrSurfaceOrigin origin, 24 const GrPrimitiveProcessor& primProc, 25 const GrTextureProxy* const primProcProxies[], 26 const GrPipeline& pipeline, 27 Desc* desc) { 28 GrMtlPipelineStateBuilder builder(gpu, renderTarget, origin, pipeline, primProc, 29 primProcProxies, desc); 30 31 if (!builder.emitAndInstallProcs()) { 32 return nullptr; 33 } 34 return builder.finalize(renderTarget, primProc, pipeline, desc); 35} 36 37GrMtlPipelineStateBuilder::GrMtlPipelineStateBuilder(GrMtlGpu* gpu, 38 GrRenderTarget* renderTarget, 39 GrSurfaceOrigin origin, 40 const GrPipeline& pipeline, 41 const GrPrimitiveProcessor& primProc, 42 const GrTextureProxy* const primProcProxies[], 43 GrProgramDesc* desc) 44 : INHERITED(renderTarget, origin, primProc, primProcProxies, pipeline, desc) 45 , fGpu(gpu) 46 , fUniformHandler(this) 47 , fVaryingHandler(this) { 48} 49 50const GrCaps* GrMtlPipelineStateBuilder::caps() const { 51 return fGpu->caps(); 52} 53 54void GrMtlPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) { 55 outputColor.addLayoutQualifier("location = 0, index = 0"); 56} 57 58void GrMtlPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) { 59 outputColor.addLayoutQualifier("location = 0, index = 1"); 60} 61 62id<MTLLibrary> GrMtlPipelineStateBuilder::createMtlShaderLibrary( 63 const GrGLSLShaderBuilder& builder, 64 SkSL::Program::Kind kind, 65 const SkSL::Program::Settings& settings, 66 GrProgramDesc* desc) { 67 SkString shaderString; 68 for (int i = 0; i < builder.fCompilerStrings.count(); ++i) { 69 if (builder.fCompilerStrings[i]) { 70 shaderString.append(builder.fCompilerStrings[i]); 71 shaderString.append("\n"); 72 } 73 } 74 75 SkSL::Program::Inputs inputs; 76 id<MTLLibrary> shaderLibrary = GrCompileMtlShaderLibrary(fGpu, shaderString.c_str(), 77 kind, settings, &inputs); 78 if (shaderLibrary == nil) { 79 return nil; 80 } 81 if (inputs.fRTHeight) { 82 this->addRTHeightUniform(SKSL_RTHEIGHT_NAME); 83 } 84 if (inputs.fFlipY) { 85 desc->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(this->origin())); 86 } 87 return shaderLibrary; 88} 89 90static inline MTLVertexFormat attribute_type_to_mtlformat(GrVertexAttribType type) { 91 // All half types will actually be float types. We are currently not using half types with 92 // metal to avoid an issue with narrow type coercions (float->half) http://skbug.com/8221 93 switch (type) { 94 case kFloat_GrVertexAttribType: 95 return MTLVertexFormatFloat; 96 case kFloat2_GrVertexAttribType: 97 return MTLVertexFormatFloat2; 98 case kFloat3_GrVertexAttribType: 99 return MTLVertexFormatFloat3; 100 case kFloat4_GrVertexAttribType: 101 return MTLVertexFormatFloat4; 102 case kHalf_GrVertexAttribType: 103 return MTLVertexFormatHalf; 104 case kHalf2_GrVertexAttribType: 105 return MTLVertexFormatHalf2; 106 case kHalf3_GrVertexAttribType: 107 return MTLVertexFormatHalf3; 108 case kHalf4_GrVertexAttribType: 109 return MTLVertexFormatHalf4; 110 case kInt2_GrVertexAttribType: 111 return MTLVertexFormatInt2; 112 case kInt3_GrVertexAttribType: 113 return MTLVertexFormatInt3; 114 case kInt4_GrVertexAttribType: 115 return MTLVertexFormatInt4; 116 case kByte_GrVertexAttribType: 117 return MTLVertexFormatChar; 118 case kByte2_GrVertexAttribType: 119 return MTLVertexFormatChar2; 120 case kByte3_GrVertexAttribType: 121 return MTLVertexFormatChar3; 122 case kByte4_GrVertexAttribType: 123 return MTLVertexFormatChar4; 124 case kUByte_GrVertexAttribType: 125 return MTLVertexFormatUChar; 126 case kUByte2_GrVertexAttribType: 127 return MTLVertexFormatUChar2; 128 case kUByte3_GrVertexAttribType: 129 return MTLVertexFormatUChar3; 130 case kUByte4_GrVertexAttribType: 131 return MTLVertexFormatUChar4; 132 case kUByte_norm_GrVertexAttribType: 133 return MTLVertexFormatUCharNormalized; 134 case kUByte4_norm_GrVertexAttribType: 135 return MTLVertexFormatUChar4Normalized; 136 case kShort2_GrVertexAttribType: 137 return MTLVertexFormatShort2; 138 case kShort4_GrVertexAttribType: 139 return MTLVertexFormatShort4; 140 case kUShort2_GrVertexAttribType: 141 return MTLVertexFormatUShort2; 142 case kUShort2_norm_GrVertexAttribType: 143 return MTLVertexFormatUShort2Normalized; 144 case kInt_GrVertexAttribType: 145 return MTLVertexFormatInt; 146 case kUint_GrVertexAttribType: 147 return MTLVertexFormatUInt; 148 } 149 SK_ABORT("Unknown vertex attribute type"); 150 return MTLVertexFormatInvalid; 151} 152 153static MTLVertexDescriptor* create_vertex_descriptor(const GrPrimitiveProcessor& primProc) { 154 uint32_t vertexBinding = 0, instanceBinding = 0; 155 156 int nextBinding = GrMtlUniformHandler::kLastUniformBinding + 1; 157 if (primProc.hasVertexAttributes()) { 158 vertexBinding = nextBinding++; 159 } 160 161 if (primProc.hasInstanceAttributes()) { 162 instanceBinding = nextBinding; 163 } 164 165 auto vertexDescriptor = [[MTLVertexDescriptor alloc] init]; 166 int attributeIndex = 0; 167 168 int vertexAttributeCount = primProc.numVertexAttributes(); 169 size_t vertexAttributeOffset = 0; 170 for (const auto& attribute : primProc.vertexAttributes()) { 171 MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex]; 172 mtlAttribute.format = attribute_type_to_mtlformat(attribute.cpuType()); 173 mtlAttribute.offset = vertexAttributeOffset; 174 mtlAttribute.bufferIndex = vertexBinding; 175 176 vertexAttributeOffset += attribute.sizeAlign4(); 177 attributeIndex++; 178 } 179 SkASSERT(vertexAttributeOffset == primProc.vertexStride()); 180 181 if (vertexAttributeCount) { 182 MTLVertexBufferLayoutDescriptor* vertexBufferLayout = 183 vertexDescriptor.layouts[vertexBinding]; 184 vertexBufferLayout.stepFunction = MTLVertexStepFunctionPerVertex; 185 vertexBufferLayout.stepRate = 1; 186 vertexBufferLayout.stride = vertexAttributeOffset; 187 } 188 189 int instanceAttributeCount = primProc.numInstanceAttributes(); 190 size_t instanceAttributeOffset = 0; 191 for (const auto& attribute : primProc.instanceAttributes()) { 192 MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex]; 193 mtlAttribute.format = attribute_type_to_mtlformat(attribute.cpuType()); 194 mtlAttribute.offset = instanceAttributeOffset; 195 mtlAttribute.bufferIndex = instanceBinding; 196 197 instanceAttributeOffset += attribute.sizeAlign4(); 198 attributeIndex++; 199 } 200 SkASSERT(instanceAttributeOffset == primProc.instanceStride()); 201 202 if (instanceAttributeCount) { 203 MTLVertexBufferLayoutDescriptor* instanceBufferLayout = 204 vertexDescriptor.layouts[instanceBinding]; 205 instanceBufferLayout.stepFunction = MTLVertexStepFunctionPerInstance; 206 instanceBufferLayout.stepRate = 1; 207 instanceBufferLayout.stride = instanceAttributeOffset; 208 } 209 return vertexDescriptor; 210} 211 212static MTLBlendFactor blend_coeff_to_mtl_blend(GrBlendCoeff coeff) { 213 static const MTLBlendFactor gTable[] = { 214 MTLBlendFactorZero, // kZero_GrBlendCoeff 215 MTLBlendFactorOne, // kOne_GrBlendCoeff 216 MTLBlendFactorSourceColor, // kSC_GrBlendCoeff 217 MTLBlendFactorOneMinusSourceColor, // kISC_GrBlendCoeff 218 MTLBlendFactorDestinationColor, // kDC_GrBlendCoeff 219 MTLBlendFactorOneMinusDestinationColor, // kIDC_GrBlendCoeff 220 MTLBlendFactorSourceAlpha, // kSA_GrBlendCoeff 221 MTLBlendFactorOneMinusSourceAlpha, // kISA_GrBlendCoeff 222 MTLBlendFactorDestinationAlpha, // kDA_GrBlendCoeff 223 MTLBlendFactorOneMinusDestinationAlpha, // kIDA_GrBlendCoeff 224 MTLBlendFactorBlendColor, // kConstC_GrBlendCoeff 225 MTLBlendFactorOneMinusBlendColor, // kIConstC_GrBlendCoeff 226 MTLBlendFactorBlendAlpha, // kConstA_GrBlendCoeff 227 MTLBlendFactorOneMinusBlendAlpha, // kIConstA_GrBlendCoeff 228 MTLBlendFactorSource1Color, // kS2C_GrBlendCoeff 229 MTLBlendFactorOneMinusSource1Color, // kIS2C_GrBlendCoeff 230 MTLBlendFactorSource1Alpha, // kS2A_GrBlendCoeff 231 MTLBlendFactorOneMinusSource1Alpha, // kIS2A_GrBlendCoeff 232 MTLBlendFactorZero, // kIllegal_GrBlendCoeff 233 }; 234 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kGrBlendCoeffCnt); 235 GR_STATIC_ASSERT(0 == kZero_GrBlendCoeff); 236 GR_STATIC_ASSERT(1 == kOne_GrBlendCoeff); 237 GR_STATIC_ASSERT(2 == kSC_GrBlendCoeff); 238 GR_STATIC_ASSERT(3 == kISC_GrBlendCoeff); 239 GR_STATIC_ASSERT(4 == kDC_GrBlendCoeff); 240 GR_STATIC_ASSERT(5 == kIDC_GrBlendCoeff); 241 GR_STATIC_ASSERT(6 == kSA_GrBlendCoeff); 242 GR_STATIC_ASSERT(7 == kISA_GrBlendCoeff); 243 GR_STATIC_ASSERT(8 == kDA_GrBlendCoeff); 244 GR_STATIC_ASSERT(9 == kIDA_GrBlendCoeff); 245 GR_STATIC_ASSERT(10 == kConstC_GrBlendCoeff); 246 GR_STATIC_ASSERT(11 == kIConstC_GrBlendCoeff); 247 GR_STATIC_ASSERT(12 == kConstA_GrBlendCoeff); 248 GR_STATIC_ASSERT(13 == kIConstA_GrBlendCoeff); 249 GR_STATIC_ASSERT(14 == kS2C_GrBlendCoeff); 250 GR_STATIC_ASSERT(15 == kIS2C_GrBlendCoeff); 251 GR_STATIC_ASSERT(16 == kS2A_GrBlendCoeff); 252 GR_STATIC_ASSERT(17 == kIS2A_GrBlendCoeff); 253 254 SkASSERT((unsigned)coeff < kGrBlendCoeffCnt); 255 return gTable[coeff]; 256} 257 258static MTLBlendOperation blend_equation_to_mtl_blend_op(GrBlendEquation equation) { 259 static const MTLBlendOperation gTable[] = { 260 MTLBlendOperationAdd, // kAdd_GrBlendEquation 261 MTLBlendOperationSubtract, // kSubtract_GrBlendEquation 262 MTLBlendOperationReverseSubtract, // kReverseSubtract_GrBlendEquation 263 }; 264 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kFirstAdvancedGrBlendEquation); 265 GR_STATIC_ASSERT(0 == kAdd_GrBlendEquation); 266 GR_STATIC_ASSERT(1 == kSubtract_GrBlendEquation); 267 GR_STATIC_ASSERT(2 == kReverseSubtract_GrBlendEquation); 268 269 SkASSERT((unsigned)equation < kGrBlendEquationCnt); 270 return gTable[equation]; 271} 272 273static MTLRenderPipelineColorAttachmentDescriptor* create_color_attachment( 274 GrPixelConfig config, const GrPipeline& pipeline) { 275 auto mtlColorAttachment = [[MTLRenderPipelineColorAttachmentDescriptor alloc] init]; 276 277 // pixel format 278 MTLPixelFormat format; 279 SkAssertResult(GrPixelConfigToMTLFormat(config, &format)); 280 mtlColorAttachment.pixelFormat = format; 281 282 // blending 283 GrXferProcessor::BlendInfo blendInfo; 284 pipeline.getXferProcessor().getBlendInfo(&blendInfo); 285 286 GrBlendEquation equation = blendInfo.fEquation; 287 GrBlendCoeff srcCoeff = blendInfo.fSrcBlend; 288 GrBlendCoeff dstCoeff = blendInfo.fDstBlend; 289 bool blendOff = (kAdd_GrBlendEquation == equation || kSubtract_GrBlendEquation == equation) && 290 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff; 291 292 mtlColorAttachment.blendingEnabled = !blendOff; 293 if (!blendOff) { 294 mtlColorAttachment.sourceRGBBlendFactor = blend_coeff_to_mtl_blend(srcCoeff); 295 mtlColorAttachment.destinationRGBBlendFactor = blend_coeff_to_mtl_blend(dstCoeff); 296 mtlColorAttachment.rgbBlendOperation = blend_equation_to_mtl_blend_op(equation); 297 mtlColorAttachment.sourceAlphaBlendFactor = blend_coeff_to_mtl_blend(srcCoeff); 298 mtlColorAttachment.destinationAlphaBlendFactor = blend_coeff_to_mtl_blend(dstCoeff); 299 mtlColorAttachment.alphaBlendOperation = blend_equation_to_mtl_blend_op(equation); 300 } 301 302 if (!blendInfo.fWriteColor) { 303 mtlColorAttachment.writeMask = MTLColorWriteMaskNone; 304 } else { 305 mtlColorAttachment.writeMask = MTLColorWriteMaskAll; 306 } 307 return mtlColorAttachment; 308} 309 310uint32_t buffer_size(uint32_t offset, uint32_t maxAlignment) { 311 // Metal expects the buffer to be padded at the end according to the alignment 312 // of the largest element in the buffer. 313 uint32_t offsetDiff = offset & maxAlignment; 314 if (offsetDiff != 0) { 315 offsetDiff = maxAlignment - offsetDiff + 1; 316 } 317 return offset + offsetDiff; 318} 319 320GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize(GrRenderTarget* renderTarget, 321 const GrPrimitiveProcessor& primProc, 322 const GrPipeline& pipeline, 323 Desc* desc) { 324 auto pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; 325 326 fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n"); 327 fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n"); 328 fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n"); 329 fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n"); 330 331 this->finalizeShaders(); 332 333 SkSL::Program::Settings settings; 334 settings.fCaps = this->caps()->shaderCaps(); 335 settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin; 336 settings.fSharpenTextures = fGpu->getContext()->priv().options().fSharpenMipmappedTextures; 337 SkASSERT(!this->fragColorIsInOut()); 338 339 // TODO: Store shaders in cache 340 id<MTLLibrary> vertexLibrary = nil; 341 id<MTLLibrary> fragmentLibrary = nil; 342 vertexLibrary = this->createMtlShaderLibrary(fVS, 343 SkSL::Program::kVertex_Kind, 344 settings, 345 desc); 346 fragmentLibrary = this->createMtlShaderLibrary(fFS, 347 SkSL::Program::kFragment_Kind, 348 settings, 349 desc); 350 SkASSERT(!this->primitiveProcessor().willUseGeoShader()); 351 352 SkASSERT(vertexLibrary); 353 SkASSERT(fragmentLibrary); 354 355 id<MTLFunction> vertexFunction = [vertexLibrary newFunctionWithName: @"vertexMain"]; 356 id<MTLFunction> fragmentFunction = [fragmentLibrary newFunctionWithName: @"fragmentMain"]; 357 358 pipelineDescriptor.vertexFunction = vertexFunction; 359 pipelineDescriptor.fragmentFunction = fragmentFunction; 360 pipelineDescriptor.vertexDescriptor = create_vertex_descriptor(primProc); 361 pipelineDescriptor.colorAttachments[0] = create_color_attachment(this->config(), pipeline); 362 bool hasStencilAttachment = SkToBool(renderTarget->renderTargetPriv().getStencilAttachment()); 363 GrMtlCaps* mtlCaps = (GrMtlCaps*)this->caps(); 364 pipelineDescriptor.stencilAttachmentPixelFormat = 365 hasStencilAttachment ? mtlCaps->preferredStencilFormat().fInternalFormat 366 : MTLPixelFormatInvalid; 367 368 SkASSERT(pipelineDescriptor.vertexFunction); 369 SkASSERT(pipelineDescriptor.fragmentFunction); 370 SkASSERT(pipelineDescriptor.vertexDescriptor); 371 SkASSERT(pipelineDescriptor.colorAttachments[0]); 372 373 NSError* error = nil; 374 id<MTLRenderPipelineState> pipelineState = 375 [fGpu->device() newRenderPipelineStateWithDescriptor: pipelineDescriptor 376 error: &error]; 377 if (error) { 378 SkDebugf("Error creating pipeline: %s\n", 379 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]); 380 return nullptr; 381 } 382 uint32_t geomBufferSize = buffer_size(fUniformHandler.fCurrentGeometryUBOOffset, 383 fUniformHandler.fCurrentGeometryUBOMaxAlignment); 384 uint32_t fragBufferSize = buffer_size(fUniformHandler.fCurrentFragmentUBOOffset, 385 fUniformHandler.fCurrentFragmentUBOMaxAlignment); 386 return new GrMtlPipelineState(fGpu, 387 pipelineState, 388 pipelineDescriptor.colorAttachments[0].pixelFormat, 389 fUniformHandles, 390 fUniformHandler.fUniforms, 391 GrMtlBuffer::Make(fGpu, 392 geomBufferSize, 393 GrGpuBufferType::kVertex, 394 kStatic_GrAccessPattern), 395 GrMtlBuffer::Make(fGpu, 396 fragBufferSize, 397 GrGpuBufferType::kVertex, 398 kStatic_GrAccessPattern), 399 (uint32_t)fUniformHandler.numSamplers(), 400 std::move(fGeometryProcessor), 401 std::move(fXferProcessor), 402 std::move(fFragmentProcessors), 403 fFragmentProcessorCnt); 404} 405 406////////////////////////////////////////////////////////////////////////////// 407 408bool GrMtlPipelineStateBuilder::Desc::Build(Desc* desc, 409 GrRenderTarget* renderTarget, 410 const GrPrimitiveProcessor& primProc, 411 const GrPipeline& pipeline, 412 GrPrimitiveType primitiveType, 413 GrMtlGpu* gpu) { 414 if (!INHERITED::Build(desc, renderTarget, primProc, 415 GrPrimitiveType::kLines == primitiveType, pipeline, gpu)) { 416 return false; 417 } 418 419 GrProcessorKeyBuilder b(&desc->key()); 420 421 int keyLength = desc->key().count(); 422 SkASSERT(0 == (keyLength % 4)); 423 desc->fShaderKeyLength = SkToU32(keyLength); 424 425 b.add32(renderTarget->config()); 426 b.add32(renderTarget->numColorSamples()); 427 bool hasStencilAttachment = SkToBool(renderTarget->renderTargetPriv().getStencilAttachment()); 428 b.add32(hasStencilAttachment ? gpu->mtlCaps().preferredStencilFormat().fInternalFormat 429 : MTLPixelFormatInvalid); 430 b.add32((uint32_t)pipeline.isStencilEnabled()); 431 // Stencil samples don't seem to be tracked in the MTLRenderPipeline 432 433 b.add32(pipeline.getBlendInfoKey()); 434 435 b.add32((uint32_t)primitiveType); 436 437 return true; 438} 439