blob: 7d388caba094aeda49af99795a21643179949bf7 [file] [log] [blame]
Stephen Whitebb6bed12019-08-02 09:57:55 -04001/*
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
Brian Salomon201cdbb2019-08-14 17:00:30 -040010#include "src/gpu/GrRenderTarget.h"
Stephen Whitef813ef72019-08-09 12:28:37 -040011#include "src/gpu/GrShaderUtils.h"
12#include "src/gpu/GrStencilSettings.h"
Stephen Whitebb6bed12019-08-02 09:57:55 -040013#include "src/gpu/dawn/GrDawnGpu.h"
Stephen White170d9902019-08-15 16:48:24 -040014#include "src/gpu/dawn/GrDawnTexture.h"
Stephen Whitebb6bed12019-08-02 09:57:55 -040015#include "src/sksl/SkSLCompiler.h"
16
Stephen Whitebb6bed12019-08-02 09:57:55 -040017static SkSL::String sksl_to_spirv(const GrDawnGpu* gpu, const char* shaderString,
Stephen White40c47e12019-11-01 13:13:03 -040018 SkSL::Program::Kind kind, bool flipY, uint32_t rtHeightOffset,
Stephen White20c626a2019-10-15 13:35:37 -040019 SkSL::Program::Inputs* inputs) {
Stephen Whitebb6bed12019-08-02 09:57:55 -040020 SkSL::Program::Settings settings;
Stephen White170d9902019-08-15 16:48:24 -040021 settings.fCaps = gpu->caps()->shaderCaps();
Stephen White20c626a2019-10-15 13:35:37 -040022 settings.fFlipY = flipY;
Stephen White40c47e12019-11-01 13:13:03 -040023 settings.fRTHeightOffset = rtHeightOffset;
Greg Daniel49f920e2020-04-16 10:33:39 -040024 settings.fRTHeightBinding = 0;
25 settings.fRTHeightSet = 0;
Stephen Whiteac45f492020-07-06 15:53:03 -040026#ifdef SK_BUILD_FOR_WIN
27 // Work around the fact that D3D12 gives w in fragcoord.w, while the other APIs give 1/w.
28 // This difference may be better handled by Dawn, at which point this workaround can be removed.
29 // (See http://skbug.com/10475).
30 settings.fInverseW = true;
31#endif
Stephen Whitebb6bed12019-08-02 09:57:55 -040032 std::unique_ptr<SkSL::Program> program = gpu->shaderCompiler()->convertProgram(
33 kind,
34 shaderString,
35 settings);
36 if (!program) {
37 SkDebugf("SkSL error:\n%s\n", gpu->shaderCompiler()->errorText().c_str());
38 SkASSERT(false);
39 return "";
40 }
41 *inputs = program->fInputs;
42 SkSL::String code;
43 if (!gpu->shaderCompiler()->toSPIRV(*program, &code)) {
44 return "";
45 }
46 return code;
47}
48
Stephen White3cc8d4f2019-10-30 09:56:23 -040049static wgpu::BlendFactor to_dawn_blend_factor(GrBlendCoeff coeff) {
Stephen Whitebb6bed12019-08-02 09:57:55 -040050 switch (coeff) {
Greg Daniel6e2af5c2020-03-30 15:07:05 -040051 case kZero_GrBlendCoeff:
52 return wgpu::BlendFactor::Zero;
53 case kOne_GrBlendCoeff:
54 return wgpu::BlendFactor::One;
55 case kSC_GrBlendCoeff:
56 return wgpu::BlendFactor::SrcColor;
57 case kISC_GrBlendCoeff:
58 return wgpu::BlendFactor::OneMinusSrcColor;
59 case kDC_GrBlendCoeff:
60 return wgpu::BlendFactor::DstColor;
61 case kIDC_GrBlendCoeff:
62 return wgpu::BlendFactor::OneMinusDstColor;
63 case kSA_GrBlendCoeff:
64 return wgpu::BlendFactor::SrcAlpha;
65 case kISA_GrBlendCoeff:
66 return wgpu::BlendFactor::OneMinusSrcAlpha;
67 case kDA_GrBlendCoeff:
68 return wgpu::BlendFactor::DstAlpha;
69 case kIDA_GrBlendCoeff:
70 return wgpu::BlendFactor::OneMinusDstAlpha;
71 case kConstC_GrBlendCoeff:
72 return wgpu::BlendFactor::BlendColor;
73 case kIConstC_GrBlendCoeff:
74 return wgpu::BlendFactor::OneMinusBlendColor;
75 case kS2C_GrBlendCoeff:
76 case kIS2C_GrBlendCoeff:
77 case kS2A_GrBlendCoeff:
78 case kIS2A_GrBlendCoeff:
79 default:
80 SkASSERT(!"unsupported blend coefficient");
81 return wgpu::BlendFactor::One;
82 }
Stephen Whitebb6bed12019-08-02 09:57:55 -040083}
84
Stephen White3cc8d4f2019-10-30 09:56:23 -040085static wgpu::BlendFactor to_dawn_blend_factor_for_alpha(GrBlendCoeff coeff) {
Stephen Whitef813ef72019-08-09 12:28:37 -040086 switch (coeff) {
87 // Force all srcColor used in alpha slot to alpha version.
88 case kSC_GrBlendCoeff:
Stephen White3cc8d4f2019-10-30 09:56:23 -040089 return wgpu::BlendFactor::SrcAlpha;
Stephen Whitef813ef72019-08-09 12:28:37 -040090 case kISC_GrBlendCoeff:
Stephen White3cc8d4f2019-10-30 09:56:23 -040091 return wgpu::BlendFactor::OneMinusSrcAlpha;
Stephen Whitef813ef72019-08-09 12:28:37 -040092 case kDC_GrBlendCoeff:
Stephen White3cc8d4f2019-10-30 09:56:23 -040093 return wgpu::BlendFactor::DstAlpha;
Stephen Whitef813ef72019-08-09 12:28:37 -040094 case kIDC_GrBlendCoeff:
Stephen White3cc8d4f2019-10-30 09:56:23 -040095 return wgpu::BlendFactor::OneMinusDstAlpha;
Stephen Whitef813ef72019-08-09 12:28:37 -040096 default:
97 return to_dawn_blend_factor(coeff);
98 }
99}
100
Stephen White3cc8d4f2019-10-30 09:56:23 -0400101static wgpu::BlendOperation to_dawn_blend_operation(GrBlendEquation equation) {
Stephen Whitebb6bed12019-08-02 09:57:55 -0400102 switch (equation) {
103 case kAdd_GrBlendEquation:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400104 return wgpu::BlendOperation::Add;
Stephen Whitebb6bed12019-08-02 09:57:55 -0400105 case kSubtract_GrBlendEquation:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400106 return wgpu::BlendOperation::Subtract;
Stephen Whitef813ef72019-08-09 12:28:37 -0400107 case kReverseSubtract_GrBlendEquation:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400108 return wgpu::BlendOperation::ReverseSubtract;
Stephen Whitebb6bed12019-08-02 09:57:55 -0400109 default:
110 SkASSERT(!"unsupported blend equation");
Stephen White3cc8d4f2019-10-30 09:56:23 -0400111 return wgpu::BlendOperation::Add;
Stephen Whitebb6bed12019-08-02 09:57:55 -0400112 }
113}
114
Stephen White3cc8d4f2019-10-30 09:56:23 -0400115static wgpu::CompareFunction to_dawn_compare_function(GrStencilTest test) {
Stephen Whitef813ef72019-08-09 12:28:37 -0400116 switch (test) {
117 case GrStencilTest::kAlways:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400118 return wgpu::CompareFunction::Always;
Stephen Whitef813ef72019-08-09 12:28:37 -0400119 case GrStencilTest::kNever:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400120 return wgpu::CompareFunction::Never;
Stephen Whitef813ef72019-08-09 12:28:37 -0400121 case GrStencilTest::kGreater:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400122 return wgpu::CompareFunction::Greater;
Stephen Whitef813ef72019-08-09 12:28:37 -0400123 case GrStencilTest::kGEqual:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400124 return wgpu::CompareFunction::GreaterEqual;
Stephen Whitef813ef72019-08-09 12:28:37 -0400125 case GrStencilTest::kLess:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400126 return wgpu::CompareFunction::Less;
Stephen Whitef813ef72019-08-09 12:28:37 -0400127 case GrStencilTest::kLEqual:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400128 return wgpu::CompareFunction::LessEqual;
Stephen Whitef813ef72019-08-09 12:28:37 -0400129 case GrStencilTest::kEqual:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400130 return wgpu::CompareFunction::Equal;
Stephen Whitef813ef72019-08-09 12:28:37 -0400131 case GrStencilTest::kNotEqual:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400132 return wgpu::CompareFunction::NotEqual;
Stephen Whitef813ef72019-08-09 12:28:37 -0400133 default:
134 SkASSERT(!"unsupported stencil test");
Stephen White3cc8d4f2019-10-30 09:56:23 -0400135 return wgpu::CompareFunction::Always;
Stephen Whitef813ef72019-08-09 12:28:37 -0400136 }
137}
138
Stephen White3cc8d4f2019-10-30 09:56:23 -0400139static wgpu::StencilOperation to_dawn_stencil_operation(GrStencilOp op) {
Stephen Whitef813ef72019-08-09 12:28:37 -0400140 switch (op) {
141 case GrStencilOp::kKeep:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400142 return wgpu::StencilOperation::Keep;
Stephen Whitef813ef72019-08-09 12:28:37 -0400143 case GrStencilOp::kZero:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400144 return wgpu::StencilOperation::Zero;
Stephen Whitef813ef72019-08-09 12:28:37 -0400145 case GrStencilOp::kReplace:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400146 return wgpu::StencilOperation::Replace;
Stephen Whitef813ef72019-08-09 12:28:37 -0400147 case GrStencilOp::kInvert:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400148 return wgpu::StencilOperation::Invert;
Stephen Whitef813ef72019-08-09 12:28:37 -0400149 case GrStencilOp::kIncClamp:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400150 return wgpu::StencilOperation::IncrementClamp;
Stephen Whitef813ef72019-08-09 12:28:37 -0400151 case GrStencilOp::kDecClamp:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400152 return wgpu::StencilOperation::DecrementClamp;
Stephen Whitef813ef72019-08-09 12:28:37 -0400153 case GrStencilOp::kIncWrap:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400154 return wgpu::StencilOperation::IncrementWrap;
Stephen Whitef813ef72019-08-09 12:28:37 -0400155 case GrStencilOp::kDecWrap:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400156 return wgpu::StencilOperation::DecrementWrap;
Stephen Whitef813ef72019-08-09 12:28:37 -0400157 default:
158 SkASSERT(!"unsupported stencil function");
Stephen White3cc8d4f2019-10-30 09:56:23 -0400159 return wgpu::StencilOperation::Keep;
Stephen Whitef813ef72019-08-09 12:28:37 -0400160 }
161}
162
Stephen White3cc8d4f2019-10-30 09:56:23 -0400163static wgpu::PrimitiveTopology to_dawn_primitive_topology(GrPrimitiveType primitiveType) {
Stephen Whitee2641312019-08-29 15:10:50 -0400164 switch (primitiveType) {
165 case GrPrimitiveType::kTriangles:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400166 return wgpu::PrimitiveTopology::TriangleList;
Stephen Whitee2641312019-08-29 15:10:50 -0400167 case GrPrimitiveType::kTriangleStrip:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400168 return wgpu::PrimitiveTopology::TriangleStrip;
Stephen Whitee2641312019-08-29 15:10:50 -0400169 case GrPrimitiveType::kPoints:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400170 return wgpu::PrimitiveTopology::PointList;
Stephen Whitee2641312019-08-29 15:10:50 -0400171 case GrPrimitiveType::kLines:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400172 return wgpu::PrimitiveTopology::LineList;
Stephen Whitee2641312019-08-29 15:10:50 -0400173 case GrPrimitiveType::kLineStrip:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400174 return wgpu::PrimitiveTopology::LineStrip;
Robert Phillips571177f2019-10-04 14:41:49 -0400175 case GrPrimitiveType::kPath:
Stephen Whitee2641312019-08-29 15:10:50 -0400176 default:
177 SkASSERT(!"unsupported primitive topology");
Stephen White3cc8d4f2019-10-30 09:56:23 -0400178 return wgpu::PrimitiveTopology::TriangleList;
Stephen Whitee2641312019-08-29 15:10:50 -0400179 }
180}
181
Stephen White3cc8d4f2019-10-30 09:56:23 -0400182static wgpu::VertexFormat to_dawn_vertex_format(GrVertexAttribType type) {
Stephen Whitee2641312019-08-29 15:10:50 -0400183 switch (type) {
184 case kFloat_GrVertexAttribType:
185 case kHalf_GrVertexAttribType:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400186 return wgpu::VertexFormat::Float;
Stephen Whitee2641312019-08-29 15:10:50 -0400187 case kFloat2_GrVertexAttribType:
188 case kHalf2_GrVertexAttribType:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400189 return wgpu::VertexFormat::Float2;
Stephen Whitee2641312019-08-29 15:10:50 -0400190 case kFloat3_GrVertexAttribType:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400191 return wgpu::VertexFormat::Float3;
Stephen Whitee2641312019-08-29 15:10:50 -0400192 case kFloat4_GrVertexAttribType:
193 case kHalf4_GrVertexAttribType:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400194 return wgpu::VertexFormat::Float4;
Stephen Whitee2641312019-08-29 15:10:50 -0400195 case kUShort2_GrVertexAttribType:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400196 return wgpu::VertexFormat::UShort2;
Stephen Whitee2641312019-08-29 15:10:50 -0400197 case kInt_GrVertexAttribType:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400198 return wgpu::VertexFormat::Int;
Stephen Whitee2641312019-08-29 15:10:50 -0400199 case kUByte4_norm_GrVertexAttribType:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400200 return wgpu::VertexFormat::UChar4Norm;
Stephen Whitee2641312019-08-29 15:10:50 -0400201 default:
202 SkASSERT(!"unsupported vertex format");
Stephen White3cc8d4f2019-10-30 09:56:23 -0400203 return wgpu::VertexFormat::Float4;
Stephen Whitee2641312019-08-29 15:10:50 -0400204 }
205}
206
Stephen White3cc8d4f2019-10-30 09:56:23 -0400207static wgpu::ColorStateDescriptor create_color_state(const GrDawnGpu* gpu,
Stephen Whitebb6bed12019-08-02 09:57:55 -0400208 const GrPipeline& pipeline,
Stephen White3cc8d4f2019-10-30 09:56:23 -0400209 wgpu::TextureFormat colorFormat) {
Stephen Whitebb6bed12019-08-02 09:57:55 -0400210 GrXferProcessor::BlendInfo blendInfo = pipeline.getXferProcessor().getBlendInfo();
211 GrBlendEquation equation = blendInfo.fEquation;
212 GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
213 GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
214
Stephen White3cc8d4f2019-10-30 09:56:23 -0400215 wgpu::BlendFactor srcFactor = to_dawn_blend_factor(srcCoeff);
216 wgpu::BlendFactor dstFactor = to_dawn_blend_factor(dstCoeff);
217 wgpu::BlendFactor srcFactorAlpha = to_dawn_blend_factor_for_alpha(srcCoeff);
218 wgpu::BlendFactor dstFactorAlpha = to_dawn_blend_factor_for_alpha(dstCoeff);
219 wgpu::BlendOperation operation = to_dawn_blend_operation(equation);
220 auto mask = blendInfo.fWriteColor ? wgpu::ColorWriteMask::All : wgpu::ColorWriteMask::None;
Stephen Whitebb6bed12019-08-02 09:57:55 -0400221
Stephen White3cc8d4f2019-10-30 09:56:23 -0400222 wgpu::BlendDescriptor colorDesc = {operation, srcFactor, dstFactor};
223 wgpu::BlendDescriptor alphaDesc = {operation, srcFactorAlpha, dstFactorAlpha};
Stephen Whitebb6bed12019-08-02 09:57:55 -0400224
Stephen White3cc8d4f2019-10-30 09:56:23 -0400225 wgpu::ColorStateDescriptor descriptor;
Stephen Whitebb6bed12019-08-02 09:57:55 -0400226 descriptor.format = colorFormat;
227 descriptor.alphaBlend = alphaDesc;
228 descriptor.colorBlend = colorDesc;
229 descriptor.nextInChain = nullptr;
230 descriptor.writeMask = mask;
231
232 return descriptor;
233}
234
Stephen White3cc8d4f2019-10-30 09:56:23 -0400235static wgpu::StencilStateFaceDescriptor to_stencil_state_face(const GrStencilSettings::Face& face) {
236 wgpu::StencilStateFaceDescriptor desc;
Stephen Whitef813ef72019-08-09 12:28:37 -0400237 desc.compare = to_dawn_compare_function(face.fTest);
238 desc.failOp = desc.depthFailOp = to_dawn_stencil_operation(face.fFailOp);
239 desc.passOp = to_dawn_stencil_operation(face.fPassOp);
240 return desc;
241}
242
Stephen White3cc8d4f2019-10-30 09:56:23 -0400243static wgpu::DepthStencilStateDescriptor create_depth_stencil_state(
Robert Phillipsa87c5292019-11-12 10:12:42 -0500244 const GrProgramInfo& programInfo,
245 wgpu::TextureFormat depthStencilFormat) {
246 GrStencilSettings stencilSettings = programInfo.nonGLStencilSettings();
247 GrSurfaceOrigin origin = programInfo.origin();
248
Stephen White3cc8d4f2019-10-30 09:56:23 -0400249 wgpu::DepthStencilStateDescriptor state;
Stephen Whitef813ef72019-08-09 12:28:37 -0400250 state.format = depthStencilFormat;
Stephen Whitee2641312019-08-29 15:10:50 -0400251 if (!stencilSettings.isDisabled()) {
Stephen Whitef813ef72019-08-09 12:28:37 -0400252 if (stencilSettings.isTwoSided()) {
Sean Gilhuly6c536a52019-11-11 11:13:03 -0500253 auto front = stencilSettings.postOriginCCWFace(origin);
Stephen White3a62ed42019-11-11 16:56:02 -0500254 auto back = stencilSettings.postOriginCWFace(origin);
Stephen Whitef4b3d6b2019-10-18 07:54:25 -0400255 state.stencilFront = to_stencil_state_face(front);
256 state.stencilBack = to_stencil_state_face(back);
257 state.stencilReadMask = front.fTestMask;
258 state.stencilWriteMask = front.fWriteMask;
Stephen Whitef813ef72019-08-09 12:28:37 -0400259 } else {
Sean Gilhuly6c536a52019-11-11 11:13:03 -0500260 auto frontAndBack = stencilSettings.singleSidedFace();
Stephen Whitef4b3d6b2019-10-18 07:54:25 -0400261 state.stencilBack = state.stencilFront = to_stencil_state_face(frontAndBack);
262 state.stencilReadMask = frontAndBack.fTestMask;
263 state.stencilWriteMask = frontAndBack.fWriteMask;
Stephen Whitef813ef72019-08-09 12:28:37 -0400264 }
265 }
266 return state;
267}
268
Stephen White3d2dd262020-04-27 15:43:59 -0400269static wgpu::BindGroupEntry make_bind_group_entry(uint32_t binding, const wgpu::Buffer& buffer,
270 uint32_t offset, uint32_t size, const
271 wgpu::Sampler& sampler,
272 const wgpu::TextureView& textureView) {
273 wgpu::BindGroupEntry result;
Stephen Whitebb6bed12019-08-02 09:57:55 -0400274 result.binding = binding;
275 result.buffer = buffer;
276 result.offset = offset;
277 result.size = size;
278 result.sampler = sampler;
279 result.textureView = textureView;
280 return result;
281}
282
Stephen White3d2dd262020-04-27 15:43:59 -0400283static wgpu::BindGroupEntry make_bind_group_entry(uint32_t binding, const wgpu::Buffer& buffer,
284 uint32_t offset, uint32_t size) {
285 return make_bind_group_entry(binding, buffer, offset, size, nullptr, nullptr);
Stephen Whitebb6bed12019-08-02 09:57:55 -0400286}
287
Stephen White3d2dd262020-04-27 15:43:59 -0400288static wgpu::BindGroupEntry make_bind_group_entry(uint32_t binding,
289 const wgpu::Sampler& sampler) {
290 return make_bind_group_entry(binding, nullptr, 0, 0, sampler, nullptr);
Stephen White170d9902019-08-15 16:48:24 -0400291}
292
Stephen White3d2dd262020-04-27 15:43:59 -0400293static wgpu::BindGroupEntry make_bind_group_entry(uint32_t binding,
294 const wgpu::TextureView& textureView) {
295 return make_bind_group_entry(binding, nullptr, 0, 0, nullptr, textureView);
Stephen White170d9902019-08-15 16:48:24 -0400296}
297
Stephen Whitebb6bed12019-08-02 09:57:55 -0400298sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu,
299 GrRenderTarget* renderTarget,
Stephen White729c78d2019-10-14 12:42:59 -0400300 const GrProgramInfo& programInfo,
Stephen White3cc8d4f2019-10-30 09:56:23 -0400301 wgpu::TextureFormat colorFormat,
Stephen Whitef813ef72019-08-09 12:28:37 -0400302 bool hasDepthStencil,
Stephen White3cc8d4f2019-10-30 09:56:23 -0400303 wgpu::TextureFormat depthStencilFormat,
Stephen Whitebb6bed12019-08-02 09:57:55 -0400304 GrProgramDesc* desc) {
Stephen White729c78d2019-10-14 12:42:59 -0400305 GrDawnProgramBuilder builder(gpu, renderTarget, programInfo, desc);
Stephen Whitebb6bed12019-08-02 09:57:55 -0400306 if (!builder.emitAndInstallProcs()) {
307 return nullptr;
308 }
309
310 builder.fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
311 builder.fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
312 builder.fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
313 builder.fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
314
315 builder.finalizeShaders();
316
317 SkSL::Program::Inputs vertInputs, fragInputs;
Stephen White20c626a2019-10-15 13:35:37 -0400318 bool flipY = programInfo.origin() != kTopLeft_GrSurfaceOrigin;
319 auto vsModule = builder.createShaderModule(builder.fVS, SkSL::Program::kVertex_Kind, flipY,
Stephen Whitee2641312019-08-29 15:10:50 -0400320 &vertInputs);
Stephen White20c626a2019-10-15 13:35:37 -0400321 auto fsModule = builder.createShaderModule(builder.fFS, SkSL::Program::kFragment_Kind, flipY,
Stephen Whitee2641312019-08-29 15:10:50 -0400322 &fragInputs);
Greg Danield59a91d2020-04-23 13:22:47 -0400323 GrSPIRVUniformHandler::UniformInfoArray& uniforms = builder.fUniformHandler.fUniforms;
Stephen White40c47e12019-11-01 13:13:03 -0400324 uint32_t uniformBufferSize = builder.fUniformHandler.fCurrentUBOOffset;
325 sk_sp<GrDawnProgram> result(new GrDawnProgram(uniforms, uniformBufferSize));
Stephen Whitebb6bed12019-08-02 09:57:55 -0400326 result->fGeometryProcessor = std::move(builder.fGeometryProcessor);
327 result->fXferProcessor = std::move(builder.fXferProcessor);
328 result->fFragmentProcessors = std::move(builder.fFragmentProcessors);
Stephen White3d2dd262020-04-27 15:43:59 -0400329 std::vector<wgpu::BindGroupLayoutEntry> uniformLayoutEntries;
Stephen Whitedd78efd2019-10-23 15:00:20 -0400330 if (0 != uniformBufferSize) {
Stephen White3d2dd262020-04-27 15:43:59 -0400331 uniformLayoutEntries.push_back({ GrSPIRVUniformHandler::kUniformBinding,
332 wgpu::ShaderStage::Vertex | wgpu::ShaderStage::Fragment,
Stephen White768e91f2020-06-22 13:45:20 -0400333 wgpu::BindingType::UniformBuffer });
Stephen White170d9902019-08-15 16:48:24 -0400334 }
Stephen White7cb52cb2019-11-12 10:40:27 -0500335 wgpu::BindGroupLayoutDescriptor uniformBindGroupLayoutDesc;
Stephen White3d2dd262020-04-27 15:43:59 -0400336 uniformBindGroupLayoutDesc.entryCount = uniformLayoutEntries.size();
337 uniformBindGroupLayoutDesc.entries = uniformLayoutEntries.data();
Stephen White768e91f2020-06-22 13:45:20 -0400338 result->fBindGroupLayouts.push_back(
339 gpu->device().CreateBindGroupLayout(&uniformBindGroupLayoutDesc));
Stephen White7cb52cb2019-11-12 10:40:27 -0500340 uint32_t binding = 0;
Stephen White3d2dd262020-04-27 15:43:59 -0400341 std::vector<wgpu::BindGroupLayoutEntry> textureLayoutEntries;
Stephen White768e91f2020-06-22 13:45:20 -0400342 int textureCount = builder.fUniformHandler.fSamplers.count();
343 if (textureCount > 0) {
344 for (int i = 0; i < textureCount; ++i) {
345 textureLayoutEntries.push_back({ binding++, wgpu::ShaderStage::Fragment,
346 wgpu::BindingType::Sampler });
347 textureLayoutEntries.push_back({ binding++, wgpu::ShaderStage::Fragment,
348 wgpu::BindingType::SampledTexture });
349 }
350 wgpu::BindGroupLayoutDescriptor textureBindGroupLayoutDesc;
351 textureBindGroupLayoutDesc.entryCount = textureLayoutEntries.size();
352 textureBindGroupLayoutDesc.entries = textureLayoutEntries.data();
353 result->fBindGroupLayouts.push_back(
354 gpu->device().CreateBindGroupLayout(&textureBindGroupLayoutDesc));
Stephen White170d9902019-08-15 16:48:24 -0400355 }
Stephen White3cc8d4f2019-10-30 09:56:23 -0400356 wgpu::PipelineLayoutDescriptor pipelineLayoutDesc;
Stephen White768e91f2020-06-22 13:45:20 -0400357 pipelineLayoutDesc.bindGroupLayoutCount = result->fBindGroupLayouts.size();
358 pipelineLayoutDesc.bindGroupLayouts = result->fBindGroupLayouts.data();
Stephen Whitee2641312019-08-29 15:10:50 -0400359 auto pipelineLayout = gpu->device().CreatePipelineLayout(&pipelineLayoutDesc);
Stephen Whitebb6bed12019-08-02 09:57:55 -0400360 result->fBuiltinUniformHandles = builder.fUniformHandles;
Stephen White729c78d2019-10-14 12:42:59 -0400361 const GrPipeline& pipeline = programInfo.pipeline();
Stephen Whitee2641312019-08-29 15:10:50 -0400362 auto colorState = create_color_state(gpu, pipeline, colorFormat);
Stephen White3cc8d4f2019-10-30 09:56:23 -0400363 wgpu::DepthStencilStateDescriptor depthStencilState;
Robert Phillipsa87c5292019-11-12 10:12:42 -0500364
365#ifdef SK_DEBUG
Stephen Whitef813ef72019-08-09 12:28:37 -0400366 if (pipeline.isStencilEnabled()) {
Robert Phillipsa87c5292019-11-12 10:12:42 -0500367 SkASSERT(renderTarget->renderTargetPriv().numStencilBits() == 8);
Stephen Whitef813ef72019-08-09 12:28:37 -0400368 }
Robert Phillipsa87c5292019-11-12 10:12:42 -0500369#endif
370 depthStencilState = create_depth_stencil_state(programInfo, depthStencilFormat);
Stephen Whitee2641312019-08-29 15:10:50 -0400371
Sean Gilhuly6c536a52019-11-11 11:13:03 -0500372 std::vector<wgpu::VertexBufferLayoutDescriptor> inputs;
Stephen Whitee2641312019-08-29 15:10:50 -0400373
Stephen White3cc8d4f2019-10-30 09:56:23 -0400374 std::vector<wgpu::VertexAttributeDescriptor> vertexAttributes;
Stephen White729c78d2019-10-14 12:42:59 -0400375 const GrPrimitiveProcessor& primProc = programInfo.primProc();
Stephen White768e91f2020-06-22 13:45:20 -0400376 int i = 0;
Stephen Whitee2641312019-08-29 15:10:50 -0400377 if (primProc.numVertexAttributes() > 0) {
378 size_t offset = 0;
Stephen Whitee2641312019-08-29 15:10:50 -0400379 for (const auto& attrib : primProc.vertexAttributes()) {
Stephen White3cc8d4f2019-10-30 09:56:23 -0400380 wgpu::VertexAttributeDescriptor attribute;
Stephen Whitee2641312019-08-29 15:10:50 -0400381 attribute.shaderLocation = i;
382 attribute.offset = offset;
383 attribute.format = to_dawn_vertex_format(attrib.cpuType());
384 vertexAttributes.push_back(attribute);
385 offset += attrib.sizeAlign4();
386 i++;
387 }
Sean Gilhuly6c536a52019-11-11 11:13:03 -0500388 wgpu::VertexBufferLayoutDescriptor input;
389 input.arrayStride = offset;
Stephen White3cc8d4f2019-10-30 09:56:23 -0400390 input.stepMode = wgpu::InputStepMode::Vertex;
Stephen Whitee2641312019-08-29 15:10:50 -0400391 input.attributeCount = vertexAttributes.size();
392 input.attributes = &vertexAttributes.front();
393 inputs.push_back(input);
394 }
Stephen White3cc8d4f2019-10-30 09:56:23 -0400395 std::vector<wgpu::VertexAttributeDescriptor> instanceAttributes;
Stephen Whitee2641312019-08-29 15:10:50 -0400396 if (primProc.numInstanceAttributes() > 0) {
397 size_t offset = 0;
Stephen Whitee2641312019-08-29 15:10:50 -0400398 for (const auto& attrib : primProc.instanceAttributes()) {
Stephen White3cc8d4f2019-10-30 09:56:23 -0400399 wgpu::VertexAttributeDescriptor attribute;
Stephen Whitee2641312019-08-29 15:10:50 -0400400 attribute.shaderLocation = i;
401 attribute.offset = offset;
402 attribute.format = to_dawn_vertex_format(attrib.cpuType());
403 instanceAttributes.push_back(attribute);
404 offset += attrib.sizeAlign4();
405 i++;
406 }
Sean Gilhuly6c536a52019-11-11 11:13:03 -0500407 wgpu::VertexBufferLayoutDescriptor input;
408 input.arrayStride = offset;
Stephen White3cc8d4f2019-10-30 09:56:23 -0400409 input.stepMode = wgpu::InputStepMode::Instance;
Stephen Whitee2641312019-08-29 15:10:50 -0400410 input.attributeCount = instanceAttributes.size();
411 input.attributes = &instanceAttributes.front();
412 inputs.push_back(input);
413 }
Sean Gilhuly6c536a52019-11-11 11:13:03 -0500414 wgpu::VertexStateDescriptor vertexState;
415 vertexState.indexFormat = wgpu::IndexFormat::Uint16;
416 vertexState.vertexBufferCount = inputs.size();
417 vertexState.vertexBuffers = &inputs.front();
Stephen Whitee2641312019-08-29 15:10:50 -0400418
Stephen White3cc8d4f2019-10-30 09:56:23 -0400419 wgpu::ProgrammableStageDescriptor vsDesc;
Stephen Whitee2641312019-08-29 15:10:50 -0400420 vsDesc.module = vsModule;
421 vsDesc.entryPoint = "main";
422
Stephen White3cc8d4f2019-10-30 09:56:23 -0400423 wgpu::ProgrammableStageDescriptor fsDesc;
Stephen Whitee2641312019-08-29 15:10:50 -0400424 fsDesc.module = fsModule;
425 fsDesc.entryPoint = "main";
426
Stephen White3cc8d4f2019-10-30 09:56:23 -0400427 wgpu::RenderPipelineDescriptor rpDesc;
Stephen Whitee2641312019-08-29 15:10:50 -0400428 rpDesc.layout = pipelineLayout;
Stephen White20c626a2019-10-15 13:35:37 -0400429 rpDesc.vertexStage = vsDesc;
Stephen Whitee2641312019-08-29 15:10:50 -0400430 rpDesc.fragmentStage = &fsDesc;
Sean Gilhuly6c536a52019-11-11 11:13:03 -0500431 rpDesc.vertexState = &vertexState;
Robert Phillipsfcaae482019-11-07 10:17:03 -0500432 rpDesc.primitiveTopology = to_dawn_primitive_topology(programInfo.primitiveType());
Stephen Whitee2641312019-08-29 15:10:50 -0400433 if (hasDepthStencil) {
434 rpDesc.depthStencilState = &depthStencilState;
435 }
436 rpDesc.colorStateCount = 1;
Stephen White20c626a2019-10-15 13:35:37 -0400437 rpDesc.colorStates = &colorState;
Stephen Whitee2641312019-08-29 15:10:50 -0400438 result->fRenderPipeline = gpu->device().CreateRenderPipeline(&rpDesc);
Stephen Whitebb6bed12019-08-02 09:57:55 -0400439 return result;
440}
441
442GrDawnProgramBuilder::GrDawnProgramBuilder(GrDawnGpu* gpu,
443 GrRenderTarget* renderTarget,
Stephen White729c78d2019-10-14 12:42:59 -0400444 const GrProgramInfo& programInfo,
Stephen Whitebb6bed12019-08-02 09:57:55 -0400445 GrProgramDesc* desc)
Stephen White511af2e2020-02-07 11:04:58 -0500446 : INHERITED(renderTarget, *desc, programInfo)
Stephen Whitebb6bed12019-08-02 09:57:55 -0400447 , fGpu(gpu)
448 , fVaryingHandler(this)
449 , fUniformHandler(this) {
450}
451
Stephen White3cc8d4f2019-10-30 09:56:23 -0400452wgpu::ShaderModule GrDawnProgramBuilder::createShaderModule(const GrGLSLShaderBuilder& builder,
Stephen Whitebb6bed12019-08-02 09:57:55 -0400453 SkSL::Program::Kind kind,
Stephen White20c626a2019-10-15 13:35:37 -0400454 bool flipY,
Stephen Whitebb6bed12019-08-02 09:57:55 -0400455 SkSL::Program::Inputs* inputs) {
Stephen White3cc8d4f2019-10-30 09:56:23 -0400456 wgpu::Device device = fGpu->device();
Stephen Whitebb6bed12019-08-02 09:57:55 -0400457 SkString source(builder.fCompilerString.c_str());
458
459#if 0
460 SkSL::String sksl = GrShaderUtils::PrettyPrint(builder.fCompilerString);
461 printf("converting program:\n%s\n", sksl.c_str());
462#endif
463
Stephen White40c47e12019-11-01 13:13:03 -0400464 SkSL::String spirvSource = sksl_to_spirv(fGpu, source.c_str(), kind, flipY,
465 fUniformHandler.getRTHeightOffset(), inputs);
466 if (inputs->fRTHeight) {
467 this->addRTHeightUniform(SKSL_RTHEIGHT_NAME);
468 }
Stephen Whitebb6bed12019-08-02 09:57:55 -0400469
Stephen White3d2dd262020-04-27 15:43:59 -0400470 wgpu::ShaderModuleSPIRVDescriptor desc;
Stephen Whitebb6bed12019-08-02 09:57:55 -0400471 desc.codeSize = spirvSource.size() / 4;
472 desc.code = reinterpret_cast<const uint32_t*>(spirvSource.c_str());
473
Stephen White3d2dd262020-04-27 15:43:59 -0400474 wgpu::ShaderModuleDescriptor smDesc;
475 smDesc.nextInChain = &desc;
476
477 return device.CreateShaderModule(&smDesc);
Stephen Whitebb6bed12019-08-02 09:57:55 -0400478};
479
480const GrCaps* GrDawnProgramBuilder::caps() const {
481 return fGpu->caps();
482}
483
484void GrDawnProgram::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin) {
485 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
486 if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
487 fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
488 fDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height()));
489 }
490
491 // set RT adjustment
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400492 SkISize dimensions = rt->dimensions();
Stephen Whitebb6bed12019-08-02 09:57:55 -0400493 SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
494 if (fRenderTargetState.fRenderTargetOrigin != origin ||
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400495 fRenderTargetState.fRenderTargetSize != dimensions) {
496 fRenderTargetState.fRenderTargetSize = dimensions;
Stephen Whitebb6bed12019-08-02 09:57:55 -0400497 fRenderTargetState.fRenderTargetOrigin = origin;
498
499 float rtAdjustmentVec[4];
500 fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
501 fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
502 }
503}
504
Brian Salomonccb61422020-01-09 10:46:36 -0500505static void set_texture(GrDawnGpu* gpu, GrSamplerState state, GrTexture* texture,
Stephen White3d2dd262020-04-27 15:43:59 -0400506 std::vector<wgpu::BindGroupEntry>* bindings, int* binding) {
Stephen Whiteb7eaedc2019-08-21 09:48:05 -0400507 // FIXME: could probably cache samplers in GrDawnProgram
Stephen White3cc8d4f2019-10-30 09:56:23 -0400508 wgpu::Sampler sampler = gpu->getOrCreateSampler(state);
Stephen White3d2dd262020-04-27 15:43:59 -0400509 bindings->push_back(make_bind_group_entry((*binding)++, sampler));
Stephen Whiteb7eaedc2019-08-21 09:48:05 -0400510 GrDawnTexture* tex = static_cast<GrDawnTexture*>(texture);
Stephen White3cc8d4f2019-10-30 09:56:23 -0400511 wgpu::TextureView textureView = tex->textureView();
Stephen White3d2dd262020-04-27 15:43:59 -0400512 bindings->push_back(make_bind_group_entry((*binding)++, textureView));
Stephen Whiteb7eaedc2019-08-21 09:48:05 -0400513}
514
Stephen White7cb52cb2019-11-12 10:40:27 -0500515wgpu::BindGroup GrDawnProgram::setUniformData(GrDawnGpu* gpu, const GrRenderTarget* renderTarget,
516 const GrProgramInfo& programInfo) {
Stephen White3d2dd262020-04-27 15:43:59 -0400517 std::vector<wgpu::BindGroupEntry> bindings;
Stephen Whitedd78efd2019-10-23 15:00:20 -0400518 GrDawnRingBuffer::Slice slice;
519 uint32_t uniformBufferSize = fDataManager.uniformBufferSize();
520 if (0 != uniformBufferSize) {
521 slice = gpu->allocateUniformRingBufferSlice(uniformBufferSize);
Stephen White3d2dd262020-04-27 15:43:59 -0400522 bindings.push_back(make_bind_group_entry(GrSPIRVUniformHandler::kUniformBinding,
Stephen Whitedd78efd2019-10-23 15:00:20 -0400523 slice.fBuffer, slice.fOffset,
524 uniformBufferSize));
Stephen Whiteb7eaedc2019-08-21 09:48:05 -0400525 }
Stephen White729c78d2019-10-14 12:42:59 -0400526 this->setRenderTargetState(renderTarget, programInfo.origin());
527 const GrPipeline& pipeline = programInfo.pipeline();
528 const GrPrimitiveProcessor& primProc = programInfo.primProc();
Brian Osman609f1592020-07-01 15:14:39 -0400529 fGeometryProcessor->setData(fDataManager, primProc);
Brian Salomon61a70fb2020-07-08 19:02:54 -0400530
531 for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) {
532 auto& pipelineFP = programInfo.pipeline().getFragmentProcessor(i);
533 auto& baseGLSLFP = *fFragmentProcessors[i];
534 for (auto [fp, glslFP] : GrGLSLFragmentProcessor::ParallelRange(pipelineFP, baseGLSLFP)) {
535 glslFP.setData(fDataManager, fp);
536 }
Stephen Whitebb6bed12019-08-02 09:57:55 -0400537 }
Brian Salomon61a70fb2020-07-08 19:02:54 -0400538
Stephen Whiteb7eaedc2019-08-21 09:48:05 -0400539 SkIPoint offset;
540 GrTexture* dstTexture = pipeline.peekDstTexture(&offset);
541 fXferProcessor->setData(fDataManager, pipeline.getXferProcessor(), dstTexture, offset);
Stephen White8eda4992020-03-17 11:44:48 -0400542 if (0 != uniformBufferSize) {
543 fDataManager.uploadUniformBuffers(slice.fData);
544 }
Stephen White3cc8d4f2019-10-30 09:56:23 -0400545 wgpu::BindGroupDescriptor descriptor;
Stephen White7cb52cb2019-11-12 10:40:27 -0500546 descriptor.layout = fBindGroupLayouts[0];
Stephen White3d2dd262020-04-27 15:43:59 -0400547 descriptor.entryCount = bindings.size();
548 descriptor.entries = bindings.data();
Stephen White7cb52cb2019-11-12 10:40:27 -0500549 return gpu->device().CreateBindGroup(&descriptor);
550}
551
552wgpu::BindGroup GrDawnProgram::setTextures(GrDawnGpu* gpu,
Stephen White6e8ceee2020-02-25 16:25:43 -0500553 const GrPrimitiveProcessor& primProc,
554 const GrPipeline& pipeline,
Michael Ludwigfcdd0612019-11-25 08:34:31 -0500555 const GrSurfaceProxy* const primProcTextures[]) {
Stephen White768e91f2020-06-22 13:45:20 -0400556 if (fBindGroupLayouts.size() < 2) {
557 return nullptr;
558 }
Stephen White3d2dd262020-04-27 15:43:59 -0400559 std::vector<wgpu::BindGroupEntry> bindings;
Stephen White7cb52cb2019-11-12 10:40:27 -0500560 int binding = 0;
Stephen White7cb52cb2019-11-12 10:40:27 -0500561 if (primProcTextures) {
562 for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
Michael Ludwigfcdd0612019-11-25 08:34:31 -0500563 SkASSERT(primProcTextures[i]->asTextureProxy());
Stephen White7cb52cb2019-11-12 10:40:27 -0500564 auto& sampler = primProc.textureSampler(i);
565 set_texture(gpu, sampler.samplerState(), primProcTextures[i]->peekTexture(), &bindings,
566 &binding);
567 }
568 }
Brian Salomon61a70fb2020-07-08 19:02:54 -0400569
570 for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) {
571 for (auto& fp : GrFragmentProcessor::FPCRange(pipeline.getFragmentProcessor(i))) {
572 for (int s = 0; s < fp.numTextureSamplers(); ++s) {
573 const auto& sampler = fp.textureSampler(s);
574 set_texture(gpu, sampler.samplerState(), sampler.peekTexture(), &bindings,
575 &binding);
576 }
Stephen White7cb52cb2019-11-12 10:40:27 -0500577 }
Stephen White7cb52cb2019-11-12 10:40:27 -0500578 }
Brian Salomon61a70fb2020-07-08 19:02:54 -0400579
Stephen White7cb52cb2019-11-12 10:40:27 -0500580 SkIPoint offset;
581 if (GrTexture* dstTexture = pipeline.peekDstTexture(&offset)) {
Brian Salomonccb61422020-01-09 10:46:36 -0500582 set_texture(gpu, GrSamplerState::Filter::kNearest, dstTexture, &bindings, &binding);
Stephen White7cb52cb2019-11-12 10:40:27 -0500583 }
584 wgpu::BindGroupDescriptor descriptor;
585 descriptor.layout = fBindGroupLayouts[1];
Stephen White3d2dd262020-04-27 15:43:59 -0400586 descriptor.entryCount = bindings.size();
587 descriptor.entries = bindings.data();
Stephen Whiteb7eaedc2019-08-21 09:48:05 -0400588 return gpu->device().CreateBindGroup(&descriptor);
Stephen Whitebb6bed12019-08-02 09:57:55 -0400589}