blob: 5168358bd7e0a2c42c62df10ad9a5f55ffa1420a [file] [log] [blame]
Timothy Liang7ac582e2018-08-06 09:47:23 -04001/*
Timothy Liang44636e92018-08-08 10:50:21 -04002 * 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 */
Timothy Liang7ac582e2018-08-06 09:47:23 -04007
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#import <simd/simd.h>
18
19GrMtlPipelineState* GrMtlPipelineStateBuilder::CreatePipelineState(
Robert Phillipsd0fe8752019-01-31 14:13:59 -050020 GrRenderTarget* renderTarget, GrSurfaceOrigin origin,
Timothy Liang7ac582e2018-08-06 09:47:23 -040021 const GrPrimitiveProcessor& primProc,
Greg Daniel9a51a862018-11-30 10:18:14 -050022 const GrTextureProxy* const primProcProxies[],
Timothy Liang7ac582e2018-08-06 09:47:23 -040023 const GrPipeline& pipeline,
24 GrProgramDesc* desc,
25 GrMtlGpu* gpu) {
Robert Phillipsd0fe8752019-01-31 14:13:59 -050026 GrMtlPipelineStateBuilder builder(renderTarget, origin, primProc, primProcProxies, pipeline,
27 desc, gpu);
Timothy Liang7ac582e2018-08-06 09:47:23 -040028
29 if (!builder.emitAndInstallProcs()) {
30 return nullptr;
31 }
32 return builder.finalize(primProc, pipeline, desc);
33}
34
Robert Phillipsd0fe8752019-01-31 14:13:59 -050035GrMtlPipelineStateBuilder::GrMtlPipelineStateBuilder(GrRenderTarget* renderTarget, GrSurfaceOrigin origin,
36 const GrPrimitiveProcessor& primProc,
Greg Daniel9a51a862018-11-30 10:18:14 -050037 const GrTextureProxy* const primProcProxies[],
Timothy Liang7ac582e2018-08-06 09:47:23 -040038 const GrPipeline& pipeline,
39 GrProgramDesc* desc,
40 GrMtlGpu* gpu)
Robert Phillipsd0fe8752019-01-31 14:13:59 -050041 : INHERITED(renderTarget, origin, primProc, primProcProxies, pipeline, desc)
Timothy Liang057c3902018-08-08 10:48:45 -040042 , fGpu(gpu)
43 , fUniformHandler(this)
44 , fVaryingHandler(this) {
Timothy Liang7ac582e2018-08-06 09:47:23 -040045}
46
47const GrCaps* GrMtlPipelineStateBuilder::caps() const {
48 return fGpu->caps();
49}
50
51void GrMtlPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) {
52 outputColor.addLayoutQualifier("location = 0, index = 0");
53}
54
55void GrMtlPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
56 outputColor.addLayoutQualifier("location = 0, index = 1");
57}
58
59id<MTLLibrary> GrMtlPipelineStateBuilder::createMtlShaderLibrary(
60 const GrGLSLShaderBuilder& builder,
61 SkSL::Program::Kind kind,
62 const SkSL::Program::Settings& settings,
63 GrProgramDesc* desc) {
64 SkString shaderString;
65 for (int i = 0; i < builder.fCompilerStrings.count(); ++i) {
66 if (builder.fCompilerStrings[i]) {
67 shaderString.append(builder.fCompilerStrings[i]);
68 shaderString.append("\n");
69 }
70 }
71
72 SkSL::Program::Inputs inputs;
73 id<MTLLibrary> shaderLibrary = GrCompileMtlShaderLibrary(fGpu, shaderString.c_str(),
74 kind, settings, &inputs);
75 if (shaderLibrary == nil) {
76 return nil;
77 }
Greg Daniele6ab9982018-08-22 13:56:32 +000078 if (inputs.fRTHeight) {
79 this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
Timothy Liang7ac582e2018-08-06 09:47:23 -040080 }
81 if (inputs.fFlipY) {
Robert Phillipsd0fe8752019-01-31 14:13:59 -050082 desc->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(this->origin()));
Timothy Liang7ac582e2018-08-06 09:47:23 -040083 }
84 return shaderLibrary;
85}
86
87static inline MTLVertexFormat attribute_type_to_mtlformat(GrVertexAttribType type) {
88 // All half types will actually be float types. We are currently not using half types with
89 // metal to avoid an issue with narrow type coercions (float->half) http://skbug.com/8221
90 switch (type) {
91 case kFloat_GrVertexAttribType:
Timothy Liang7ac582e2018-08-06 09:47:23 -040092 return MTLVertexFormatFloat;
93 case kFloat2_GrVertexAttribType:
Timothy Liang7ac582e2018-08-06 09:47:23 -040094 return MTLVertexFormatFloat2;
95 case kFloat3_GrVertexAttribType:
Timothy Liang7ac582e2018-08-06 09:47:23 -040096 return MTLVertexFormatFloat3;
97 case kFloat4_GrVertexAttribType:
Timothy Liang7ac582e2018-08-06 09:47:23 -040098 return MTLVertexFormatFloat4;
Brian Osmand4c29702018-09-14 16:16:55 -040099 case kHalf_GrVertexAttribType:
100 return MTLVertexFormatHalf;
101 case kHalf2_GrVertexAttribType:
102 return MTLVertexFormatHalf2;
103 case kHalf3_GrVertexAttribType:
104 return MTLVertexFormatHalf3;
105 case kHalf4_GrVertexAttribType:
106 return MTLVertexFormatHalf4;
Timothy Liang7ac582e2018-08-06 09:47:23 -0400107 case kInt2_GrVertexAttribType:
108 return MTLVertexFormatInt2;
109 case kInt3_GrVertexAttribType:
110 return MTLVertexFormatInt3;
111 case kInt4_GrVertexAttribType:
112 return MTLVertexFormatInt4;
113 case kByte_GrVertexAttribType:
114 return MTLVertexFormatChar;
115 case kByte2_GrVertexAttribType:
116 return MTLVertexFormatChar2;
117 case kByte3_GrVertexAttribType:
118 return MTLVertexFormatChar3;
119 case kByte4_GrVertexAttribType:
120 return MTLVertexFormatChar4;
121 case kUByte_GrVertexAttribType:
122 return MTLVertexFormatUChar;
123 case kUByte2_GrVertexAttribType:
124 return MTLVertexFormatUChar2;
125 case kUByte3_GrVertexAttribType:
126 return MTLVertexFormatUChar3;
127 case kUByte4_GrVertexAttribType:
128 return MTLVertexFormatUChar4;
129 case kUByte_norm_GrVertexAttribType:
130 return MTLVertexFormatUCharNormalized;
131 case kUByte4_norm_GrVertexAttribType:
132 return MTLVertexFormatUChar4Normalized;
133 case kShort2_GrVertexAttribType:
134 return MTLVertexFormatShort2;
Brian Osmana5c578f2018-09-19 14:19:02 -0400135 case kShort4_GrVertexAttribType:
136 return MTLVertexFormatShort4;
Timothy Liang7ac582e2018-08-06 09:47:23 -0400137 case kUShort2_GrVertexAttribType:
138 return MTLVertexFormatUShort2;
139 case kUShort2_norm_GrVertexAttribType:
140 return MTLVertexFormatUShort2Normalized;
141 case kInt_GrVertexAttribType:
142 return MTLVertexFormatInt;
143 case kUint_GrVertexAttribType:
144 return MTLVertexFormatUInt;
145 }
146 SK_ABORT("Unknown vertex attribute type");
147 return MTLVertexFormatInvalid;
148}
149
150static MTLVertexDescriptor* create_vertex_descriptor(const GrPrimitiveProcessor& primProc) {
151 uint32_t vertexBinding = 0, instanceBinding = 0;
152
Timothy Liang057c3902018-08-08 10:48:45 -0400153 int nextBinding = GrMtlUniformHandler::kLastUniformBinding + 1;
Timothy Liang7ac582e2018-08-06 09:47:23 -0400154 if (primProc.hasVertexAttributes()) {
155 vertexBinding = nextBinding++;
156 }
157
158 if (primProc.hasInstanceAttributes()) {
159 instanceBinding = nextBinding;
160 }
161
162 auto vertexDescriptor = [[MTLVertexDescriptor alloc] init];
163 int attributeIndex = 0;
164
165 int vertexAttributeCount = primProc.numVertexAttributes();
166 size_t vertexAttributeOffset = 0;
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500167 for (const auto& attribute : primProc.vertexAttributes()) {
Timothy Liang7ac582e2018-08-06 09:47:23 -0400168 MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
Brian Osmand4c29702018-09-14 16:16:55 -0400169 mtlAttribute.format = attribute_type_to_mtlformat(attribute.cpuType());
Timothy Liang7ac582e2018-08-06 09:47:23 -0400170 mtlAttribute.offset = vertexAttributeOffset;
171 mtlAttribute.bufferIndex = vertexBinding;
172
Timothy Liang7ac582e2018-08-06 09:47:23 -0400173 vertexAttributeOffset += attribute.sizeAlign4();
174 attributeIndex++;
175 }
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500176 SkASSERT(vertexAttributeOffset == primProc.vertexStride());
Timothy Liang7ac582e2018-08-06 09:47:23 -0400177
178 if (vertexAttributeCount) {
179 MTLVertexBufferLayoutDescriptor* vertexBufferLayout =
180 vertexDescriptor.layouts[vertexBinding];
181 vertexBufferLayout.stepFunction = MTLVertexStepFunctionPerVertex;
182 vertexBufferLayout.stepRate = 1;
183 vertexBufferLayout.stride = vertexAttributeOffset;
184 }
185
186 int instanceAttributeCount = primProc.numInstanceAttributes();
187 size_t instanceAttributeOffset = 0;
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500188 for (const auto& attribute : primProc.instanceAttributes()) {
Timothy Liang7ac582e2018-08-06 09:47:23 -0400189 MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
Brian Osmand4c29702018-09-14 16:16:55 -0400190 mtlAttribute.format = attribute_type_to_mtlformat(attribute.cpuType());
Timothy Liang7ac582e2018-08-06 09:47:23 -0400191 mtlAttribute.offset = instanceAttributeOffset;
192 mtlAttribute.bufferIndex = instanceBinding;
193
Timothy Liang7ac582e2018-08-06 09:47:23 -0400194 instanceAttributeOffset += attribute.sizeAlign4();
195 attributeIndex++;
196 }
Brian Osmanf04fb3c2018-11-12 15:34:00 -0500197 SkASSERT(instanceAttributeOffset == primProc.instanceStride());
Timothy Liang7ac582e2018-08-06 09:47:23 -0400198
199 if (instanceAttributeCount) {
200 MTLVertexBufferLayoutDescriptor* instanceBufferLayout =
201 vertexDescriptor.layouts[instanceBinding];
202 instanceBufferLayout.stepFunction = MTLVertexStepFunctionPerInstance;
203 instanceBufferLayout.stepRate = 1;
204 instanceBufferLayout.stride = instanceAttributeOffset;
205 }
206 return vertexDescriptor;
207}
208
209static MTLBlendFactor blend_coeff_to_mtl_blend(GrBlendCoeff coeff) {
210 static const MTLBlendFactor gTable[] = {
211 MTLBlendFactorZero, // kZero_GrBlendCoeff
212 MTLBlendFactorOne, // kOne_GrBlendCoeff
213 MTLBlendFactorSourceColor, // kSC_GrBlendCoeff
214 MTLBlendFactorOneMinusSourceColor, // kISC_GrBlendCoeff
215 MTLBlendFactorDestinationColor, // kDC_GrBlendCoeff
216 MTLBlendFactorOneMinusDestinationColor, // kIDC_GrBlendCoeff
217 MTLBlendFactorSourceAlpha, // kSA_GrBlendCoeff
218 MTLBlendFactorOneMinusSourceAlpha, // kISA_GrBlendCoeff
219 MTLBlendFactorDestinationAlpha, // kDA_GrBlendCoeff
220 MTLBlendFactorOneMinusDestinationAlpha, // kIDA_GrBlendCoeff
221 MTLBlendFactorBlendColor, // kConstC_GrBlendCoeff
222 MTLBlendFactorOneMinusBlendColor, // kIConstC_GrBlendCoeff
223 MTLBlendFactorBlendAlpha, // kConstA_GrBlendCoeff
224 MTLBlendFactorOneMinusBlendAlpha, // kIConstA_GrBlendCoeff
225 MTLBlendFactorSource1Color, // kS2C_GrBlendCoeff
226 MTLBlendFactorOneMinusSource1Color, // kIS2C_GrBlendCoeff
227 MTLBlendFactorSource1Alpha, // kS2A_GrBlendCoeff
228 MTLBlendFactorOneMinusSource1Alpha, // kIS2A_GrBlendCoeff
Mike Klein36743362018-11-06 08:23:30 -0500229 MTLBlendFactorZero, // kIllegal_GrBlendCoeff
Timothy Liang7ac582e2018-08-06 09:47:23 -0400230 };
231 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kGrBlendCoeffCnt);
232 GR_STATIC_ASSERT(0 == kZero_GrBlendCoeff);
233 GR_STATIC_ASSERT(1 == kOne_GrBlendCoeff);
234 GR_STATIC_ASSERT(2 == kSC_GrBlendCoeff);
235 GR_STATIC_ASSERT(3 == kISC_GrBlendCoeff);
236 GR_STATIC_ASSERT(4 == kDC_GrBlendCoeff);
237 GR_STATIC_ASSERT(5 == kIDC_GrBlendCoeff);
238 GR_STATIC_ASSERT(6 == kSA_GrBlendCoeff);
239 GR_STATIC_ASSERT(7 == kISA_GrBlendCoeff);
240 GR_STATIC_ASSERT(8 == kDA_GrBlendCoeff);
241 GR_STATIC_ASSERT(9 == kIDA_GrBlendCoeff);
242 GR_STATIC_ASSERT(10 == kConstC_GrBlendCoeff);
243 GR_STATIC_ASSERT(11 == kIConstC_GrBlendCoeff);
244 GR_STATIC_ASSERT(12 == kConstA_GrBlendCoeff);
245 GR_STATIC_ASSERT(13 == kIConstA_GrBlendCoeff);
246 GR_STATIC_ASSERT(14 == kS2C_GrBlendCoeff);
247 GR_STATIC_ASSERT(15 == kIS2C_GrBlendCoeff);
248 GR_STATIC_ASSERT(16 == kS2A_GrBlendCoeff);
249 GR_STATIC_ASSERT(17 == kIS2A_GrBlendCoeff);
250
Timothy Liang7ac582e2018-08-06 09:47:23 -0400251 SkASSERT((unsigned)coeff < kGrBlendCoeffCnt);
252 return gTable[coeff];
253}
254
255static MTLBlendOperation blend_equation_to_mtl_blend_op(GrBlendEquation equation) {
256 static const MTLBlendOperation gTable[] = {
257 MTLBlendOperationAdd, // kAdd_GrBlendEquation
258 MTLBlendOperationSubtract, // kSubtract_GrBlendEquation
259 MTLBlendOperationReverseSubtract, // kReverseSubtract_GrBlendEquation
260 };
261 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kFirstAdvancedGrBlendEquation);
262 GR_STATIC_ASSERT(0 == kAdd_GrBlendEquation);
263 GR_STATIC_ASSERT(1 == kSubtract_GrBlendEquation);
264 GR_STATIC_ASSERT(2 == kReverseSubtract_GrBlendEquation);
265
Mike Klein36743362018-11-06 08:23:30 -0500266 SkASSERT((unsigned)equation < kGrBlendEquationCnt);
Timothy Liang7ac582e2018-08-06 09:47:23 -0400267 return gTable[equation];
268}
269
270static MTLRenderPipelineColorAttachmentDescriptor* create_color_attachment(
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500271 GrPixelConfig config, const GrPipeline& pipeline) {
Timothy Liang7ac582e2018-08-06 09:47:23 -0400272 auto mtlColorAttachment = [[MTLRenderPipelineColorAttachmentDescriptor alloc] init];
273
274 // pixel format
275 MTLPixelFormat format;
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500276 SkAssertResult(GrPixelConfigToMTLFormat(config, &format));
Timothy Liang7ac582e2018-08-06 09:47:23 -0400277 mtlColorAttachment.pixelFormat = format;
278
279 // blending
280 GrXferProcessor::BlendInfo blendInfo;
281 pipeline.getXferProcessor().getBlendInfo(&blendInfo);
282
283 GrBlendEquation equation = blendInfo.fEquation;
284 GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
285 GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
286 bool blendOff = (kAdd_GrBlendEquation == equation || kSubtract_GrBlendEquation == equation) &&
287 kOne_GrBlendCoeff == srcCoeff && kZero_GrBlendCoeff == dstCoeff;
288
289 mtlColorAttachment.blendingEnabled = !blendOff;
290 if (!blendOff) {
291 mtlColorAttachment.sourceRGBBlendFactor = blend_coeff_to_mtl_blend(srcCoeff);
292 mtlColorAttachment.destinationRGBBlendFactor = blend_coeff_to_mtl_blend(dstCoeff);
293 mtlColorAttachment.rgbBlendOperation = blend_equation_to_mtl_blend_op(equation);
294 mtlColorAttachment.sourceAlphaBlendFactor = blend_coeff_to_mtl_blend(srcCoeff);
295 mtlColorAttachment.destinationAlphaBlendFactor = blend_coeff_to_mtl_blend(dstCoeff);
296 mtlColorAttachment.alphaBlendOperation = blend_equation_to_mtl_blend_op(equation);
297 }
298
299 if (!blendInfo.fWriteColor) {
300 mtlColorAttachment.writeMask = MTLColorWriteMaskNone;
301 } else {
302 mtlColorAttachment.writeMask = MTLColorWriteMaskAll;
303 }
304 return mtlColorAttachment;
305}
306
Timothy Liang7ac582e2018-08-06 09:47:23 -0400307GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize(const GrPrimitiveProcessor& primProc,
308 const GrPipeline& pipeline,
309 GrProgramDesc* desc) {
310 auto pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
311
312 fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
313 fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
314 fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
315 fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
316
317 this->finalizeShaders();
318
319 SkSL::Program::Settings settings;
320 settings.fCaps = this->caps()->shaderCaps();
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500321 settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
Robert Phillips9da87e02019-02-04 13:26:26 -0500322 settings.fSharpenTextures = fGpu->getContext()->priv().options().fSharpenMipmappedTextures;
Timothy Liang7ac582e2018-08-06 09:47:23 -0400323 SkASSERT(!this->fragColorIsInOut());
324
325 id<MTLLibrary> vertexLibrary = nil;
326 id<MTLLibrary> fragmentLibrary = nil;
327 vertexLibrary = this->createMtlShaderLibrary(fVS,
328 SkSL::Program::kVertex_Kind,
329 settings,
330 desc);
331 fragmentLibrary = this->createMtlShaderLibrary(fFS,
332 SkSL::Program::kFragment_Kind,
333 settings,
334 desc);
335 SkASSERT(!this->primitiveProcessor().willUseGeoShader());
336
337 SkASSERT(vertexLibrary);
338 SkASSERT(fragmentLibrary);
339
340 id<MTLFunction> vertexFunction = [vertexLibrary newFunctionWithName: @"vertexMain"];
341 id<MTLFunction> fragmentFunction = [fragmentLibrary newFunctionWithName: @"fragmentMain"];
342
343 pipelineDescriptor.vertexFunction = vertexFunction;
344 pipelineDescriptor.fragmentFunction = fragmentFunction;
345 pipelineDescriptor.vertexDescriptor = create_vertex_descriptor(primProc);
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500346 pipelineDescriptor.colorAttachments[0] = create_color_attachment(this->config(), pipeline);
Timothy Liang7ac582e2018-08-06 09:47:23 -0400347
348 SkASSERT(pipelineDescriptor.vertexFunction);
349 SkASSERT(pipelineDescriptor.fragmentFunction);
350 SkASSERT(pipelineDescriptor.vertexDescriptor);
351 SkASSERT(pipelineDescriptor.colorAttachments[0]);
352
353 NSError* error = nil;
354 id<MTLRenderPipelineState> pipelineState =
355 [fGpu->device() newRenderPipelineStateWithDescriptor: pipelineDescriptor
356 error: &error];
357 if (error) {
358 SkDebugf("Error creating pipeline: %s\n",
359 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
Timothy Liang6ed63962018-08-10 09:49:44 -0400360 return nullptr;
Timothy Liang7ac582e2018-08-06 09:47:23 -0400361 }
Timothy Liang057c3902018-08-08 10:48:45 -0400362 return new GrMtlPipelineState(fGpu,
363 pipelineState,
364 pipelineDescriptor.colorAttachments[0].pixelFormat,
Timothy Liang6ed63962018-08-10 09:49:44 -0400365 fUniformHandles,
366 fUniformHandler.fUniforms,
Brian Salomon12d22642019-01-29 14:38:50 -0500367 GrMtlBuffer::Make(fGpu,
368 fUniformHandler.fCurrentGeometryUBOOffset,
Brian Salomonae64c192019-02-05 09:41:37 -0500369 GrGpuBufferType::kVertex,
Brian Salomon12d22642019-01-29 14:38:50 -0500370 kStatic_GrAccessPattern),
371 GrMtlBuffer::Make(fGpu,
372 fUniformHandler.fCurrentFragmentUBOOffset,
Brian Salomonae64c192019-02-05 09:41:37 -0500373 GrGpuBufferType::kVertex,
Brian Salomon12d22642019-01-29 14:38:50 -0500374 kStatic_GrAccessPattern),
Timothy Liang6ed63962018-08-10 09:49:44 -0400375 (uint32_t)fUniformHandler.numSamplers(),
376 std::move(fGeometryProcessor),
377 std::move(fXferProcessor),
378 std::move(fFragmentProcessors),
379 fFragmentProcessorCnt);
Timothy Liang7ac582e2018-08-06 09:47:23 -0400380}