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