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