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