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