blob: 9339d97326922a61d6dc328908928ab0b687bedc [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(
20 const GrPrimitiveProcessor& primProc,
21 const GrPipeline& pipeline,
22 GrProgramDesc* desc,
23 GrMtlGpu* gpu) {
24 GrMtlPipelineStateBuilder builder(primProc, pipeline, desc, gpu);
25
26 if (!builder.emitAndInstallProcs()) {
27 return nullptr;
28 }
29 return builder.finalize(primProc, pipeline, desc);
30}
31
32GrMtlPipelineStateBuilder::GrMtlPipelineStateBuilder(const GrPrimitiveProcessor& primProc,
33 const GrPipeline& pipeline,
34 GrProgramDesc* desc,
35 GrMtlGpu* gpu)
36 : INHERITED(primProc, pipeline, desc)
Timothy Liang057c3902018-08-08 10:48:45 -040037 , fGpu(gpu)
38 , fUniformHandler(this)
39 , fVaryingHandler(this) {
Timothy Liang7ac582e2018-08-06 09:47:23 -040040}
41
42const GrCaps* GrMtlPipelineStateBuilder::caps() const {
43 return fGpu->caps();
44}
45
46void GrMtlPipelineStateBuilder::finalizeFragmentOutputColor(GrShaderVar& outputColor) {
47 outputColor.addLayoutQualifier("location = 0, index = 0");
48}
49
50void GrMtlPipelineStateBuilder::finalizeFragmentSecondaryColor(GrShaderVar& outputColor) {
51 outputColor.addLayoutQualifier("location = 0, index = 1");
52}
53
54id<MTLLibrary> GrMtlPipelineStateBuilder::createMtlShaderLibrary(
55 const GrGLSLShaderBuilder& builder,
56 SkSL::Program::Kind kind,
57 const SkSL::Program::Settings& settings,
58 GrProgramDesc* desc) {
59 SkString shaderString;
60 for (int i = 0; i < builder.fCompilerStrings.count(); ++i) {
61 if (builder.fCompilerStrings[i]) {
62 shaderString.append(builder.fCompilerStrings[i]);
63 shaderString.append("\n");
64 }
65 }
66
67 SkSL::Program::Inputs inputs;
68 id<MTLLibrary> shaderLibrary = GrCompileMtlShaderLibrary(fGpu, shaderString.c_str(),
69 kind, settings, &inputs);
70 if (shaderLibrary == nil) {
71 return nil;
72 }
Greg Daniele6ab9982018-08-22 13:56:32 +000073 if (inputs.fRTHeight) {
74 this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
Timothy Liang7ac582e2018-08-06 09:47:23 -040075 }
76 if (inputs.fFlipY) {
77 desc->setSurfaceOriginKey(GrGLSLFragmentShaderBuilder::KeyForSurfaceOrigin(
78 this->pipeline().proxy()->origin()));
79 desc->finalize();
80 }
81 return shaderLibrary;
82}
83
84static inline MTLVertexFormat attribute_type_to_mtlformat(GrVertexAttribType type) {
85 // All half types will actually be float types. We are currently not using half types with
86 // metal to avoid an issue with narrow type coercions (float->half) http://skbug.com/8221
87 switch (type) {
88 case kFloat_GrVertexAttribType:
Timothy Liang7ac582e2018-08-06 09:47:23 -040089 return MTLVertexFormatFloat;
90 case kFloat2_GrVertexAttribType:
Timothy Liang7ac582e2018-08-06 09:47:23 -040091 return MTLVertexFormatFloat2;
92 case kFloat3_GrVertexAttribType:
Timothy Liang7ac582e2018-08-06 09:47:23 -040093 return MTLVertexFormatFloat3;
94 case kFloat4_GrVertexAttribType:
Timothy Liang7ac582e2018-08-06 09:47:23 -040095 return MTLVertexFormatFloat4;
Brian Osmand4c29702018-09-14 16:16:55 -040096 case kHalf_GrVertexAttribType:
97 return MTLVertexFormatHalf;
98 case kHalf2_GrVertexAttribType:
99 return MTLVertexFormatHalf2;
100 case kHalf3_GrVertexAttribType:
101 return MTLVertexFormatHalf3;
102 case kHalf4_GrVertexAttribType:
103 return MTLVertexFormatHalf4;
Timothy Liang7ac582e2018-08-06 09:47:23 -0400104 case kInt2_GrVertexAttribType:
105 return MTLVertexFormatInt2;
106 case kInt3_GrVertexAttribType:
107 return MTLVertexFormatInt3;
108 case kInt4_GrVertexAttribType:
109 return MTLVertexFormatInt4;
110 case kByte_GrVertexAttribType:
111 return MTLVertexFormatChar;
112 case kByte2_GrVertexAttribType:
113 return MTLVertexFormatChar2;
114 case kByte3_GrVertexAttribType:
115 return MTLVertexFormatChar3;
116 case kByte4_GrVertexAttribType:
117 return MTLVertexFormatChar4;
118 case kUByte_GrVertexAttribType:
119 return MTLVertexFormatUChar;
120 case kUByte2_GrVertexAttribType:
121 return MTLVertexFormatUChar2;
122 case kUByte3_GrVertexAttribType:
123 return MTLVertexFormatUChar3;
124 case kUByte4_GrVertexAttribType:
125 return MTLVertexFormatUChar4;
126 case kUByte_norm_GrVertexAttribType:
127 return MTLVertexFormatUCharNormalized;
128 case kUByte4_norm_GrVertexAttribType:
129 return MTLVertexFormatUChar4Normalized;
130 case kShort2_GrVertexAttribType:
131 return MTLVertexFormatShort2;
Brian Osmand2ca0472018-09-17 15:39:36 -0400132 case kShort4_GrVertexAttribType:
133 return MTLVertexFormatShort4;
Timothy Liang7ac582e2018-08-06 09:47:23 -0400134 case kUShort2_GrVertexAttribType:
135 return MTLVertexFormatUShort2;
136 case kUShort2_norm_GrVertexAttribType:
137 return MTLVertexFormatUShort2Normalized;
138 case kInt_GrVertexAttribType:
139 return MTLVertexFormatInt;
140 case kUint_GrVertexAttribType:
141 return MTLVertexFormatUInt;
142 }
143 SK_ABORT("Unknown vertex attribute type");
144 return MTLVertexFormatInvalid;
145}
146
147static MTLVertexDescriptor* create_vertex_descriptor(const GrPrimitiveProcessor& primProc) {
148 uint32_t vertexBinding = 0, instanceBinding = 0;
149
Timothy Liang057c3902018-08-08 10:48:45 -0400150 int nextBinding = GrMtlUniformHandler::kLastUniformBinding + 1;
Timothy Liang7ac582e2018-08-06 09:47:23 -0400151 if (primProc.hasVertexAttributes()) {
152 vertexBinding = nextBinding++;
153 }
154
155 if (primProc.hasInstanceAttributes()) {
156 instanceBinding = nextBinding;
157 }
158
159 auto vertexDescriptor = [[MTLVertexDescriptor alloc] init];
160 int attributeIndex = 0;
161
162 int vertexAttributeCount = primProc.numVertexAttributes();
163 size_t vertexAttributeOffset = 0;
164 for (int vertexIndex = 0; vertexIndex < vertexAttributeCount; vertexIndex++) {
165 const GrGeometryProcessor::Attribute& attribute = primProc.vertexAttribute(vertexIndex);
166 MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
Brian Osmand4c29702018-09-14 16:16:55 -0400167 mtlAttribute.format = attribute_type_to_mtlformat(attribute.cpuType());
Timothy Liang7ac582e2018-08-06 09:47:23 -0400168 mtlAttribute.offset = vertexAttributeOffset;
169 mtlAttribute.bufferIndex = vertexBinding;
170
171 SkASSERT(mtlAttribute.offset == primProc.debugOnly_vertexAttributeOffset(vertexIndex));
172 vertexAttributeOffset += attribute.sizeAlign4();
173 attributeIndex++;
174 }
175 SkASSERT(vertexAttributeOffset == primProc.debugOnly_vertexStride());
176
177 if (vertexAttributeCount) {
178 MTLVertexBufferLayoutDescriptor* vertexBufferLayout =
179 vertexDescriptor.layouts[vertexBinding];
180 vertexBufferLayout.stepFunction = MTLVertexStepFunctionPerVertex;
181 vertexBufferLayout.stepRate = 1;
182 vertexBufferLayout.stride = vertexAttributeOffset;
183 }
184
185 int instanceAttributeCount = primProc.numInstanceAttributes();
186 size_t instanceAttributeOffset = 0;
187 for (int instanceIndex = 0; instanceIndex < instanceAttributeCount; instanceIndex++) {
188 const GrGeometryProcessor::Attribute& attribute = primProc.instanceAttribute(instanceIndex);
189 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
194 SkASSERT(mtlAttribute.offset == primProc.debugOnly_instanceAttributeOffset(instanceIndex));
195 instanceAttributeOffset += attribute.sizeAlign4();
196 attributeIndex++;
197 }
198 SkASSERT(instanceAttributeOffset == primProc.debugOnly_instanceStride());
199
200 if (instanceAttributeCount) {
201 MTLVertexBufferLayoutDescriptor* instanceBufferLayout =
202 vertexDescriptor.layouts[instanceBinding];
203 instanceBufferLayout.stepFunction = MTLVertexStepFunctionPerInstance;
204 instanceBufferLayout.stepRate = 1;
205 instanceBufferLayout.stride = instanceAttributeOffset;
206 }
207 return vertexDescriptor;
208}
209
210static MTLBlendFactor blend_coeff_to_mtl_blend(GrBlendCoeff coeff) {
211 static const MTLBlendFactor gTable[] = {
212 MTLBlendFactorZero, // kZero_GrBlendCoeff
213 MTLBlendFactorOne, // kOne_GrBlendCoeff
214 MTLBlendFactorSourceColor, // kSC_GrBlendCoeff
215 MTLBlendFactorOneMinusSourceColor, // kISC_GrBlendCoeff
216 MTLBlendFactorDestinationColor, // kDC_GrBlendCoeff
217 MTLBlendFactorOneMinusDestinationColor, // kIDC_GrBlendCoeff
218 MTLBlendFactorSourceAlpha, // kSA_GrBlendCoeff
219 MTLBlendFactorOneMinusSourceAlpha, // kISA_GrBlendCoeff
220 MTLBlendFactorDestinationAlpha, // kDA_GrBlendCoeff
221 MTLBlendFactorOneMinusDestinationAlpha, // kIDA_GrBlendCoeff
222 MTLBlendFactorBlendColor, // kConstC_GrBlendCoeff
223 MTLBlendFactorOneMinusBlendColor, // kIConstC_GrBlendCoeff
224 MTLBlendFactorBlendAlpha, // kConstA_GrBlendCoeff
225 MTLBlendFactorOneMinusBlendAlpha, // kIConstA_GrBlendCoeff
226 MTLBlendFactorSource1Color, // kS2C_GrBlendCoeff
227 MTLBlendFactorOneMinusSource1Color, // kIS2C_GrBlendCoeff
228 MTLBlendFactorSource1Alpha, // kS2A_GrBlendCoeff
229 MTLBlendFactorOneMinusSource1Alpha, // kIS2A_GrBlendCoeff
230 };
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
266 SkASSERT((unsigned)equation < kGrBlendCoeffCnt);
267 return gTable[equation];
268}
269
270static MTLRenderPipelineColorAttachmentDescriptor* create_color_attachment(
271 const GrPipeline& pipeline) {
272 auto mtlColorAttachment = [[MTLRenderPipelineColorAttachmentDescriptor alloc] init];
273
274 // pixel format
275 MTLPixelFormat format;
Timothy Liang512875a2018-08-06 14:43:54 -0400276 SkAssertResult(GrPixelConfigToMTLFormat(pipeline.renderTarget()->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
307
308GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize(const GrPrimitiveProcessor& primProc,
309 const GrPipeline& pipeline,
310 GrProgramDesc* desc) {
311 auto pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
312
313 fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
314 fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
315 fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
316 fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
317
318 this->finalizeShaders();
319
320 SkSL::Program::Settings settings;
321 settings.fCaps = this->caps()->shaderCaps();
322 settings.fFlipY = this->pipeline().proxy()->origin() != kTopLeft_GrSurfaceOrigin;
323 settings.fSharpenTextures = fGpu->getContext()->contextPriv().sharpenMipmappedTextures();
324 SkASSERT(!this->fragColorIsInOut());
325
326 id<MTLLibrary> vertexLibrary = nil;
327 id<MTLLibrary> fragmentLibrary = nil;
328 vertexLibrary = this->createMtlShaderLibrary(fVS,
329 SkSL::Program::kVertex_Kind,
330 settings,
331 desc);
332 fragmentLibrary = this->createMtlShaderLibrary(fFS,
333 SkSL::Program::kFragment_Kind,
334 settings,
335 desc);
336 SkASSERT(!this->primitiveProcessor().willUseGeoShader());
337
338 SkASSERT(vertexLibrary);
339 SkASSERT(fragmentLibrary);
340
341 id<MTLFunction> vertexFunction = [vertexLibrary newFunctionWithName: @"vertexMain"];
342 id<MTLFunction> fragmentFunction = [fragmentLibrary newFunctionWithName: @"fragmentMain"];
343
344 pipelineDescriptor.vertexFunction = vertexFunction;
345 pipelineDescriptor.fragmentFunction = fragmentFunction;
346 pipelineDescriptor.vertexDescriptor = create_vertex_descriptor(primProc);
347 pipelineDescriptor.colorAttachments[0] = create_color_attachment(pipeline);
348
349 SkASSERT(pipelineDescriptor.vertexFunction);
350 SkASSERT(pipelineDescriptor.fragmentFunction);
351 SkASSERT(pipelineDescriptor.vertexDescriptor);
352 SkASSERT(pipelineDescriptor.colorAttachments[0]);
353
354 NSError* error = nil;
355 id<MTLRenderPipelineState> pipelineState =
356 [fGpu->device() newRenderPipelineStateWithDescriptor: pipelineDescriptor
357 error: &error];
358 if (error) {
359 SkDebugf("Error creating pipeline: %s\n",
360 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
Timothy Liang6ed63962018-08-10 09:49:44 -0400361 return nullptr;
Timothy Liang7ac582e2018-08-06 09:47:23 -0400362 }
Timothy Liang057c3902018-08-08 10:48:45 -0400363 return new GrMtlPipelineState(fGpu,
364 pipelineState,
365 pipelineDescriptor.colorAttachments[0].pixelFormat,
Timothy Liang6ed63962018-08-10 09:49:44 -0400366 fUniformHandles,
367 fUniformHandler.fUniforms,
Timothy Liang057c3902018-08-08 10:48:45 -0400368 GrMtlBuffer::Create(fGpu,
369 fUniformHandler.fCurrentGeometryUBOOffset,
370 kVertex_GrBufferType,
371 kStatic_GrAccessPattern),
372 GrMtlBuffer::Create(fGpu,
373 fUniformHandler.fCurrentFragmentUBOOffset,
374 kVertex_GrBufferType,
Timothy Liang6ed63962018-08-10 09:49:44 -0400375 kStatic_GrAccessPattern),
376 (uint32_t)fUniformHandler.numSamplers(),
377 std::move(fGeometryProcessor),
378 std::move(fXferProcessor),
379 std::move(fFragmentProcessors),
380 fFragmentProcessorCnt);
Timothy Liang7ac582e2018-08-06 09:47:23 -0400381}