Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
MtlGraphicsPipeline.mm
Go to the documentation of this file.
1/*
2 * Copyright 2021 Google LLC
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
9
17
18namespace skgpu::graphite {
19
20namespace {
21
23 switch (type) {
25 return MTLVertexFormatFloat;
27 return MTLVertexFormatFloat2;
29 return MTLVertexFormatFloat3;
31 return MTLVertexFormatFloat4;
33 if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
34 return MTLVertexFormatHalf;
35 } else {
36 return MTLVertexFormatInvalid;
37 }
39 return MTLVertexFormatHalf2;
41 return MTLVertexFormatHalf4;
43 return MTLVertexFormatInt2;
45 return MTLVertexFormatInt3;
47 return MTLVertexFormatInt4;
49 if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
50 return MTLVertexFormatChar;
51 } else {
52 return MTLVertexFormatInvalid;
53 }
55 return MTLVertexFormatChar2;
57 return MTLVertexFormatChar4;
59 if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
60 return MTLVertexFormatUChar;
61 } else {
62 return MTLVertexFormatInvalid;
63 }
65 return MTLVertexFormatUChar2;
67 return MTLVertexFormatUChar4;
69 if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
70 return MTLVertexFormatUCharNormalized;
71 } else {
72 return MTLVertexFormatInvalid;
73 }
75 return MTLVertexFormatUChar4Normalized;
77 return MTLVertexFormatShort2;
79 return MTLVertexFormatShort4;
81 return MTLVertexFormatUShort2;
83 return MTLVertexFormatUShort2Normalized;
85 return MTLVertexFormatInt;
87 return MTLVertexFormatUInt;
89 if (@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)) {
90 return MTLVertexFormatUShortNormalized;
91 } else {
92 return MTLVertexFormatInvalid;
93 }
95 return MTLVertexFormatUShort4Normalized;
96 }
97 SK_ABORT("Unknown vertex attribute type");
98}
99
100MTLVertexDescriptor* create_vertex_descriptor(SkSpan<const Attribute> vertexAttrs,
101 SkSpan<const Attribute> instanceAttrs) {
102 auto vertexDescriptor = [[MTLVertexDescriptor alloc] init];
103 int attributeIndex = 0;
104
105 size_t vertexAttributeOffset = 0;
106 for (const auto& attribute : vertexAttrs) {
107 MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
108 MTLVertexFormat format = attribute_type_to_mtlformat(attribute.cpuType());
109 SkASSERT(MTLVertexFormatInvalid != format);
110 mtlAttribute.format = format;
111 mtlAttribute.offset = vertexAttributeOffset;
112 mtlAttribute.bufferIndex = MtlGraphicsPipeline::kVertexBufferIndex;
113
114 vertexAttributeOffset += attribute.sizeAlign4();
115 attributeIndex++;
116 }
117
118 if (vertexAttributeOffset) {
119 MTLVertexBufferLayoutDescriptor* vertexBufferLayout =
120 vertexDescriptor.layouts[MtlGraphicsPipeline::kVertexBufferIndex];
121 vertexBufferLayout.stepFunction = MTLVertexStepFunctionPerVertex;
122 vertexBufferLayout.stepRate = 1;
123 vertexBufferLayout.stride = vertexAttributeOffset;
124 }
125
126 size_t instanceAttributeOffset = 0;
127 for (const auto& attribute : instanceAttrs) {
128 MTLVertexAttributeDescriptor* mtlAttribute = vertexDescriptor.attributes[attributeIndex];
129 MTLVertexFormat format = attribute_type_to_mtlformat(attribute.cpuType());
130 SkASSERT(MTLVertexFormatInvalid != format);
131 mtlAttribute.format = format;
132 mtlAttribute.offset = instanceAttributeOffset;
133 mtlAttribute.bufferIndex = MtlGraphicsPipeline::kInstanceBufferIndex;
134
135 instanceAttributeOffset += attribute.sizeAlign4();
136 attributeIndex++;
137 }
138
139 if (instanceAttributeOffset) {
140 MTLVertexBufferLayoutDescriptor* instanceBufferLayout =
141 vertexDescriptor.layouts[MtlGraphicsPipeline::kInstanceBufferIndex];
142 instanceBufferLayout.stepFunction = MTLVertexStepFunctionPerInstance;
143 instanceBufferLayout.stepRate = 1;
144 instanceBufferLayout.stride = instanceAttributeOffset;
145 }
146 return vertexDescriptor;
147}
148
149// TODO: share this w/ Ganesh Metal backend?
150static MTLBlendFactor blend_coeff_to_mtl_blend(skgpu::BlendCoeff coeff) {
151 switch (coeff) {
153 return MTLBlendFactorZero;
155 return MTLBlendFactorOne;
157 return MTLBlendFactorSourceColor;
159 return MTLBlendFactorOneMinusSourceColor;
161 return MTLBlendFactorDestinationColor;
163 return MTLBlendFactorOneMinusDestinationColor;
165 return MTLBlendFactorSourceAlpha;
167 return MTLBlendFactorOneMinusSourceAlpha;
169 return MTLBlendFactorDestinationAlpha;
171 return MTLBlendFactorOneMinusDestinationAlpha;
173 return MTLBlendFactorBlendColor;
175 return MTLBlendFactorOneMinusBlendColor;
177 if (@available(macOS 10.12, iOS 11.0, tvOS 11.0, *)) {
178 return MTLBlendFactorSource1Color;
179 } else {
180 return MTLBlendFactorZero;
181 }
183 if (@available(macOS 10.12, iOS 11.0, tvOS 11.0, *)) {
184 return MTLBlendFactorOneMinusSource1Color;
185 } else {
186 return MTLBlendFactorZero;
187 }
189 if (@available(macOS 10.12, iOS 11.0, tvOS 11.0, *)) {
190 return MTLBlendFactorSource1Alpha;
191 } else {
192 return MTLBlendFactorZero;
193 }
195 if (@available(macOS 10.12, iOS 11.0, tvOS 11.0, *)) {
196 return MTLBlendFactorOneMinusSource1Alpha;
197 } else {
198 return MTLBlendFactorZero;
199 }
201 return MTLBlendFactorZero;
202 }
203
204 SK_ABORT("Unknown blend coefficient");
205}
206
207// TODO: share this w/ Ganesh Metal backend?
208static MTLBlendOperation blend_equation_to_mtl_blend_op(skgpu::BlendEquation equation) {
209 static const MTLBlendOperation gTable[] = {
210 MTLBlendOperationAdd, // skgpu::BlendEquation::kAdd
211 MTLBlendOperationSubtract, // skgpu::BlendEquation::kSubtract
212 MTLBlendOperationReverseSubtract, // skgpu::BlendEquation::kReverseSubtract
213 };
214 static_assert(std::size(gTable) == (int)skgpu::BlendEquation::kFirstAdvanced);
215 static_assert(0 == (int)skgpu::BlendEquation::kAdd);
216 static_assert(1 == (int)skgpu::BlendEquation::kSubtract);
217 static_assert(2 == (int)skgpu::BlendEquation::kReverseSubtract);
218
219 SkASSERT((unsigned)equation < skgpu::kBlendEquationCnt);
220 return gTable[(int)equation];
221}
222
223static MTLRenderPipelineColorAttachmentDescriptor* create_color_attachment(
224 MTLPixelFormat format,
225 const BlendInfo& blendInfo) {
226
227 skgpu::BlendEquation equation = blendInfo.fEquation;
228 skgpu::BlendCoeff srcCoeff = blendInfo.fSrcBlend;
229 skgpu::BlendCoeff dstCoeff = blendInfo.fDstBlend;
230 bool blendOn = !skgpu::BlendShouldDisable(equation, srcCoeff, dstCoeff);
231
232 // TODO: I *think* this gets cleaned up by the pipelineDescriptor?
233 auto mtlColorAttachment = [[MTLRenderPipelineColorAttachmentDescriptor alloc] init];
234
235 mtlColorAttachment.pixelFormat = format;
236
237 mtlColorAttachment.blendingEnabled = blendOn;
238
239 if (blendOn) {
240 mtlColorAttachment.sourceRGBBlendFactor = blend_coeff_to_mtl_blend(srcCoeff);
241 mtlColorAttachment.destinationRGBBlendFactor = blend_coeff_to_mtl_blend(dstCoeff);
242 mtlColorAttachment.rgbBlendOperation = blend_equation_to_mtl_blend_op(equation);
243 mtlColorAttachment.sourceAlphaBlendFactor = blend_coeff_to_mtl_blend(srcCoeff);
244 mtlColorAttachment.destinationAlphaBlendFactor = blend_coeff_to_mtl_blend(dstCoeff);
245 mtlColorAttachment.alphaBlendOperation = blend_equation_to_mtl_blend_op(equation);
246 }
247
248 mtlColorAttachment.writeMask = blendInfo.fWritesColor ? MTLColorWriteMaskAll
249 : MTLColorWriteMaskNone;
250
251 return mtlColorAttachment;
252}
253
254} // anonymous namespace
255
257 const std::string& label,
258 MSLFunction vertexMain,
259 SkSpan<const Attribute> vertexAttrs,
260 SkSpan<const Attribute> instanceAttrs,
261 MSLFunction fragmentMain,
262 sk_cfp<id<MTLDepthStencilState>> dss,
263 uint32_t stencilRefValue,
264 const BlendInfo& blendInfo,
265 const RenderPassDesc& renderPassDesc,
266 PipelineInfo* pipelineInfo) {
267 id<MTLLibrary> vsLibrary = std::get<0>(vertexMain);
268 id<MTLLibrary> fsLibrary = std::get<0>(fragmentMain);
269 if (!vsLibrary || !fsLibrary) {
270 return nullptr;
271 }
272
273 sk_cfp<MTLRenderPipelineDescriptor*> psoDescriptor([[MTLRenderPipelineDescriptor alloc] init]);
274
275 NSString* labelName = [NSString stringWithUTF8String: label.c_str()];
276 NSString* vsFuncName = [NSString stringWithUTF8String: std::get<1>(vertexMain).c_str()];
277 NSString* fsFuncName = [NSString stringWithUTF8String: std::get<1>(fragmentMain).c_str()];
278
279 (*psoDescriptor).label = labelName;
280 (*psoDescriptor).vertexFunction = [vsLibrary newFunctionWithName: vsFuncName];
281 (*psoDescriptor).fragmentFunction = [fsLibrary newFunctionWithName: fsFuncName];
282
283 // TODO: I *think* this gets cleaned up by the pipelineDescriptor?
284 (*psoDescriptor).vertexDescriptor = create_vertex_descriptor(vertexAttrs, instanceAttrs);
285
286 const MtlTextureSpec& mtlColorSpec =
287 renderPassDesc.fColorAttachment.fTextureInfo.mtlTextureSpec();
288 auto mtlColorAttachment = create_color_attachment((MTLPixelFormat)mtlColorSpec.fFormat,
289 blendInfo);
290 (*psoDescriptor).colorAttachments[0] = mtlColorAttachment;
291
292 (*psoDescriptor).rasterSampleCount =
294
295 const MtlTextureSpec& mtlDSSpec =
296 renderPassDesc.fDepthStencilAttachment.fTextureInfo.mtlTextureSpec();
297 MTLPixelFormat depthStencilFormat = (MTLPixelFormat)mtlDSSpec.fFormat;
298 if (MtlFormatIsStencil(depthStencilFormat)) {
299 (*psoDescriptor).stencilAttachmentPixelFormat = depthStencilFormat;
300 } else {
301 (*psoDescriptor).stencilAttachmentPixelFormat = MTLPixelFormatInvalid;
302 }
303 if (MtlFormatIsDepth(depthStencilFormat)) {
304 (*psoDescriptor).depthAttachmentPixelFormat = depthStencilFormat;
305 } else {
306 (*psoDescriptor).depthAttachmentPixelFormat = MTLPixelFormatInvalid;
307 }
308
309 NSError* error;
310 sk_cfp<id<MTLRenderPipelineState>> pso(
311 [sharedContext->device() newRenderPipelineStateWithDescriptor:psoDescriptor.get()
312 error:&error]);
313 if (!pso) {
314 SKGPU_LOG_E("Render pipeline creation failure:\n%s", error.debugDescription.UTF8String);
315 return nullptr;
316 }
317
319 pipelineInfo,
320 std::move(pso),
321 std::move(dss),
322 stencilRefValue));
323}
324
325MtlGraphicsPipeline::MtlGraphicsPipeline(const skgpu::graphite::SharedContext* sharedContext,
326 PipelineInfo* pipelineInfo,
327 sk_cfp<id<MTLRenderPipelineState>> pso,
328 sk_cfp<id<MTLDepthStencilState>> dss,
329 uint32_t refValue)
330 : GraphicsPipeline(sharedContext, pipelineInfo)
331 , fPipelineState(std::move(pso))
332 , fDepthStencilState(std::move(dss))
333 , fStencilReferenceValue(refValue) {}
334
336 fPipelineState.reset();
337}
338
339} // namespace skgpu::graphite
static MTLBlendOperation blend_equation_to_mtl_blend_op(skgpu::BlendEquation equation)
static MTLRenderPipelineColorAttachmentDescriptor * create_color_attachment(MTLPixelFormat format, const GrPipeline &pipeline, SkBinaryWriteBuffer *writer)
static MTLBlendFactor blend_coeff_to_mtl_blend(skgpu::BlendCoeff coeff)
static MTLVertexFormat attribute_type_to_mtlformat(GrVertexAttribType type)
static MTLVertexDescriptor * create_vertex_descriptor(const GrGeometryProcessor &geomProc, SkBinaryWriteBuffer *writer)
#define SKGPU_LOG_E(fmt,...)
Definition Log.h:38
#define SK_ABORT(message,...)
Definition SkAssert.h:70
#define SkASSERT(cond)
Definition SkAssert.h:116
Type::kYUV Type::kRGBA() int(0.7 *637)
std::pair< id< MTLLibrary >, std::string > MSLFunction
static constexpr unsigned int kVertexBufferIndex
static constexpr unsigned int kInstanceBufferIndex
static sk_sp< MtlGraphicsPipeline > Make(const MtlSharedContext *, const std::string &label, MSLFunction vertexMain, SkSpan< const Attribute > vertexAttrs, SkSpan< const Attribute > instanceAttrs, MSLFunction fragmentMain, sk_cfp< id< MTLDepthStencilState > >, uint32_t stencilRefValue, const BlendInfo &blendInfo, const RenderPassDesc &, PipelineInfo *pipelineInfo)
const SharedContext * sharedContext() const
Definition Resource.h:187
uint32_t numSamples() const
Definition TextureInfo.h:78
const uint8_t uint32_t uint32_t GError ** error
uint32_t uint32_t * format
static constexpr bool BlendShouldDisable(BlendEquation equation, BlendCoeff srcCoeff, BlendCoeff dstCoeff)
Definition Blend.h:145
static const int kBlendEquationCnt
Definition Blend.h:55
BlendEquation
Definition Blend.h:26
BlendCoeff
Definition Blend.h:60
bool MtlFormatIsStencil(MTLPixelFormat format)
Definition MtlUtils.mm:39
bool MtlFormatIsDepth(MTLPixelFormat format)
Definition MtlUtils.mm:29
Definition ref_ptr.h:256
init(device_serial, adb_binary)
Definition _adb_path.py:12