• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/ganesh/dawn/GrDawnProgramBuilder.h"
9 
10 #include "include/private/SkSLProgramKind.h"
11 #include "src/gpu/ganesh/GrAutoLocaleSetter.h"
12 #include "src/gpu/ganesh/GrRenderTarget.h"
13 #include "src/gpu/ganesh/GrStencilSettings.h"
14 #include "src/gpu/ganesh/dawn/GrDawnGpu.h"
15 #include "src/gpu/ganesh/dawn/GrDawnTexture.h"
16 #include "src/gpu/ganesh/effects/GrTextureEffect.h"
17 #include "src/sksl/SkSLCompiler.h"
18 #include "src/utils/SkShaderUtils.h"
19 
to_dawn_blend_factor(skgpu::BlendCoeff coeff)20 static wgpu::BlendFactor to_dawn_blend_factor(skgpu::BlendCoeff coeff) {
21     switch (coeff) {
22         case skgpu::BlendCoeff::kZero:
23             return wgpu::BlendFactor::Zero;
24         case skgpu::BlendCoeff::kOne:
25             return wgpu::BlendFactor::One;
26         case skgpu::BlendCoeff::kSC:
27             return wgpu::BlendFactor::Src;
28         case skgpu::BlendCoeff::kISC:
29             return wgpu::BlendFactor::OneMinusSrc;
30         case skgpu::BlendCoeff::kDC:
31             return wgpu::BlendFactor::Dst;
32         case skgpu::BlendCoeff::kIDC:
33             return wgpu::BlendFactor::OneMinusDst;
34         case skgpu::BlendCoeff::kSA:
35             return wgpu::BlendFactor::SrcAlpha;
36         case skgpu::BlendCoeff::kISA:
37             return wgpu::BlendFactor::OneMinusSrcAlpha;
38         case skgpu::BlendCoeff::kDA:
39             return wgpu::BlendFactor::DstAlpha;
40         case skgpu::BlendCoeff::kIDA:
41             return wgpu::BlendFactor::OneMinusDstAlpha;
42         case skgpu::BlendCoeff::kConstC:
43             return wgpu::BlendFactor::Constant;
44         case skgpu::BlendCoeff::kIConstC:
45             return wgpu::BlendFactor::OneMinusConstant;
46         case skgpu::BlendCoeff::kS2C:
47         case skgpu::BlendCoeff::kIS2C:
48         case skgpu::BlendCoeff::kS2A:
49         case skgpu::BlendCoeff::kIS2A:
50         default:
51             SkASSERT(!"unsupported blend coefficient");
52             return wgpu::BlendFactor::One;
53         }
54 }
55 
to_dawn_blend_factor_for_alpha(skgpu::BlendCoeff coeff)56 static wgpu::BlendFactor to_dawn_blend_factor_for_alpha(skgpu::BlendCoeff coeff) {
57     switch (coeff) {
58     // Force all srcColor used in alpha slot to alpha version.
59     case skgpu::BlendCoeff::kSC:
60         return wgpu::BlendFactor::SrcAlpha;
61     case skgpu::BlendCoeff::kISC:
62         return wgpu::BlendFactor::OneMinusSrcAlpha;
63     case skgpu::BlendCoeff::kDC:
64         return wgpu::BlendFactor::DstAlpha;
65     case skgpu::BlendCoeff::kIDC:
66         return wgpu::BlendFactor::OneMinusDstAlpha;
67     default:
68         return to_dawn_blend_factor(coeff);
69     }
70 }
71 
to_dawn_blend_operation(skgpu::BlendEquation equation)72 static wgpu::BlendOperation to_dawn_blend_operation(skgpu::BlendEquation equation) {
73     switch (equation) {
74     case skgpu::BlendEquation::kAdd:
75         return wgpu::BlendOperation::Add;
76     case skgpu::BlendEquation::kSubtract:
77         return wgpu::BlendOperation::Subtract;
78     case skgpu::BlendEquation::kReverseSubtract:
79         return wgpu::BlendOperation::ReverseSubtract;
80     default:
81         SkASSERT(!"unsupported blend equation");
82         return wgpu::BlendOperation::Add;
83     }
84 }
85 
to_dawn_compare_function(GrStencilTest test)86 static wgpu::CompareFunction to_dawn_compare_function(GrStencilTest test) {
87     switch (test) {
88         case GrStencilTest::kAlways:
89             return wgpu::CompareFunction::Always;
90         case GrStencilTest::kNever:
91             return wgpu::CompareFunction::Never;
92         case GrStencilTest::kGreater:
93             return wgpu::CompareFunction::Greater;
94         case GrStencilTest::kGEqual:
95             return wgpu::CompareFunction::GreaterEqual;
96         case GrStencilTest::kLess:
97             return wgpu::CompareFunction::Less;
98         case GrStencilTest::kLEqual:
99             return wgpu::CompareFunction::LessEqual;
100         case GrStencilTest::kEqual:
101             return wgpu::CompareFunction::Equal;
102         case GrStencilTest::kNotEqual:
103             return wgpu::CompareFunction::NotEqual;
104         default:
105             SkASSERT(!"unsupported stencil test");
106             return wgpu::CompareFunction::Always;
107     }
108 }
109 
to_dawn_stencil_operation(GrStencilOp op)110 static wgpu::StencilOperation to_dawn_stencil_operation(GrStencilOp op) {
111     switch (op) {
112         case GrStencilOp::kKeep:
113             return wgpu::StencilOperation::Keep;
114         case GrStencilOp::kZero:
115             return wgpu::StencilOperation::Zero;
116         case GrStencilOp::kReplace:
117             return wgpu::StencilOperation::Replace;
118         case GrStencilOp::kInvert:
119             return wgpu::StencilOperation::Invert;
120         case GrStencilOp::kIncClamp:
121             return wgpu::StencilOperation::IncrementClamp;
122         case GrStencilOp::kDecClamp:
123             return wgpu::StencilOperation::DecrementClamp;
124         case GrStencilOp::kIncWrap:
125             return wgpu::StencilOperation::IncrementWrap;
126         case GrStencilOp::kDecWrap:
127             return wgpu::StencilOperation::DecrementWrap;
128         default:
129             SkASSERT(!"unsupported stencil function");
130             return wgpu::StencilOperation::Keep;
131     }
132 }
133 
to_dawn_primitive_topology(GrPrimitiveType primitiveType)134 static wgpu::PrimitiveTopology to_dawn_primitive_topology(GrPrimitiveType primitiveType) {
135     switch (primitiveType) {
136         case GrPrimitiveType::kTriangles:
137             return wgpu::PrimitiveTopology::TriangleList;
138         case GrPrimitiveType::kTriangleStrip:
139             return wgpu::PrimitiveTopology::TriangleStrip;
140         case GrPrimitiveType::kPoints:
141             return wgpu::PrimitiveTopology::PointList;
142         case GrPrimitiveType::kLines:
143             return wgpu::PrimitiveTopology::LineList;
144         case GrPrimitiveType::kLineStrip:
145             return wgpu::PrimitiveTopology::LineStrip;
146     }
147     SkUNREACHABLE;
148 }
149 
to_dawn_vertex_format(GrVertexAttribType type)150 static wgpu::VertexFormat to_dawn_vertex_format(GrVertexAttribType type) {
151     switch (type) {
152     case kFloat_GrVertexAttribType:
153     case kHalf_GrVertexAttribType:
154         return wgpu::VertexFormat::Float32;
155     case kFloat2_GrVertexAttribType:
156     case kHalf2_GrVertexAttribType:
157         return wgpu::VertexFormat::Float32x2;
158     case kFloat3_GrVertexAttribType:
159         return wgpu::VertexFormat::Float32x3;
160     case kFloat4_GrVertexAttribType:
161     case kHalf4_GrVertexAttribType:
162         return wgpu::VertexFormat::Float32x4;
163     case kUShort2_GrVertexAttribType:
164         return wgpu::VertexFormat::Uint16x2;
165     case kInt_GrVertexAttribType:
166         return wgpu::VertexFormat::Sint32;
167     case kUByte4_norm_GrVertexAttribType:
168         return wgpu::VertexFormat::Unorm8x4;
169     default:
170         SkASSERT(!"unsupported vertex format");
171         return wgpu::VertexFormat::Float32x4;
172     }
173 }
174 
create_blend_state(const GrDawnGpu * gpu,const GrPipeline & pipeline)175 static wgpu::BlendState create_blend_state(const GrDawnGpu* gpu, const GrPipeline& pipeline) {
176     skgpu::BlendInfo blendInfo = pipeline.getXferProcessor().getBlendInfo();
177     skgpu::BlendEquation equation = blendInfo.fEquation;
178     skgpu::BlendCoeff srcCoeff = blendInfo.fSrcBlend;
179     skgpu::BlendCoeff dstCoeff = blendInfo.fDstBlend;
180 
181     wgpu::BlendFactor srcFactor = to_dawn_blend_factor(srcCoeff);
182     wgpu::BlendFactor dstFactor = to_dawn_blend_factor(dstCoeff);
183     wgpu::BlendFactor srcFactorAlpha = to_dawn_blend_factor_for_alpha(srcCoeff);
184     wgpu::BlendFactor dstFactorAlpha = to_dawn_blend_factor_for_alpha(dstCoeff);
185     wgpu::BlendOperation operation = to_dawn_blend_operation(equation);
186 
187     wgpu::BlendState blendState;
188     blendState.color = {operation, srcFactor, dstFactor};
189     blendState.alpha = {operation, srcFactorAlpha, dstFactorAlpha};
190 
191     return blendState;
192 }
193 
to_stencil_state_face(const GrStencilSettings::Face & face)194 static wgpu::StencilFaceState to_stencil_state_face(const GrStencilSettings::Face& face) {
195      wgpu::StencilFaceState desc;
196      desc.compare = to_dawn_compare_function(face.fTest);
197      desc.failOp = desc.depthFailOp = to_dawn_stencil_operation(face.fFailOp);
198      desc.passOp = to_dawn_stencil_operation(face.fPassOp);
199      return desc;
200 }
201 
create_depth_stencil_state(const GrProgramInfo & programInfo,wgpu::TextureFormat depthStencilFormat)202 static wgpu::DepthStencilState create_depth_stencil_state(
203         const GrProgramInfo& programInfo,
204         wgpu::TextureFormat depthStencilFormat) {
205     GrStencilSettings stencilSettings = programInfo.nonGLStencilSettings();
206     GrSurfaceOrigin origin = programInfo.origin();
207 
208     wgpu::DepthStencilState state;
209     state.format = depthStencilFormat;
210     if (!stencilSettings.isDisabled()) {
211         if (stencilSettings.isTwoSided()) {
212             auto front = stencilSettings.postOriginCCWFace(origin);
213             auto back = stencilSettings.postOriginCWFace(origin);
214             state.stencilFront = to_stencil_state_face(front);
215             state.stencilBack = to_stencil_state_face(back);
216             state.stencilReadMask = front.fTestMask;
217             state.stencilWriteMask = front.fWriteMask;
218         } else {
219             auto frontAndBack = stencilSettings.singleSidedFace();
220             state.stencilBack = state.stencilFront = to_stencil_state_face(frontAndBack);
221             state.stencilReadMask = frontAndBack.fTestMask;
222             state.stencilWriteMask = frontAndBack.fWriteMask;
223         }
224     }
225     return state;
226 }
227 
make_bind_group_entry(uint32_t binding,const wgpu::Sampler & sampler,const wgpu::TextureView & textureView)228 static wgpu::BindGroupEntry make_bind_group_entry(uint32_t binding,
229                                                   const wgpu::Sampler& sampler,
230                                                   const wgpu::TextureView& textureView) {
231     wgpu::BindGroupEntry result;
232     result.binding = binding;
233     result.buffer = nullptr;
234     result.offset = 0;
235     result.size = 0;
236     result.sampler = sampler;
237     result.textureView = textureView;
238     return result;
239 }
240 
make_bind_group_entry(uint32_t binding,const wgpu::Sampler & sampler)241 static wgpu::BindGroupEntry make_bind_group_entry(uint32_t binding,
242                                                   const wgpu::Sampler& sampler) {
243     return make_bind_group_entry(binding, sampler, nullptr);
244 }
245 
make_bind_group_entry(uint32_t binding,const wgpu::TextureView & textureView)246 static wgpu::BindGroupEntry make_bind_group_entry(uint32_t binding,
247                                                   const wgpu::TextureView& textureView) {
248     return make_bind_group_entry(binding, nullptr, textureView);
249 }
250 
Build(GrDawnGpu * gpu,GrRenderTarget * renderTarget,const GrProgramInfo & programInfo,wgpu::TextureFormat colorFormat,bool hasDepthStencil,wgpu::TextureFormat depthStencilFormat,GrProgramDesc * desc)251 sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu,
252                                                  GrRenderTarget* renderTarget,
253                                                  const GrProgramInfo& programInfo,
254                                                  wgpu::TextureFormat colorFormat,
255                                                  bool hasDepthStencil,
256                                                  wgpu::TextureFormat depthStencilFormat,
257                                                  GrProgramDesc* desc) {
258     GrAutoLocaleSetter als("C");
259 
260     GrDawnProgramBuilder builder(gpu, programInfo, desc);
261     if (!builder.emitAndInstallProcs()) {
262         return nullptr;
263     }
264 
265     builder.finalizeShaders();
266 
267     SkSL::Program::Inputs vertInputs, fragInputs;
268     bool flipY = programInfo.origin() != kTopLeft_GrSurfaceOrigin;
269     auto vsModule = builder.createShaderModule(builder.fVS, SkSL::ProgramKind::kVertex, flipY,
270                                                &vertInputs);
271     auto fsModule = builder.createShaderModule(builder.fFS, SkSL::ProgramKind::kFragment, flipY,
272                                                &fragInputs);
273     GrSPIRVUniformHandler::UniformInfoArray& uniforms = builder.fUniformHandler.fUniforms;
274     uint32_t uniformBufferSize = builder.fUniformHandler.fCurrentUBOOffset;
275     sk_sp<GrDawnProgram> result(new GrDawnProgram(uniforms, uniformBufferSize));
276     result->fGPImpl = std::move(builder.fGPImpl);
277     result->fXPImpl = std::move(builder.fXPImpl);
278     result->fFPImpls = std::move(builder.fFPImpls);
279     std::vector<wgpu::BindGroupLayoutEntry> uniformLayoutEntries;
280     if (0 != uniformBufferSize) {
281         wgpu::BindGroupLayoutEntry entry;
282         entry.binding = GrSPIRVUniformHandler::kUniformBinding;
283         entry.visibility = wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment;
284         entry.buffer.type = wgpu::BufferBindingType::Uniform;
285         uniformLayoutEntries.push_back(std::move(entry));
286     }
287     wgpu::BindGroupLayoutDescriptor uniformBindGroupLayoutDesc;
288     uniformBindGroupLayoutDesc.entryCount = uniformLayoutEntries.size();
289     uniformBindGroupLayoutDesc.entries = uniformLayoutEntries.data();
290     result->fBindGroupLayouts.push_back(
291         gpu->device().CreateBindGroupLayout(&uniformBindGroupLayoutDesc));
292     uint32_t binding = 0;
293     std::vector<wgpu::BindGroupLayoutEntry> textureLayoutEntries;
294     int textureCount = builder.fUniformHandler.fSamplers.count();
295     if (textureCount > 0) {
296         for (int i = 0; i < textureCount; ++i)  {
297             {
298                 wgpu::BindGroupLayoutEntry entry;
299                 entry.binding = binding++;
300                 entry.visibility = wgpu::ShaderStage::Fragment;
301                 entry.sampler.type = wgpu::SamplerBindingType::Filtering;
302                 textureLayoutEntries.push_back(std::move(entry));
303             }
304             {
305                 wgpu::BindGroupLayoutEntry entry;
306                 entry.binding = binding++;
307                 entry.visibility = wgpu::ShaderStage::Fragment;
308                 entry.texture.sampleType = wgpu::TextureSampleType::Float;
309                 entry.texture.viewDimension = wgpu::TextureViewDimension::e2D;
310                 textureLayoutEntries.push_back(std::move(entry));
311             }
312         }
313         wgpu::BindGroupLayoutDescriptor textureBindGroupLayoutDesc;
314         textureBindGroupLayoutDesc.entryCount = textureLayoutEntries.size();
315         textureBindGroupLayoutDesc.entries = textureLayoutEntries.data();
316         result->fBindGroupLayouts.push_back(
317             gpu->device().CreateBindGroupLayout(&textureBindGroupLayoutDesc));
318     }
319     wgpu::PipelineLayoutDescriptor pipelineLayoutDesc;
320     pipelineLayoutDesc.bindGroupLayoutCount = result->fBindGroupLayouts.size();
321     pipelineLayoutDesc.bindGroupLayouts = result->fBindGroupLayouts.data();
322     auto pipelineLayout = gpu->device().CreatePipelineLayout(&pipelineLayoutDesc);
323     result->fBuiltinUniformHandles = builder.fUniformHandles;
324     const GrPipeline& pipeline = programInfo.pipeline();
325     wgpu::DepthStencilState depthStencilState;
326 
327 #ifdef SK_DEBUG
328     if (programInfo.isStencilEnabled()) {
329         SkASSERT(renderTarget->numStencilBits(renderTarget->numSamples() > 1) == 8);
330     }
331 #endif
332     depthStencilState = create_depth_stencil_state(programInfo, depthStencilFormat);
333 
334     std::vector<wgpu::VertexBufferLayout> inputs;
335 
336     std::vector<wgpu::VertexAttribute> vertexAttributes;
337     const GrGeometryProcessor& geomProc = programInfo.geomProc();
338     int i = 0;
339     if (geomProc.numVertexAttributes() > 0) {
340         for (auto attrib : geomProc.vertexAttributes()) {
341             wgpu::VertexAttribute attribute;
342             attribute.shaderLocation = i;
343             attribute.offset = *attrib.offset();
344             attribute.format = to_dawn_vertex_format(attrib.cpuType());
345             vertexAttributes.push_back(attribute);
346             i++;
347         }
348         wgpu::VertexBufferLayout input;
349         input.arrayStride = geomProc.vertexStride();
350         input.stepMode = wgpu::VertexStepMode::Vertex;
351         input.attributeCount = vertexAttributes.size();
352         input.attributes = &vertexAttributes.front();
353         inputs.push_back(input);
354     }
355     std::vector<wgpu::VertexAttribute> instanceAttributes;
356     if (geomProc.numInstanceAttributes() > 0) {
357         for (auto attrib : geomProc.instanceAttributes()) {
358             wgpu::VertexAttribute attribute;
359             attribute.shaderLocation = i;
360             attribute.offset = *attrib.offset();
361             attribute.format = to_dawn_vertex_format(attrib.cpuType());
362             instanceAttributes.push_back(attribute);
363             i++;
364         }
365         wgpu::VertexBufferLayout input;
366         input.arrayStride = geomProc.instanceStride();
367         input.stepMode = wgpu::VertexStepMode::Instance;
368         input.attributeCount = instanceAttributes.size();
369         input.attributes = &instanceAttributes.front();
370         inputs.push_back(input);
371     }
372     wgpu::VertexState vertexState;
373     vertexState.module = vsModule;
374     vertexState.entryPoint = "main";
375     vertexState.bufferCount = inputs.size();
376     vertexState.buffers = &inputs.front();
377 
378     wgpu::BlendState blendState = create_blend_state(gpu, pipeline);
379 
380     wgpu::ColorTargetState colorTargetState;
381     colorTargetState.format = colorFormat;
382     colorTargetState.blend = &blendState;
383 
384     bool writesColor = pipeline.getXferProcessor().getBlendInfo().fWritesColor;
385     colorTargetState.writeMask = writesColor ? wgpu::ColorWriteMask::All
386                                              : wgpu::ColorWriteMask::None;
387 
388     wgpu::FragmentState fragmentState;
389     fragmentState.module = fsModule;
390     fragmentState.entryPoint = "main";
391     fragmentState.targetCount = 1;
392     fragmentState.targets = &colorTargetState;
393 
394     wgpu::RenderPipelineDescriptor rpDesc;
395     rpDesc.layout = pipelineLayout;
396     rpDesc.vertex = vertexState;
397     rpDesc.primitive.topology = to_dawn_primitive_topology(programInfo.primitiveType());
398     GrPrimitiveType primitiveType = programInfo.primitiveType();
399     if (primitiveType == GrPrimitiveType::kTriangleStrip ||
400         primitiveType == GrPrimitiveType::kLineStrip) {
401         rpDesc.primitive.stripIndexFormat = wgpu::IndexFormat::Uint16;
402     }
403     if (hasDepthStencil) {
404         rpDesc.depthStencil = &depthStencilState;
405     }
406     rpDesc.fragment = &fragmentState;
407     result->fRenderPipeline = gpu->device().CreateRenderPipeline(&rpDesc);
408     return result;
409 }
410 
GrDawnProgramBuilder(GrDawnGpu * gpu,const GrProgramInfo & programInfo,GrProgramDesc * desc)411 GrDawnProgramBuilder::GrDawnProgramBuilder(GrDawnGpu* gpu,
412                                            const GrProgramInfo& programInfo,
413                                            GrProgramDesc* desc)
414     : INHERITED(*desc, programInfo)
415     , fGpu(gpu)
416     , fVaryingHandler(this)
417     , fUniformHandler(this) {
418 }
419 
createShaderModule(const GrGLSLShaderBuilder & builder,SkSL::ProgramKind kind,bool flipY,SkSL::Program::Inputs * inputs)420 wgpu::ShaderModule GrDawnProgramBuilder::createShaderModule(const GrGLSLShaderBuilder& builder,
421                                                             SkSL::ProgramKind kind,
422                                                             bool flipY,
423                                                             SkSL::Program::Inputs* inputs) {
424     wgpu::Device device = fGpu->device();
425     SkString source(builder.fCompilerString.c_str());
426 
427 #if 0
428     std::string sksl = SkShaderUtils::PrettyPrint(builder.fCompilerString);
429     printf("converting program:\n%s\n", sksl.c_str());
430 #endif
431 
432     std::string spirvSource = fGpu->SkSLToSPIRV(source.c_str(),
433                                                 kind,
434                                                 fUniformHandler.getRTFlipOffset(),
435                                                 inputs);
436     if (inputs->fUseFlipRTUniform) {
437         this->addRTFlipUniform(SKSL_RTFLIP_NAME);
438     }
439 
440     return fGpu->createShaderModule(spirvSource);
441 }
442 
caps() const443 const GrCaps* GrDawnProgramBuilder::caps() const {
444     return fGpu->caps();
445 }
446 
shaderCompiler() const447 SkSL::Compiler* GrDawnProgramBuilder::shaderCompiler() const {
448     return fGpu->shaderCompiler();
449 }
450 
setRenderTargetState(const GrRenderTarget * rt,GrSurfaceOrigin origin)451 void GrDawnProgram::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin) {
452     // Set RT adjustment and RT flip
453     SkISize dimensions = rt->dimensions();
454     SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
455     if (fRenderTargetState.fRenderTargetOrigin != origin ||
456         fRenderTargetState.fRenderTargetSize != dimensions) {
457         fRenderTargetState.fRenderTargetSize = dimensions;
458         fRenderTargetState.fRenderTargetOrigin = origin;
459 
460         // The client will mark a swap buffer as kTopLeft when making a SkSurface because
461         // Dawn's framebuffer space has (0, 0) at the top left. This agrees with Skia's device
462         // coords. However, in NDC (-1, -1) is the bottom left. So we flip when origin is kTopLeft.
463         bool flip = (origin == kTopLeft_GrSurfaceOrigin);
464         std::array<float, 4> v = SkSL::Compiler::GetRTAdjustVector(dimensions, flip);
465         fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, v.data());
466         if (fBuiltinUniformHandles.fRTFlipUni.isValid()) {
467             // Note above that framebuffer space has origin top left. So we need !flip here.
468             std::array<float, 2> d = SkSL::Compiler::GetRTFlipVector(rt->height(), !flip);
469             fDataManager.set2fv(fBuiltinUniformHandles.fRTFlipUni, 1, d.data());
470         }
471     }
472 }
473 
set_texture(GrDawnGpu * gpu,GrSamplerState state,GrTexture * texture,std::vector<wgpu::BindGroupEntry> * bindings,int * binding)474 static void set_texture(GrDawnGpu* gpu, GrSamplerState state, GrTexture* texture,
475                         std::vector<wgpu::BindGroupEntry>* bindings, int* binding) {
476     // FIXME: could probably cache samplers in GrDawnProgram
477     wgpu::Sampler sampler = gpu->getOrCreateSampler(state);
478     bindings->push_back(make_bind_group_entry((*binding)++, sampler));
479     GrDawnTexture* tex = static_cast<GrDawnTexture*>(texture);
480     wgpu::TextureViewDescriptor viewDesc;
481     // Note that a mipLevelCount == WGPU_MIP_LEVEL_COUNT_UNDEFINED here means to expose all
482     // available levels.
483     viewDesc.mipLevelCount = GrSamplerState::MipmapMode::kNone == state.mipmapMode()
484                                      ? 1
485                                      : WGPU_MIP_LEVEL_COUNT_UNDEFINED;
486     wgpu::TextureView textureView = tex->texture().CreateView(&viewDesc);
487     bindings->push_back(make_bind_group_entry((*binding)++, textureView));
488 }
489 
setUniformData(GrDawnGpu * gpu,const GrRenderTarget * renderTarget,const GrProgramInfo & programInfo)490 wgpu::BindGroup GrDawnProgram::setUniformData(GrDawnGpu* gpu, const GrRenderTarget* renderTarget,
491                                               const GrProgramInfo& programInfo) {
492     if (0 == fDataManager.uniformBufferSize()) {
493         return nullptr;
494     }
495     this->setRenderTargetState(renderTarget, programInfo.origin());
496     const GrPipeline& pipeline = programInfo.pipeline();
497     const GrGeometryProcessor& geomProc = programInfo.geomProc();
498     fGPImpl->setData(fDataManager, *gpu->caps()->shaderCaps(), geomProc);
499 
500     for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) {
501         const auto& fp = programInfo.pipeline().getFragmentProcessor(i);
502         fp.visitWithImpls([&](const GrFragmentProcessor& fp,
503                               GrFragmentProcessor::ProgramImpl& impl) {
504             impl.setData(fDataManager, fp);
505         }, *fFPImpls[i]);
506     }
507 
508     programInfo.pipeline().setDstTextureUniforms(fDataManager, &fBuiltinUniformHandles);
509     fXPImpl->setData(fDataManager, pipeline.getXferProcessor());
510 
511     return fDataManager.uploadUniformBuffers(gpu, fBindGroupLayouts[0]);
512 }
513 
setTextures(GrDawnGpu * gpu,const GrGeometryProcessor & geomProc,const GrPipeline & pipeline,const GrSurfaceProxy * const geomProcTextures[])514 wgpu::BindGroup GrDawnProgram::setTextures(GrDawnGpu* gpu,
515                                            const GrGeometryProcessor& geomProc,
516                                            const GrPipeline& pipeline,
517                                            const GrSurfaceProxy* const geomProcTextures[]) {
518     if (fBindGroupLayouts.size() < 2) {
519         return nullptr;
520     }
521     std::vector<wgpu::BindGroupEntry> bindings;
522     int binding = 0;
523     if (geomProcTextures) {
524         for (int i = 0; i < geomProc.numTextureSamplers(); ++i) {
525             SkASSERT(geomProcTextures[i]->asTextureProxy());
526             auto& sampler = geomProc.textureSampler(i);
527             set_texture(gpu, sampler.samplerState(), geomProcTextures[i]->peekTexture(), &bindings,
528                         &binding);
529         }
530     }
531 
532     if (GrTexture* dstTexture = pipeline.peekDstTexture()) {
533         set_texture(gpu, GrSamplerState::Filter::kNearest, dstTexture, &bindings, &binding);
534     }
535 
536     pipeline.visitTextureEffects([&](const GrTextureEffect& te) {
537         set_texture(gpu, te.samplerState(), te.texture(), &bindings, &binding);
538     });
539 
540     wgpu::BindGroupDescriptor descriptor;
541     descriptor.layout = fBindGroupLayouts[1];
542     descriptor.entryCount = bindings.size();
543     descriptor.entries = bindings.data();
544     return gpu->device().CreateBindGroup(&descriptor);
545 }
546