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