blob: 93ba09402471c408a88581de8634a988ad21fe4b [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
Jim Van Verth3d482992019-02-07 10:48:05 -0500307uint32_t buffer_size(uint32_t offset, uint32_t maxAlignment) {
308 // Metal expects the buffer to be padded at the end according to the alignment
309 // of the largest element in the buffer.
310 uint32_t offsetDiff = offset & maxAlignment;
311 if (offsetDiff != 0) {
312 offsetDiff = maxAlignment - offsetDiff + 1;
313 }
314 return offset + offsetDiff;
315}
316
Timothy Liang7ac582e2018-08-06 09:47:23 -0400317GrMtlPipelineState* GrMtlPipelineStateBuilder::finalize(const GrPrimitiveProcessor& primProc,
318 const GrPipeline& pipeline,
319 GrProgramDesc* desc) {
320 auto pipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
321
322 fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
323 fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
324 fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
325 fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
326
327 this->finalizeShaders();
328
329 SkSL::Program::Settings settings;
330 settings.fCaps = this->caps()->shaderCaps();
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500331 settings.fFlipY = this->origin() != kTopLeft_GrSurfaceOrigin;
Robert Phillips9da87e02019-02-04 13:26:26 -0500332 settings.fSharpenTextures = fGpu->getContext()->priv().options().fSharpenMipmappedTextures;
Timothy Liang7ac582e2018-08-06 09:47:23 -0400333 SkASSERT(!this->fragColorIsInOut());
334
335 id<MTLLibrary> vertexLibrary = nil;
336 id<MTLLibrary> fragmentLibrary = nil;
337 vertexLibrary = this->createMtlShaderLibrary(fVS,
338 SkSL::Program::kVertex_Kind,
339 settings,
340 desc);
341 fragmentLibrary = this->createMtlShaderLibrary(fFS,
342 SkSL::Program::kFragment_Kind,
343 settings,
344 desc);
345 SkASSERT(!this->primitiveProcessor().willUseGeoShader());
346
347 SkASSERT(vertexLibrary);
348 SkASSERT(fragmentLibrary);
349
350 id<MTLFunction> vertexFunction = [vertexLibrary newFunctionWithName: @"vertexMain"];
351 id<MTLFunction> fragmentFunction = [fragmentLibrary newFunctionWithName: @"fragmentMain"];
352
353 pipelineDescriptor.vertexFunction = vertexFunction;
354 pipelineDescriptor.fragmentFunction = fragmentFunction;
355 pipelineDescriptor.vertexDescriptor = create_vertex_descriptor(primProc);
Robert Phillipsd0fe8752019-01-31 14:13:59 -0500356 pipelineDescriptor.colorAttachments[0] = create_color_attachment(this->config(), pipeline);
Timothy Liang7ac582e2018-08-06 09:47:23 -0400357
358 SkASSERT(pipelineDescriptor.vertexFunction);
359 SkASSERT(pipelineDescriptor.fragmentFunction);
360 SkASSERT(pipelineDescriptor.vertexDescriptor);
361 SkASSERT(pipelineDescriptor.colorAttachments[0]);
362
363 NSError* error = nil;
364 id<MTLRenderPipelineState> pipelineState =
365 [fGpu->device() newRenderPipelineStateWithDescriptor: pipelineDescriptor
366 error: &error];
367 if (error) {
368 SkDebugf("Error creating pipeline: %s\n",
369 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]);
Timothy Liang6ed63962018-08-10 09:49:44 -0400370 return nullptr;
Timothy Liang7ac582e2018-08-06 09:47:23 -0400371 }
Jim Van Verth3d482992019-02-07 10:48:05 -0500372 uint32_t geomBufferSize = buffer_size(fUniformHandler.fCurrentGeometryUBOOffset,
373 fUniformHandler.fCurrentGeometryUBOMaxAlignment);
374 uint32_t fragBufferSize = buffer_size(fUniformHandler.fCurrentFragmentUBOOffset,
375 fUniformHandler.fCurrentFragmentUBOMaxAlignment);
Timothy Liang057c3902018-08-08 10:48:45 -0400376 return new GrMtlPipelineState(fGpu,
377 pipelineState,
378 pipelineDescriptor.colorAttachments[0].pixelFormat,
Timothy Liang6ed63962018-08-10 09:49:44 -0400379 fUniformHandles,
380 fUniformHandler.fUniforms,
Brian Salomon12d22642019-01-29 14:38:50 -0500381 GrMtlBuffer::Make(fGpu,
Jim Van Verth3d482992019-02-07 10:48:05 -0500382 geomBufferSize,
Brian Salomonae64c192019-02-05 09:41:37 -0500383 GrGpuBufferType::kVertex,
Brian Salomon12d22642019-01-29 14:38:50 -0500384 kStatic_GrAccessPattern),
385 GrMtlBuffer::Make(fGpu,
Jim Van Verth3d482992019-02-07 10:48:05 -0500386 fragBufferSize,
Brian Salomonae64c192019-02-05 09:41:37 -0500387 GrGpuBufferType::kVertex,
Brian Salomon12d22642019-01-29 14:38:50 -0500388 kStatic_GrAccessPattern),
Timothy Liang6ed63962018-08-10 09:49:44 -0400389 (uint32_t)fUniformHandler.numSamplers(),
390 std::move(fGeometryProcessor),
391 std::move(fXferProcessor),
392 std::move(fFragmentProcessors),
393 fFragmentProcessorCnt);
Timothy Liang7ac582e2018-08-06 09:47:23 -0400394}