1 /*
2 * Copyright 2019 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 "src/gpu/dawn/GrDawnProgramBuilder.h"
9
10 #include "src/gpu/GrRenderTarget.h"
11 #include "src/gpu/GrShaderUtils.h"
12 #include "src/gpu/GrStencilSettings.h"
13 #include "src/gpu/dawn/GrDawnGpu.h"
14 #include "src/gpu/dawn/GrDawnTexture.h"
15 #include "src/sksl/SkSLCompiler.h"
16
sksl_to_spirv(const GrDawnGpu * gpu,const char * shaderString,SkSL::Program::Kind kind,bool flipY,SkSL::Program::Inputs * inputs)17 static SkSL::String sksl_to_spirv(const GrDawnGpu* gpu, const char* shaderString,
18 SkSL::Program::Kind kind, bool flipY,
19 SkSL::Program::Inputs* inputs) {
20 SkSL::Program::Settings settings;
21 settings.fCaps = gpu->caps()->shaderCaps();
22 settings.fFlipY = flipY;
23 std::unique_ptr<SkSL::Program> program = gpu->shaderCompiler()->convertProgram(
24 kind,
25 shaderString,
26 settings);
27 if (!program) {
28 SkDebugf("SkSL error:\n%s\n", gpu->shaderCompiler()->errorText().c_str());
29 SkASSERT(false);
30 return "";
31 }
32 *inputs = program->fInputs;
33 SkSL::String code;
34 if (!gpu->shaderCompiler()->toSPIRV(*program, &code)) {
35 return "";
36 }
37 return code;
38 }
39
to_dawn_blend_factor(GrBlendCoeff coeff)40 static dawn::BlendFactor to_dawn_blend_factor(GrBlendCoeff coeff) {
41 switch (coeff) {
42 case kZero_GrBlendCoeff:
43 return dawn::BlendFactor::Zero;
44 case kOne_GrBlendCoeff:
45 return dawn::BlendFactor::One;
46 case kSC_GrBlendCoeff:
47 return dawn::BlendFactor::SrcColor;
48 case kISC_GrBlendCoeff:
49 return dawn::BlendFactor::OneMinusSrcColor;
50 case kDC_GrBlendCoeff:
51 return dawn::BlendFactor::DstColor;
52 case kIDC_GrBlendCoeff:
53 return dawn::BlendFactor::OneMinusDstColor;
54 case kSA_GrBlendCoeff:
55 return dawn::BlendFactor::SrcAlpha;
56 case kISA_GrBlendCoeff:
57 return dawn::BlendFactor::OneMinusSrcAlpha;
58 case kDA_GrBlendCoeff:
59 return dawn::BlendFactor::DstAlpha;
60 case kIDA_GrBlendCoeff:
61 return dawn::BlendFactor::OneMinusDstAlpha;
62 case kConstC_GrBlendCoeff:
63 return dawn::BlendFactor::BlendColor;
64 case kIConstC_GrBlendCoeff:
65 return dawn::BlendFactor::OneMinusBlendColor;
66 case kConstA_GrBlendCoeff:
67 case kIConstA_GrBlendCoeff:
68 case kS2C_GrBlendCoeff:
69 case kIS2C_GrBlendCoeff:
70 case kS2A_GrBlendCoeff:
71 case kIS2A_GrBlendCoeff:
72 default:
73 SkASSERT(!"unsupported blend coefficient");
74 return dawn::BlendFactor::One;
75 }
76 }
77
to_dawn_blend_factor_for_alpha(GrBlendCoeff coeff)78 static dawn::BlendFactor to_dawn_blend_factor_for_alpha(GrBlendCoeff coeff) {
79 switch (coeff) {
80 // Force all srcColor used in alpha slot to alpha version.
81 case kSC_GrBlendCoeff:
82 return dawn::BlendFactor::SrcAlpha;
83 case kISC_GrBlendCoeff:
84 return dawn::BlendFactor::OneMinusSrcAlpha;
85 case kDC_GrBlendCoeff:
86 return dawn::BlendFactor::DstAlpha;
87 case kIDC_GrBlendCoeff:
88 return dawn::BlendFactor::OneMinusDstAlpha;
89 default:
90 return to_dawn_blend_factor(coeff);
91 }
92 }
93
to_dawn_blend_operation(GrBlendEquation equation)94 static dawn::BlendOperation to_dawn_blend_operation(GrBlendEquation equation) {
95 switch (equation) {
96 case kAdd_GrBlendEquation:
97 return dawn::BlendOperation::Add;
98 case kSubtract_GrBlendEquation:
99 return dawn::BlendOperation::Subtract;
100 case kReverseSubtract_GrBlendEquation:
101 return dawn::BlendOperation::ReverseSubtract;
102 default:
103 SkASSERT(!"unsupported blend equation");
104 return dawn::BlendOperation::Add;
105 }
106 }
107
to_dawn_compare_function(GrStencilTest test)108 static dawn::CompareFunction to_dawn_compare_function(GrStencilTest test) {
109 switch (test) {
110 case GrStencilTest::kAlways:
111 return dawn::CompareFunction::Always;
112 case GrStencilTest::kNever:
113 return dawn::CompareFunction::Never;
114 case GrStencilTest::kGreater:
115 return dawn::CompareFunction::Greater;
116 case GrStencilTest::kGEqual:
117 return dawn::CompareFunction::GreaterEqual;
118 case GrStencilTest::kLess:
119 return dawn::CompareFunction::Less;
120 case GrStencilTest::kLEqual:
121 return dawn::CompareFunction::LessEqual;
122 case GrStencilTest::kEqual:
123 return dawn::CompareFunction::Equal;
124 case GrStencilTest::kNotEqual:
125 return dawn::CompareFunction::NotEqual;
126 default:
127 SkASSERT(!"unsupported stencil test");
128 return dawn::CompareFunction::Always;
129 }
130 }
131
to_dawn_stencil_operation(GrStencilOp op)132 static dawn::StencilOperation to_dawn_stencil_operation(GrStencilOp op) {
133 switch (op) {
134 case GrStencilOp::kKeep:
135 return dawn::StencilOperation::Keep;
136 case GrStencilOp::kZero:
137 return dawn::StencilOperation::Zero;
138 case GrStencilOp::kReplace:
139 return dawn::StencilOperation::Replace;
140 case GrStencilOp::kInvert:
141 return dawn::StencilOperation::Invert;
142 case GrStencilOp::kIncClamp:
143 return dawn::StencilOperation::IncrementClamp;
144 case GrStencilOp::kDecClamp:
145 return dawn::StencilOperation::DecrementClamp;
146 case GrStencilOp::kIncWrap:
147 return dawn::StencilOperation::IncrementWrap;
148 case GrStencilOp::kDecWrap:
149 return dawn::StencilOperation::DecrementWrap;
150 default:
151 SkASSERT(!"unsupported stencil function");
152 return dawn::StencilOperation::Keep;
153 }
154 }
155
to_dawn_primitive_topology(GrPrimitiveType primitiveType)156 static dawn::PrimitiveTopology to_dawn_primitive_topology(GrPrimitiveType primitiveType) {
157 switch (primitiveType) {
158 case GrPrimitiveType::kTriangles:
159 return dawn::PrimitiveTopology::TriangleList;
160 case GrPrimitiveType::kTriangleStrip:
161 return dawn::PrimitiveTopology::TriangleStrip;
162 case GrPrimitiveType::kPoints:
163 return dawn::PrimitiveTopology::PointList;
164 case GrPrimitiveType::kLines:
165 return dawn::PrimitiveTopology::LineList;
166 case GrPrimitiveType::kLineStrip:
167 return dawn::PrimitiveTopology::LineStrip;
168 case GrPrimitiveType::kPath:
169 default:
170 SkASSERT(!"unsupported primitive topology");
171 return dawn::PrimitiveTopology::TriangleList;
172 }
173 }
174
to_dawn_vertex_format(GrVertexAttribType type)175 static dawn::VertexFormat to_dawn_vertex_format(GrVertexAttribType type) {
176 switch (type) {
177 case kFloat_GrVertexAttribType:
178 case kHalf_GrVertexAttribType:
179 return dawn::VertexFormat::Float;
180 case kFloat2_GrVertexAttribType:
181 case kHalf2_GrVertexAttribType:
182 return dawn::VertexFormat::Float2;
183 case kFloat3_GrVertexAttribType:
184 case kHalf3_GrVertexAttribType:
185 return dawn::VertexFormat::Float3;
186 case kFloat4_GrVertexAttribType:
187 case kHalf4_GrVertexAttribType:
188 return dawn::VertexFormat::Float4;
189 case kUShort2_GrVertexAttribType:
190 return dawn::VertexFormat::UShort2;
191 case kInt_GrVertexAttribType:
192 return dawn::VertexFormat::Int;
193 case kUByte4_norm_GrVertexAttribType:
194 return dawn::VertexFormat::UChar4Norm;
195 default:
196 SkASSERT(!"unsupported vertex format");
197 return dawn::VertexFormat::Float4;
198 }
199 }
200
create_color_state(const GrDawnGpu * gpu,const GrPipeline & pipeline,dawn::TextureFormat colorFormat)201 static dawn::ColorStateDescriptor create_color_state(const GrDawnGpu* gpu,
202 const GrPipeline& pipeline,
203 dawn::TextureFormat colorFormat) {
204 GrXferProcessor::BlendInfo blendInfo = pipeline.getXferProcessor().getBlendInfo();
205 GrBlendEquation equation = blendInfo.fEquation;
206 GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
207 GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
208
209 dawn::BlendFactor srcFactor = to_dawn_blend_factor(srcCoeff);
210 dawn::BlendFactor dstFactor = to_dawn_blend_factor(dstCoeff);
211 dawn::BlendFactor srcFactorAlpha = to_dawn_blend_factor_for_alpha(srcCoeff);
212 dawn::BlendFactor dstFactorAlpha = to_dawn_blend_factor_for_alpha(dstCoeff);
213 dawn::BlendOperation operation = to_dawn_blend_operation(equation);
214 auto mask = blendInfo.fWriteColor ? dawn::ColorWriteMask::All : dawn::ColorWriteMask::None;
215
216 dawn::BlendDescriptor colorDesc = {operation, srcFactor, dstFactor};
217 dawn::BlendDescriptor alphaDesc = {operation, srcFactorAlpha, dstFactorAlpha};
218
219 dawn::ColorStateDescriptor descriptor;
220 descriptor.format = colorFormat;
221 descriptor.alphaBlend = alphaDesc;
222 descriptor.colorBlend = colorDesc;
223 descriptor.nextInChain = nullptr;
224 descriptor.writeMask = mask;
225
226 return descriptor;
227 }
228
to_stencil_state_face(const GrStencilSettings::Face & face)229 static dawn::StencilStateFaceDescriptor to_stencil_state_face(const GrStencilSettings::Face& face) {
230 dawn::StencilStateFaceDescriptor desc;
231 desc.compare = to_dawn_compare_function(face.fTest);
232 desc.failOp = desc.depthFailOp = to_dawn_stencil_operation(face.fFailOp);
233 desc.passOp = to_dawn_stencil_operation(face.fPassOp);
234 return desc;
235 }
236
create_depth_stencil_state(const GrStencilSettings & stencilSettings,dawn::TextureFormat depthStencilFormat,GrSurfaceOrigin origin)237 static dawn::DepthStencilStateDescriptor create_depth_stencil_state(
238 const GrStencilSettings& stencilSettings,
239 dawn::TextureFormat depthStencilFormat,
240 GrSurfaceOrigin origin) {
241 dawn::DepthStencilStateDescriptor state;
242 state.format = depthStencilFormat;
243 if (!stencilSettings.isDisabled()) {
244 const GrStencilSettings::Face& front = stencilSettings.front(origin);
245 state.stencilReadMask = front.fTestMask;
246 state.stencilWriteMask = front.fWriteMask;
247 state.stencilFront = to_stencil_state_face(stencilSettings.front(origin));
248 if (stencilSettings.isTwoSided()) {
249 state.stencilBack = to_stencil_state_face(stencilSettings.back(origin));
250 } else {
251 state.stencilBack = state.stencilFront;
252 }
253 }
254 return state;
255 }
256
make_bind_group_binding(uint32_t binding,const dawn::Buffer & buffer,uint32_t offset,uint32_t size,const dawn::Sampler & sampler,const dawn::TextureView & textureView)257 static dawn::BindGroupBinding make_bind_group_binding(uint32_t binding, const dawn::Buffer& buffer,
258 uint32_t offset, uint32_t size, const
259 dawn::Sampler& sampler,
260 const dawn::TextureView& textureView) {
261 dawn::BindGroupBinding result;
262 result.binding = binding;
263 result.buffer = buffer;
264 result.offset = offset;
265 result.size = size;
266 result.sampler = sampler;
267 result.textureView = textureView;
268 return result;
269 }
270
make_bind_group_binding(uint32_t binding,const dawn::Buffer & buffer,uint32_t offset,uint32_t size)271 static dawn::BindGroupBinding make_bind_group_binding(uint32_t binding, const dawn::Buffer& buffer,
272 uint32_t offset, uint32_t size) {
273 return make_bind_group_binding(binding, buffer, offset, size, nullptr, nullptr);
274 }
275
make_bind_group_binding(uint32_t binding,const dawn::Sampler & sampler)276 static dawn::BindGroupBinding make_bind_group_binding(uint32_t binding,
277 const dawn::Sampler& sampler) {
278 return make_bind_group_binding(binding, nullptr, 0, 0, sampler, nullptr);
279 }
280
make_bind_group_binding(uint32_t binding,const dawn::TextureView & textureView)281 static dawn::BindGroupBinding make_bind_group_binding(uint32_t binding,
282 const dawn::TextureView& textureView) {
283 return make_bind_group_binding(binding, nullptr, 0, 0, nullptr, textureView);
284 }
285
Build(GrDawnGpu * gpu,GrRenderTarget * renderTarget,const GrProgramInfo & programInfo,GrPrimitiveType primitiveType,dawn::TextureFormat colorFormat,bool hasDepthStencil,dawn::TextureFormat depthStencilFormat,GrProgramDesc * desc)286 sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu,
287 GrRenderTarget* renderTarget,
288 const GrProgramInfo& programInfo,
289 GrPrimitiveType primitiveType,
290 dawn::TextureFormat colorFormat,
291 bool hasDepthStencil,
292 dawn::TextureFormat depthStencilFormat,
293 GrProgramDesc* desc) {
294 GrDawnProgramBuilder builder(gpu, renderTarget, programInfo, desc);
295 if (!builder.emitAndInstallProcs()) {
296 return nullptr;
297 }
298
299 builder.fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
300 builder.fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
301 builder.fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
302 builder.fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
303
304 builder.finalizeShaders();
305
306 SkSL::Program::Inputs vertInputs, fragInputs;
307 GrDawnUniformHandler::UniformInfoArray& uniforms = builder.fUniformHandler.fUniforms;
308 uint32_t geometryUniformSize = builder.fUniformHandler.fCurrentGeometryUBOOffset;
309 uint32_t fragmentUniformSize = builder.fUniformHandler.fCurrentFragmentUBOOffset;
310 sk_sp<GrDawnProgram> result(
311 new GrDawnProgram(uniforms, geometryUniformSize, fragmentUniformSize));
312 bool flipY = programInfo.origin() != kTopLeft_GrSurfaceOrigin;
313 auto vsModule = builder.createShaderModule(builder.fVS, SkSL::Program::kVertex_Kind, flipY,
314 &vertInputs);
315 auto fsModule = builder.createShaderModule(builder.fFS, SkSL::Program::kFragment_Kind, flipY,
316 &fragInputs);
317 result->fGeometryProcessor = std::move(builder.fGeometryProcessor);
318 result->fXferProcessor = std::move(builder.fXferProcessor);
319 result->fFragmentProcessors = std::move(builder.fFragmentProcessors);
320 result->fFragmentProcessorCnt = builder.fFragmentProcessorCnt;
321 std::vector<dawn::BindGroupLayoutBinding> layoutBindings;
322 if (0 != geometryUniformSize) {
323 layoutBindings.push_back({ GrDawnUniformHandler::kGeometryBinding,
324 dawn::ShaderStage::Vertex,
325 dawn::BindingType::UniformBuffer});
326 }
327 if (0 != fragmentUniformSize) {
328 layoutBindings.push_back({ GrDawnUniformHandler::kFragBinding,
329 dawn::ShaderStage::Fragment,
330 dawn::BindingType::UniformBuffer});
331 }
332 uint32_t binding = GrDawnUniformHandler::kSamplerBindingBase;
333 for (int i = 0; i < builder.fUniformHandler.fSamplers.count(); ++i) {
334 layoutBindings.push_back({ binding++, dawn::ShaderStage::Fragment,
335 dawn::BindingType::Sampler});
336 layoutBindings.push_back({ binding++, dawn::ShaderStage::Fragment,
337 dawn::BindingType::SampledTexture});
338 }
339 dawn::BindGroupLayoutDescriptor bindGroupLayoutDesc;
340 bindGroupLayoutDesc.bindingCount = layoutBindings.size();
341 bindGroupLayoutDesc.bindings = layoutBindings.data();
342 result->fBindGroupLayout = gpu->device().CreateBindGroupLayout(&bindGroupLayoutDesc);
343 dawn::PipelineLayoutDescriptor pipelineLayoutDesc;
344 pipelineLayoutDesc.bindGroupLayoutCount = 1;
345 pipelineLayoutDesc.bindGroupLayouts = &result->fBindGroupLayout;
346 auto pipelineLayout = gpu->device().CreatePipelineLayout(&pipelineLayoutDesc);
347 result->fBuiltinUniformHandles = builder.fUniformHandles;
348 const GrPipeline& pipeline = programInfo.pipeline();
349 auto colorState = create_color_state(gpu, pipeline, colorFormat);
350 dawn::DepthStencilStateDescriptor depthStencilState;
351 GrStencilSettings stencil;
352 if (pipeline.isStencilEnabled()) {
353 int numStencilBits = renderTarget->renderTargetPriv().numStencilBits();
354 stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(), numStencilBits);
355 }
356 depthStencilState = create_depth_stencil_state(stencil, depthStencilFormat,
357 programInfo.origin());
358
359 std::vector<dawn::VertexBufferDescriptor> inputs;
360
361 std::vector<dawn::VertexAttributeDescriptor> vertexAttributes;
362 const GrPrimitiveProcessor& primProc = programInfo.primProc();
363 if (primProc.numVertexAttributes() > 0) {
364 size_t offset = 0;
365 int i = 0;
366 for (const auto& attrib : primProc.vertexAttributes()) {
367 dawn::VertexAttributeDescriptor attribute;
368 attribute.shaderLocation = i;
369 attribute.offset = offset;
370 attribute.format = to_dawn_vertex_format(attrib.cpuType());
371 vertexAttributes.push_back(attribute);
372 offset += attrib.sizeAlign4();
373 i++;
374 }
375 dawn::VertexBufferDescriptor input;
376 input.stride = offset;
377 input.stepMode = dawn::InputStepMode::Vertex;
378 input.attributeCount = vertexAttributes.size();
379 input.attributes = &vertexAttributes.front();
380 inputs.push_back(input);
381 }
382 std::vector<dawn::VertexAttributeDescriptor> instanceAttributes;
383 if (primProc.numInstanceAttributes() > 0) {
384 size_t offset = 0;
385 int i = 0;
386 for (const auto& attrib : primProc.instanceAttributes()) {
387 dawn::VertexAttributeDescriptor attribute;
388 attribute.shaderLocation = i;
389 attribute.offset = offset;
390 attribute.format = to_dawn_vertex_format(attrib.cpuType());
391 instanceAttributes.push_back(attribute);
392 offset += attrib.sizeAlign4();
393 i++;
394 }
395 dawn::VertexBufferDescriptor input;
396 input.stride = offset;
397 input.stepMode = dawn::InputStepMode::Instance;
398 input.attributeCount = instanceAttributes.size();
399 input.attributes = &instanceAttributes.front();
400 inputs.push_back(input);
401 }
402 dawn::VertexInputDescriptor vertexInput;
403 vertexInput.indexFormat = dawn::IndexFormat::Uint16;
404 vertexInput.bufferCount = inputs.size();
405 vertexInput.buffers = &inputs.front();
406
407 dawn::ProgrammableStageDescriptor vsDesc;
408 vsDesc.module = vsModule;
409 vsDesc.entryPoint = "main";
410
411 dawn::ProgrammableStageDescriptor fsDesc;
412 fsDesc.module = fsModule;
413 fsDesc.entryPoint = "main";
414
415 dawn::RenderPipelineDescriptor rpDesc;
416 rpDesc.layout = pipelineLayout;
417 rpDesc.vertexStage = vsDesc;
418 rpDesc.fragmentStage = &fsDesc;
419 rpDesc.vertexInput = &vertexInput;
420 rpDesc.primitiveTopology = to_dawn_primitive_topology(primitiveType);
421 if (hasDepthStencil) {
422 rpDesc.depthStencilState = &depthStencilState;
423 }
424 rpDesc.colorStateCount = 1;
425 rpDesc.colorStates = &colorState;
426 result->fRenderPipeline = gpu->device().CreateRenderPipeline(&rpDesc);
427 return result;
428 }
429
GrDawnProgramBuilder(GrDawnGpu * gpu,GrRenderTarget * renderTarget,const GrProgramInfo & programInfo,GrProgramDesc * desc)430 GrDawnProgramBuilder::GrDawnProgramBuilder(GrDawnGpu* gpu,
431 GrRenderTarget* renderTarget,
432 const GrProgramInfo& programInfo,
433 GrProgramDesc* desc)
434 : INHERITED(renderTarget, programInfo, desc)
435 , fGpu(gpu)
436 , fVaryingHandler(this)
437 , fUniformHandler(this) {
438 }
439
createShaderModule(const GrGLSLShaderBuilder & builder,SkSL::Program::Kind kind,bool flipY,SkSL::Program::Inputs * inputs)440 dawn::ShaderModule GrDawnProgramBuilder::createShaderModule(const GrGLSLShaderBuilder& builder,
441 SkSL::Program::Kind kind,
442 bool flipY,
443 SkSL::Program::Inputs* inputs) {
444 dawn::Device device = fGpu->device();
445 SkString source(builder.fCompilerString.c_str());
446
447 #if 0
448 SkSL::String sksl = GrShaderUtils::PrettyPrint(builder.fCompilerString);
449 printf("converting program:\n%s\n", sksl.c_str());
450 #endif
451
452 SkSL::String spirvSource = sksl_to_spirv(fGpu, source.c_str(), kind, flipY, inputs);
453
454 dawn::ShaderModuleDescriptor desc;
455 desc.codeSize = spirvSource.size() / 4;
456 desc.code = reinterpret_cast<const uint32_t*>(spirvSource.c_str());
457
458 return device.CreateShaderModule(&desc);
459 };
460
caps() const461 const GrCaps* GrDawnProgramBuilder::caps() const {
462 return fGpu->caps();
463 }
464
setRenderTargetState(const GrRenderTarget * rt,GrSurfaceOrigin origin)465 void GrDawnProgram::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin) {
466 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
467 if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
468 fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
469 fDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height()));
470 }
471
472 // set RT adjustment
473 SkISize size;
474 size.set(rt->width(), rt->height());
475 SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
476 if (fRenderTargetState.fRenderTargetOrigin != origin ||
477 fRenderTargetState.fRenderTargetSize != size) {
478 fRenderTargetState.fRenderTargetSize = size;
479 fRenderTargetState.fRenderTargetOrigin = origin;
480
481 float rtAdjustmentVec[4];
482 fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
483 fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
484 }
485 }
486
setTexture(GrDawnGpu * gpu,const GrSamplerState & state,GrTexture * texture,std::vector<dawn::BindGroupBinding> * bindings,int * binding)487 static void setTexture(GrDawnGpu* gpu, const GrSamplerState& state, GrTexture* texture,
488 std::vector<dawn::BindGroupBinding> *bindings, int* binding) {
489 // FIXME: could probably cache samplers in GrDawnProgram
490 dawn::Sampler sampler = gpu->getOrCreateSampler(state);
491 bindings->push_back(make_bind_group_binding((*binding)++, sampler));
492 GrDawnTexture* tex = static_cast<GrDawnTexture*>(texture);
493 dawn::TextureView textureView = tex->textureView();
494 bindings->push_back(make_bind_group_binding((*binding)++, textureView));
495 }
496
setData(GrDawnGpu * gpu,const GrRenderTarget * renderTarget,const GrProgramInfo & programInfo)497 dawn::BindGroup GrDawnProgram::setData(GrDawnGpu* gpu, const GrRenderTarget* renderTarget,
498 const GrProgramInfo& programInfo) {
499 std::vector<dawn::BindGroupBinding> bindings;
500 GrDawnRingBuffer::Slice geom, frag;
501 uint32_t geometryUniformSize = fDataManager.geometryUniformSize();
502 uint32_t fragmentUniformSize = fDataManager.fragmentUniformSize();
503 if (0 != geometryUniformSize) {
504 geom = gpu->allocateUniformRingBufferSlice(geometryUniformSize);
505 bindings.push_back(make_bind_group_binding(GrDawnUniformHandler::kGeometryBinding,
506 geom.fBuffer, geom.fOffset,
507 geometryUniformSize));
508 }
509 if (0 != fragmentUniformSize) {
510 frag = gpu->allocateUniformRingBufferSlice(fragmentUniformSize);
511 bindings.push_back(make_bind_group_binding(GrDawnUniformHandler::kFragBinding,
512 frag.fBuffer, frag.fOffset,
513 fragmentUniformSize));
514 }
515 this->setRenderTargetState(renderTarget, programInfo.origin());
516 const GrPipeline& pipeline = programInfo.pipeline();
517 const GrPrimitiveProcessor& primProc = programInfo.primProc();
518 fGeometryProcessor->setData(fDataManager, primProc,
519 GrFragmentProcessor::CoordTransformIter(pipeline));
520 int binding = GrDawnUniformHandler::kSamplerBindingBase;
521 auto primProcTextures = programInfo.hasFixedPrimProcTextures() ?
522 programInfo.fixedPrimProcTextures() : nullptr;
523
524 for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
525 auto& sampler = primProc.textureSampler(i);
526 setTexture(gpu, sampler.samplerState(), primProcTextures[i]->peekTexture(), &bindings,
527 &binding);
528 }
529 GrFragmentProcessor::Iter iter(pipeline);
530 GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
531 const GrFragmentProcessor* fp = iter.next();
532 GrGLSLFragmentProcessor* glslFP = glslIter.next();
533 while (fp && glslFP) {
534 glslFP->setData(fDataManager, *fp);
535 for (int i = 0; i < fp->numTextureSamplers(); ++i) {
536 auto& s = fp->textureSampler(i);
537 setTexture(gpu, s.samplerState(), s.peekTexture(), &bindings, &binding);
538 }
539 fp = iter.next();
540 glslFP = glslIter.next();
541 }
542 SkIPoint offset;
543 GrTexture* dstTexture = pipeline.peekDstTexture(&offset);
544 fXferProcessor->setData(fDataManager, pipeline.getXferProcessor(), dstTexture, offset);
545 if (GrTextureProxy* proxy = pipeline.dstTextureProxy()) {
546 GrFragmentProcessor::TextureSampler sampler(sk_ref_sp(proxy));
547 setTexture(gpu, sampler.samplerState(), sampler.peekTexture(), &bindings, &binding);
548 }
549 fDataManager.uploadUniformBuffers(gpu, geom, frag);
550 dawn::BindGroupDescriptor descriptor;
551 descriptor.layout = fBindGroupLayout;
552 descriptor.bindingCount = bindings.size();
553 descriptor.bindings = bindings.data();
554 return gpu->device().CreateBindGroup(&descriptor);
555 }
556