blob: b72ee2644b595122e948329a0db8a3a99a08960c [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"
14#include "src/sksl/SkSLCompiler.h"
15
Stephen Whitebb6bed12019-08-02 09:57:55 -040016static SkSL::String sksl_to_spirv(const GrDawnGpu* gpu, const char* shaderString,
17 SkSL::Program::Kind kind, SkSL::Program::Inputs* inputs) {
18 SkSL::Program::Settings settings;
19 std::unique_ptr<SkSL::Program> program = gpu->shaderCompiler()->convertProgram(
20 kind,
21 shaderString,
22 settings);
23 if (!program) {
24 SkDebugf("SkSL error:\n%s\n", gpu->shaderCompiler()->errorText().c_str());
25 SkASSERT(false);
26 return "";
27 }
28 *inputs = program->fInputs;
29 SkSL::String code;
30 if (!gpu->shaderCompiler()->toSPIRV(*program, &code)) {
31 return "";
32 }
33 return code;
34}
35
36static dawn::BlendFactor to_dawn_blend_factor(GrBlendCoeff coeff) {
37 switch (coeff) {
38 case kZero_GrBlendCoeff:
39 return dawn::BlendFactor::Zero;
40 case kOne_GrBlendCoeff:
41 return dawn::BlendFactor::One;
42 case kSC_GrBlendCoeff:
43 return dawn::BlendFactor::SrcColor;
44 case kISC_GrBlendCoeff:
45 return dawn::BlendFactor::OneMinusSrcColor;
46 case kDC_GrBlendCoeff:
47 return dawn::BlendFactor::DstColor;
48 case kIDC_GrBlendCoeff:
49 return dawn::BlendFactor::OneMinusDstColor;
50 case kSA_GrBlendCoeff:
51 return dawn::BlendFactor::SrcAlpha;
52 case kISA_GrBlendCoeff:
53 return dawn::BlendFactor::OneMinusSrcAlpha;
54 case kDA_GrBlendCoeff:
55 return dawn::BlendFactor::DstAlpha;
56 case kIDA_GrBlendCoeff:
57 return dawn::BlendFactor::OneMinusDstAlpha;
58 case kConstC_GrBlendCoeff:
59 return dawn::BlendFactor::BlendColor;
60 case kIConstC_GrBlendCoeff:
61 return dawn::BlendFactor::OneMinusBlendColor;
62 case kConstA_GrBlendCoeff:
63 case kIConstA_GrBlendCoeff:
64 case kS2C_GrBlendCoeff:
65 case kIS2C_GrBlendCoeff:
66 case kS2A_GrBlendCoeff:
67 case kIS2A_GrBlendCoeff:
68 default:
69 SkASSERT(!"unsupported blend coefficient");
70 return dawn::BlendFactor::One;
71 }
72}
73
Stephen Whitef813ef72019-08-09 12:28:37 -040074static dawn::BlendFactor to_dawn_blend_factor_for_alpha(GrBlendCoeff coeff) {
75 switch (coeff) {
76 // Force all srcColor used in alpha slot to alpha version.
77 case kSC_GrBlendCoeff:
78 return dawn::BlendFactor::SrcAlpha;
79 case kISC_GrBlendCoeff:
80 return dawn::BlendFactor::OneMinusSrcAlpha;
81 case kDC_GrBlendCoeff:
82 return dawn::BlendFactor::DstAlpha;
83 case kIDC_GrBlendCoeff:
84 return dawn::BlendFactor::OneMinusDstAlpha;
85 default:
86 return to_dawn_blend_factor(coeff);
87 }
88}
89
Stephen Whitebb6bed12019-08-02 09:57:55 -040090static dawn::BlendOperation to_dawn_blend_operation(GrBlendEquation equation) {
91 switch (equation) {
92 case kAdd_GrBlendEquation:
93 return dawn::BlendOperation::Add;
94 case kSubtract_GrBlendEquation:
95 return dawn::BlendOperation::Subtract;
Stephen Whitef813ef72019-08-09 12:28:37 -040096 case kReverseSubtract_GrBlendEquation:
97 return dawn::BlendOperation::ReverseSubtract;
Stephen Whitebb6bed12019-08-02 09:57:55 -040098 default:
99 SkASSERT(!"unsupported blend equation");
100 return dawn::BlendOperation::Add;
101 }
102}
103
Stephen Whitef813ef72019-08-09 12:28:37 -0400104static dawn::CompareFunction to_dawn_compare_function(GrStencilTest test) {
105 switch (test) {
106 case GrStencilTest::kAlways:
107 return dawn::CompareFunction::Always;
108 case GrStencilTest::kNever:
109 return dawn::CompareFunction::Never;
110 case GrStencilTest::kGreater:
111 return dawn::CompareFunction::Greater;
112 case GrStencilTest::kGEqual:
113 return dawn::CompareFunction::GreaterEqual;
114 case GrStencilTest::kLess:
115 return dawn::CompareFunction::Less;
116 case GrStencilTest::kLEqual:
117 return dawn::CompareFunction::LessEqual;
118 case GrStencilTest::kEqual:
119 return dawn::CompareFunction::Equal;
120 case GrStencilTest::kNotEqual:
121 return dawn::CompareFunction::NotEqual;
122 default:
123 SkASSERT(!"unsupported stencil test");
124 return dawn::CompareFunction::Always;
125 }
126}
127
128static dawn::StencilOperation to_dawn_stencil_operation(GrStencilOp op) {
129 switch (op) {
130 case GrStencilOp::kKeep:
131 return dawn::StencilOperation::Keep;
132 case GrStencilOp::kZero:
133 return dawn::StencilOperation::Zero;
134 case GrStencilOp::kReplace:
135 return dawn::StencilOperation::Replace;
136 case GrStencilOp::kInvert:
137 return dawn::StencilOperation::Invert;
138 case GrStencilOp::kIncClamp:
139 return dawn::StencilOperation::IncrementClamp;
140 case GrStencilOp::kDecClamp:
141 return dawn::StencilOperation::DecrementClamp;
142 case GrStencilOp::kIncWrap:
143 return dawn::StencilOperation::IncrementWrap;
144 case GrStencilOp::kDecWrap:
145 return dawn::StencilOperation::DecrementWrap;
146 default:
147 SkASSERT(!"unsupported stencil function");
148 return dawn::StencilOperation::Keep;
149 }
150}
151
Stephen Whitebb6bed12019-08-02 09:57:55 -0400152static dawn::ColorStateDescriptor create_color_state(const GrDawnGpu* gpu,
153 const GrPipeline& pipeline,
154 dawn::TextureFormat colorFormat) {
155 GrXferProcessor::BlendInfo blendInfo = pipeline.getXferProcessor().getBlendInfo();
156 GrBlendEquation equation = blendInfo.fEquation;
157 GrBlendCoeff srcCoeff = blendInfo.fSrcBlend;
158 GrBlendCoeff dstCoeff = blendInfo.fDstBlend;
159
160 dawn::BlendFactor srcFactor = to_dawn_blend_factor(srcCoeff);
161 dawn::BlendFactor dstFactor = to_dawn_blend_factor(dstCoeff);
Stephen Whitef813ef72019-08-09 12:28:37 -0400162 dawn::BlendFactor srcFactorAlpha = to_dawn_blend_factor_for_alpha(srcCoeff);
163 dawn::BlendFactor dstFactorAlpha = to_dawn_blend_factor_for_alpha(dstCoeff);
Stephen Whitebb6bed12019-08-02 09:57:55 -0400164 dawn::BlendOperation operation = to_dawn_blend_operation(equation);
165 auto mask = blendInfo.fWriteColor ? dawn::ColorWriteMask::All : dawn::ColorWriteMask::None;
166
167 dawn::BlendDescriptor colorDesc = {operation, srcFactor, dstFactor};
Stephen Whitef813ef72019-08-09 12:28:37 -0400168 dawn::BlendDescriptor alphaDesc = {operation, srcFactorAlpha, dstFactorAlpha};
Stephen Whitebb6bed12019-08-02 09:57:55 -0400169
170 dawn::ColorStateDescriptor descriptor;
171 descriptor.format = colorFormat;
172 descriptor.alphaBlend = alphaDesc;
173 descriptor.colorBlend = colorDesc;
174 descriptor.nextInChain = nullptr;
175 descriptor.writeMask = mask;
176
177 return descriptor;
178}
179
Stephen Whitef813ef72019-08-09 12:28:37 -0400180static dawn::StencilStateFaceDescriptor to_stencil_state_face(const GrStencilSettings::Face& face) {
181 dawn::StencilStateFaceDescriptor desc;
182 desc.compare = to_dawn_compare_function(face.fTest);
183 desc.failOp = desc.depthFailOp = to_dawn_stencil_operation(face.fFailOp);
184 desc.passOp = to_dawn_stencil_operation(face.fPassOp);
185 return desc;
186}
187
188static dawn::DepthStencilStateDescriptor create_depth_stencil_state(
189 const GrStencilSettings& stencilSettings,
190 dawn::TextureFormat depthStencilFormat,
191 GrSurfaceOrigin origin) {
192 dawn::DepthStencilStateDescriptor state;
193 state.format = depthStencilFormat;
194 state.depthWriteEnabled = false;
195 state.depthCompare = dawn::CompareFunction::Always;
196 if (stencilSettings.isDisabled()) {
197 dawn::StencilStateFaceDescriptor stencilFace;
198 stencilFace.compare = dawn::CompareFunction::Always;
199 stencilFace.failOp = dawn::StencilOperation::Keep;
200 stencilFace.depthFailOp = dawn::StencilOperation::Keep;
201 stencilFace.passOp = dawn::StencilOperation::Keep;
202 state.stencilReadMask = state.stencilWriteMask = 0x0;
203 state.stencilBack = state.stencilFront = stencilFace;
204 } else {
205 const GrStencilSettings::Face& front = stencilSettings.front(origin);
206 state.stencilReadMask = front.fTestMask;
207 state.stencilWriteMask = front.fWriteMask;
208 state.stencilFront = to_stencil_state_face(stencilSettings.front(origin));
209 if (stencilSettings.isTwoSided()) {
210 state.stencilBack = to_stencil_state_face(stencilSettings.back(origin));
211 } else {
212 state.stencilBack = state.stencilFront;
213 }
214 }
215 return state;
216}
217
Stephen Whitebb6bed12019-08-02 09:57:55 -0400218static dawn::BindGroupBinding make_bind_group_binding(uint32_t binding, const dawn::Buffer& buffer,
219 uint32_t offset, uint32_t size, const
220 dawn::Sampler& sampler,
221 const dawn::TextureView& textureView) {
222 dawn::BindGroupBinding result;
223 result.binding = binding;
224 result.buffer = buffer;
225 result.offset = offset;
226 result.size = size;
227 result.sampler = sampler;
228 result.textureView = textureView;
229 return result;
230}
231
232static dawn::BindGroupBinding make_bind_group_binding(uint32_t binding, const dawn::Buffer& buffer,
233 uint32_t offset, uint32_t size) {
234 return make_bind_group_binding(binding, buffer, offset, size, nullptr, nullptr);
235}
236
237sk_sp<GrDawnProgram> GrDawnProgramBuilder::Build(GrDawnGpu* gpu,
238 GrRenderTarget* renderTarget,
239 GrSurfaceOrigin origin,
240 const GrPipeline& pipeline,
241 const GrPrimitiveProcessor& primProc,
242 const GrTextureProxy* const primProcProxies[],
243 dawn::TextureFormat colorFormat,
Stephen Whitef813ef72019-08-09 12:28:37 -0400244 bool hasDepthStencil,
245 dawn::TextureFormat depthStencilFormat,
Stephen Whitebb6bed12019-08-02 09:57:55 -0400246 GrProgramDesc* desc) {
247 GrDawnProgramBuilder builder(gpu, renderTarget, origin, primProc, primProcProxies, pipeline,
248 desc);
249 if (!builder.emitAndInstallProcs()) {
250 return nullptr;
251 }
252
253 builder.fVS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
254 builder.fFS.extensions().appendf("#extension GL_ARB_separate_shader_objects : enable\n");
255 builder.fVS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
256 builder.fFS.extensions().appendf("#extension GL_ARB_shading_language_420pack : enable\n");
257
258 builder.finalizeShaders();
259
260 SkSL::Program::Inputs vertInputs, fragInputs;
261 GrDawnUniformHandler::UniformInfoArray& uniforms = builder.fUniformHandler.fUniforms;
262 uint32_t geometryUniformSize = builder.fUniformHandler.fCurrentGeometryUBOOffset;
263 uint32_t fragmentUniformSize = builder.fUniformHandler.fCurrentFragmentUBOOffset;
264 sk_sp<GrDawnProgram> result(
265 new GrDawnProgram(uniforms, geometryUniformSize, fragmentUniformSize));
266 result->fVSModule = builder.createShaderModule(builder.fVS, SkSL::Program::kVertex_Kind,
267 &vertInputs);
268 result->fFSModule = builder.createShaderModule(builder.fFS, SkSL::Program::kFragment_Kind,
269 &fragInputs);
270 result->fGeometryProcessor = std::move(builder.fGeometryProcessor);
271 result->fXferProcessor = std::move(builder.fXferProcessor);
272 result->fFragmentProcessors = std::move(builder.fFragmentProcessors);
273 result->fFragmentProcessorCnt = builder.fFragmentProcessorCnt;
274 std::vector<dawn::BindGroupLayoutBinding> layoutBindings;
275 std::vector<dawn::BindGroupBinding> bindings;
276
277 if (0 != geometryUniformSize) {
278 dawn::BufferDescriptor desc;
279 desc.usage = dawn::BufferUsageBit::Uniform | dawn::BufferUsageBit::CopyDst;
280 desc.size = geometryUniformSize;
281 result->fGeometryUniformBuffer = gpu->device().CreateBuffer(&desc);
282 bindings.push_back(make_bind_group_binding(0, result->fGeometryUniformBuffer, 0,
283 geometryUniformSize));
284 layoutBindings.push_back({ 0, dawn::ShaderStageBit::Vertex,
285 dawn::BindingType::UniformBuffer});
286 }
287 if (0 != fragmentUniformSize) {
288 dawn::BufferDescriptor desc;
289 desc.usage = dawn::BufferUsageBit::Uniform | dawn::BufferUsageBit::CopyDst;
290 desc.size = fragmentUniformSize;
291 result->fFragmentUniformBuffer = gpu->device().CreateBuffer(&desc);
292 bindings.push_back(make_bind_group_binding(1, result->fFragmentUniformBuffer, 0,
293 fragmentUniformSize));
294 layoutBindings.push_back({ 1, dawn::ShaderStageBit::Fragment,
295 dawn::BindingType::UniformBuffer});
296 }
297 dawn::BindGroupLayoutDescriptor bindGroupLayoutDesc;
298 bindGroupLayoutDesc.bindingCount = layoutBindings.size();
299 bindGroupLayoutDesc.bindings = layoutBindings.data();
300 auto bindGroupLayout = gpu->device().CreateBindGroupLayout(&bindGroupLayoutDesc);
301 dawn::BindGroupDescriptor descriptor;
302 descriptor.layout = bindGroupLayout;
303 descriptor.bindingCount = bindings.size();
304 descriptor.bindings = bindings.data();
305 result->fUniformBindGroup = gpu->device().CreateBindGroup(&descriptor);
306 dawn::PipelineLayoutDescriptor pipelineLayoutDesc;
307 pipelineLayoutDesc.bindGroupLayoutCount = 1;
308 pipelineLayoutDesc.bindGroupLayouts = &bindGroupLayout;
309 result->fPipelineLayout = gpu->device().CreatePipelineLayout(&pipelineLayoutDesc);
310 result->fBuiltinUniformHandles = builder.fUniformHandles;
311 result->fColorState = create_color_state(gpu, pipeline, colorFormat);
Stephen Whitef813ef72019-08-09 12:28:37 -0400312 GrStencilSettings stencil;
313 if (pipeline.isStencilEnabled()) {
314 int numStencilBits = renderTarget->renderTargetPriv().numStencilBits();
315 stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(), numStencilBits);
316 }
317 result->fDepthStencilState = create_depth_stencil_state(stencil, depthStencilFormat, origin);
Stephen Whitebb6bed12019-08-02 09:57:55 -0400318 return result;
319}
320
321GrDawnProgramBuilder::GrDawnProgramBuilder(GrDawnGpu* gpu,
322 GrRenderTarget* renderTarget,
323 GrSurfaceOrigin origin,
324 const GrPrimitiveProcessor& primProc,
325 const GrTextureProxy* const primProcProxies[],
326 const GrPipeline& pipeline,
327 GrProgramDesc* desc)
328 : INHERITED(renderTarget, origin, primProc, primProcProxies, pipeline, desc)
329 , fGpu(gpu)
330 , fVaryingHandler(this)
331 , fUniformHandler(this) {
332}
333
334dawn::ShaderModule GrDawnProgramBuilder::createShaderModule(const GrGLSLShaderBuilder& builder,
335 SkSL::Program::Kind kind,
336 SkSL::Program::Inputs* inputs) {
337 dawn::Device device = fGpu->device();
338 SkString source(builder.fCompilerString.c_str());
339
340#if 0
341 SkSL::String sksl = GrShaderUtils::PrettyPrint(builder.fCompilerString);
342 printf("converting program:\n%s\n", sksl.c_str());
343#endif
344
345 SkSL::String spirvSource = sksl_to_spirv(fGpu, source.c_str(), kind, inputs);
346
347 dawn::ShaderModuleDescriptor desc;
348 desc.codeSize = spirvSource.size() / 4;
349 desc.code = reinterpret_cast<const uint32_t*>(spirvSource.c_str());
350
351 return device.CreateShaderModule(&desc);
352};
353
354const GrCaps* GrDawnProgramBuilder::caps() const {
355 return fGpu->caps();
356}
357
358void GrDawnProgram::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin) {
359 // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
360 if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
361 fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
362 fDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height()));
363 }
364
365 // set RT adjustment
366 SkISize size;
367 size.set(rt->width(), rt->height());
368 SkASSERT(fBuiltinUniformHandles.fRTAdjustmentUni.isValid());
369 if (fRenderTargetState.fRenderTargetOrigin != origin ||
370 fRenderTargetState.fRenderTargetSize != size) {
371 fRenderTargetState.fRenderTargetSize = size;
372 fRenderTargetState.fRenderTargetOrigin = origin;
373
374 float rtAdjustmentVec[4];
375 fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
376 fDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
377 }
378}
379
380void GrDawnProgram::setData(const GrPrimitiveProcessor& primProc,
381 const GrRenderTarget* renderTarget,
382 GrSurfaceOrigin origin,
383 const GrPipeline& pipeline) {
384 this->setRenderTargetState(renderTarget, origin);
385 fGeometryProcessor->setData(fDataManager, primProc,
386 GrFragmentProcessor::CoordTransformIter(pipeline));
387 GrFragmentProcessor::Iter iter(pipeline);
388 GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
389 const GrFragmentProcessor* fp = iter.next();
390 GrGLSLFragmentProcessor* glslFP = glslIter.next();
391 while (fp && glslFP) {
392 glslFP->setData(fDataManager, *fp);
393 fp = iter.next();
394 glslFP = glslIter.next();
395 }
396 fDataManager.uploadUniformBuffers(fGeometryUniformBuffer,
397 fFragmentUniformBuffer);
398}