xref: /aosp_15_r20/external/skia/src/gpu/graphite/dawn/DawnGraphicsPipeline.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2022 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/dawn/DawnGraphicsPipeline.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/graphite/TextureInfo.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/SkSLToBackend.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/Swizzle.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Attribute.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ContextUtils.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/GraphicsPipelineDesc.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/Log.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RenderPassDesc.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/RendererProvider.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/ShaderInfo.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/UniformManager.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/dawn/DawnCaps.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/dawn/DawnErrorChecker.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/dawn/DawnGraphiteTypesPriv.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/dawn/DawnGraphiteUtilsPriv.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/dawn/DawnResourceProvider.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/dawn/DawnSharedContext.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/dawn/DawnUtilsPriv.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLProgramSettings.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/SkSLUtil.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLProgram.h"
32*c8dee2aaSAndroid Build Coastguard Worker 
33*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
34*c8dee2aaSAndroid Build Coastguard Worker 
35*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite {
36*c8dee2aaSAndroid Build Coastguard Worker 
37*c8dee2aaSAndroid Build Coastguard Worker namespace {
38*c8dee2aaSAndroid Build Coastguard Worker 
attribute_type_to_dawn(VertexAttribType type)39*c8dee2aaSAndroid Build Coastguard Worker inline wgpu::VertexFormat attribute_type_to_dawn(VertexAttribType type) {
40*c8dee2aaSAndroid Build Coastguard Worker     switch (type) {
41*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kFloat:
42*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Float32;
43*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kFloat2:
44*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Float32x2;
45*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kFloat3:
46*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Float32x3;
47*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kFloat4:
48*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Float32x4;
49*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kHalf2:
50*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Float16x2;
51*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kHalf4:
52*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Float16x4;
53*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kInt2:
54*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Sint32x2;
55*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kInt3:
56*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Sint32x3;
57*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kInt4:
58*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Sint32x4;
59*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUInt2:
60*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Uint32x2;
61*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kByte2:
62*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Sint8x2;
63*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kByte4:
64*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Sint8x4;
65*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUByte2:
66*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Uint8x2;
67*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUByte4:
68*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Uint8x4;
69*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUByte4_norm:
70*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Unorm8x4;
71*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kShort2:
72*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Sint16x2;
73*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kShort4:
74*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Sint16x4;
75*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUShort2:
76*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Uint16x2;
77*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUShort2_norm:
78*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Unorm16x2;
79*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kInt:
80*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Sint32;
81*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUInt:
82*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Uint32;
83*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUShort4_norm:
84*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::VertexFormat::Unorm16x4;
85*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kHalf:
86*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kByte:
87*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUByte:
88*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUByte_norm:
89*c8dee2aaSAndroid Build Coastguard Worker         case VertexAttribType::kUShort_norm:
90*c8dee2aaSAndroid Build Coastguard Worker             // Not supported.
91*c8dee2aaSAndroid Build Coastguard Worker             break;
92*c8dee2aaSAndroid Build Coastguard Worker     }
93*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
94*c8dee2aaSAndroid Build Coastguard Worker }
95*c8dee2aaSAndroid Build Coastguard Worker 
compare_op_to_dawn(CompareOp op)96*c8dee2aaSAndroid Build Coastguard Worker wgpu::CompareFunction compare_op_to_dawn(CompareOp op) {
97*c8dee2aaSAndroid Build Coastguard Worker     switch (op) {
98*c8dee2aaSAndroid Build Coastguard Worker         case CompareOp::kAlways:
99*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::CompareFunction::Always;
100*c8dee2aaSAndroid Build Coastguard Worker         case CompareOp::kNever:
101*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::CompareFunction::Never;
102*c8dee2aaSAndroid Build Coastguard Worker         case CompareOp::kGreater:
103*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::CompareFunction::Greater;
104*c8dee2aaSAndroid Build Coastguard Worker         case CompareOp::kGEqual:
105*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::CompareFunction::GreaterEqual;
106*c8dee2aaSAndroid Build Coastguard Worker         case CompareOp::kLess:
107*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::CompareFunction::Less;
108*c8dee2aaSAndroid Build Coastguard Worker         case CompareOp::kLEqual:
109*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::CompareFunction::LessEqual;
110*c8dee2aaSAndroid Build Coastguard Worker         case CompareOp::kEqual:
111*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::CompareFunction::Equal;
112*c8dee2aaSAndroid Build Coastguard Worker         case CompareOp::kNotEqual:
113*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::CompareFunction::NotEqual;
114*c8dee2aaSAndroid Build Coastguard Worker     }
115*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
116*c8dee2aaSAndroid Build Coastguard Worker }
117*c8dee2aaSAndroid Build Coastguard Worker 
stencil_op_to_dawn(StencilOp op)118*c8dee2aaSAndroid Build Coastguard Worker wgpu::StencilOperation stencil_op_to_dawn(StencilOp op) {
119*c8dee2aaSAndroid Build Coastguard Worker     switch (op) {
120*c8dee2aaSAndroid Build Coastguard Worker         case StencilOp::kKeep:
121*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::StencilOperation::Keep;
122*c8dee2aaSAndroid Build Coastguard Worker         case StencilOp::kZero:
123*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::StencilOperation::Zero;
124*c8dee2aaSAndroid Build Coastguard Worker         case StencilOp::kReplace:
125*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::StencilOperation::Replace;
126*c8dee2aaSAndroid Build Coastguard Worker         case StencilOp::kInvert:
127*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::StencilOperation::Invert;
128*c8dee2aaSAndroid Build Coastguard Worker         case StencilOp::kIncWrap:
129*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::StencilOperation::IncrementWrap;
130*c8dee2aaSAndroid Build Coastguard Worker         case StencilOp::kDecWrap:
131*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::StencilOperation::DecrementWrap;
132*c8dee2aaSAndroid Build Coastguard Worker         case StencilOp::kIncClamp:
133*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::StencilOperation::IncrementClamp;
134*c8dee2aaSAndroid Build Coastguard Worker         case StencilOp::kDecClamp:
135*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::StencilOperation::DecrementClamp;
136*c8dee2aaSAndroid Build Coastguard Worker     }
137*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
138*c8dee2aaSAndroid Build Coastguard Worker }
139*c8dee2aaSAndroid Build Coastguard Worker 
stencil_face_to_dawn(DepthStencilSettings::Face face)140*c8dee2aaSAndroid Build Coastguard Worker wgpu::StencilFaceState stencil_face_to_dawn(DepthStencilSettings::Face face) {
141*c8dee2aaSAndroid Build Coastguard Worker     wgpu::StencilFaceState state;
142*c8dee2aaSAndroid Build Coastguard Worker     state.compare = compare_op_to_dawn(face.fCompareOp);
143*c8dee2aaSAndroid Build Coastguard Worker     state.failOp = stencil_op_to_dawn(face.fStencilFailOp);
144*c8dee2aaSAndroid Build Coastguard Worker     state.depthFailOp = stencil_op_to_dawn(face.fDepthFailOp);
145*c8dee2aaSAndroid Build Coastguard Worker     state.passOp = stencil_op_to_dawn(face.fDepthStencilPassOp);
146*c8dee2aaSAndroid Build Coastguard Worker     return state;
147*c8dee2aaSAndroid Build Coastguard Worker }
148*c8dee2aaSAndroid Build Coastguard Worker 
create_vertex_attributes(SkSpan<const Attribute> attrs,int shaderLocationOffset,std::vector<wgpu::VertexAttribute> * out)149*c8dee2aaSAndroid Build Coastguard Worker size_t create_vertex_attributes(SkSpan<const Attribute> attrs,
150*c8dee2aaSAndroid Build Coastguard Worker                                 int shaderLocationOffset,
151*c8dee2aaSAndroid Build Coastguard Worker                                 std::vector<wgpu::VertexAttribute>* out) {
152*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(out && out->empty());
153*c8dee2aaSAndroid Build Coastguard Worker     out->resize(attrs.size());
154*c8dee2aaSAndroid Build Coastguard Worker     size_t vertexAttributeOffset = 0;
155*c8dee2aaSAndroid Build Coastguard Worker     int attributeIndex = 0;
156*c8dee2aaSAndroid Build Coastguard Worker     for (const auto& attr : attrs) {
157*c8dee2aaSAndroid Build Coastguard Worker         wgpu::VertexAttribute& vertexAttribute =  (*out)[attributeIndex];
158*c8dee2aaSAndroid Build Coastguard Worker         vertexAttribute.format = attribute_type_to_dawn(attr.cpuType());
159*c8dee2aaSAndroid Build Coastguard Worker         vertexAttribute.offset = vertexAttributeOffset;
160*c8dee2aaSAndroid Build Coastguard Worker         vertexAttribute.shaderLocation = shaderLocationOffset + attributeIndex;
161*c8dee2aaSAndroid Build Coastguard Worker         vertexAttributeOffset += attr.sizeAlign4();
162*c8dee2aaSAndroid Build Coastguard Worker         attributeIndex++;
163*c8dee2aaSAndroid Build Coastguard Worker     }
164*c8dee2aaSAndroid Build Coastguard Worker     return vertexAttributeOffset;
165*c8dee2aaSAndroid Build Coastguard Worker }
166*c8dee2aaSAndroid Build Coastguard Worker 
167*c8dee2aaSAndroid Build Coastguard Worker // TODO: share this w/ Ganesh dawn backend?
blend_coeff_to_dawn_blend(const DawnCaps & caps,skgpu::BlendCoeff coeff)168*c8dee2aaSAndroid Build Coastguard Worker static wgpu::BlendFactor blend_coeff_to_dawn_blend(const DawnCaps& caps, skgpu::BlendCoeff coeff) {
169*c8dee2aaSAndroid Build Coastguard Worker #if defined(__EMSCRIPTEN__)
170*c8dee2aaSAndroid Build Coastguard Worker #define VALUE_IF_DSB_OR_ZERO(VALUE) wgpu::BlendFactor::Zero
171*c8dee2aaSAndroid Build Coastguard Worker #else
172*c8dee2aaSAndroid Build Coastguard Worker #define VALUE_IF_DSB_OR_ZERO(VALUE) \
173*c8dee2aaSAndroid Build Coastguard Worker     ((caps.shaderCaps()->fDualSourceBlendingSupport) ? (VALUE) : wgpu::BlendFactor::Zero)
174*c8dee2aaSAndroid Build Coastguard Worker #endif
175*c8dee2aaSAndroid Build Coastguard Worker     switch (coeff) {
176*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kZero:
177*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::Zero;
178*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kOne:
179*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::One;
180*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kSC:
181*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::Src;
182*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kISC:
183*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::OneMinusSrc;
184*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kDC:
185*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::Dst;
186*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kIDC:
187*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::OneMinusDst;
188*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kSA:
189*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::SrcAlpha;
190*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kISA:
191*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::OneMinusSrcAlpha;
192*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kDA:
193*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::DstAlpha;
194*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kIDA:
195*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::OneMinusDstAlpha;
196*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kConstC:
197*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::Constant;
198*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kIConstC:
199*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::OneMinusConstant;
200*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kS2C:
201*c8dee2aaSAndroid Build Coastguard Worker             return VALUE_IF_DSB_OR_ZERO(wgpu::BlendFactor::Src1);
202*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kIS2C:
203*c8dee2aaSAndroid Build Coastguard Worker             return VALUE_IF_DSB_OR_ZERO(wgpu::BlendFactor::OneMinusSrc1);
204*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kS2A:
205*c8dee2aaSAndroid Build Coastguard Worker             return VALUE_IF_DSB_OR_ZERO(wgpu::BlendFactor::Src1Alpha);
206*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kIS2A:
207*c8dee2aaSAndroid Build Coastguard Worker             return VALUE_IF_DSB_OR_ZERO(wgpu::BlendFactor::OneMinusSrc1Alpha);
208*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kIllegal:
209*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::Zero;
210*c8dee2aaSAndroid Build Coastguard Worker     }
211*c8dee2aaSAndroid Build Coastguard Worker     SkUNREACHABLE;
212*c8dee2aaSAndroid Build Coastguard Worker #undef VALUE_IF_DSB_OR_ZERO
213*c8dee2aaSAndroid Build Coastguard Worker }
214*c8dee2aaSAndroid Build Coastguard Worker 
blend_coeff_to_dawn_blend_for_alpha(const DawnCaps & caps,skgpu::BlendCoeff coeff)215*c8dee2aaSAndroid Build Coastguard Worker static wgpu::BlendFactor blend_coeff_to_dawn_blend_for_alpha(const DawnCaps& caps,
216*c8dee2aaSAndroid Build Coastguard Worker                                                              skgpu::BlendCoeff coeff) {
217*c8dee2aaSAndroid Build Coastguard Worker     switch (coeff) {
218*c8dee2aaSAndroid Build Coastguard Worker         // Force all srcColor used in alpha slot to alpha version.
219*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kSC:
220*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::SrcAlpha;
221*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kISC:
222*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::OneMinusSrcAlpha;
223*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kDC:
224*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::DstAlpha;
225*c8dee2aaSAndroid Build Coastguard Worker         case skgpu::BlendCoeff::kIDC:
226*c8dee2aaSAndroid Build Coastguard Worker             return wgpu::BlendFactor::OneMinusDstAlpha;
227*c8dee2aaSAndroid Build Coastguard Worker         default:
228*c8dee2aaSAndroid Build Coastguard Worker             return blend_coeff_to_dawn_blend(caps, coeff);
229*c8dee2aaSAndroid Build Coastguard Worker     }
230*c8dee2aaSAndroid Build Coastguard Worker }
231*c8dee2aaSAndroid Build Coastguard Worker 
232*c8dee2aaSAndroid Build Coastguard Worker // TODO: share this w/ Ganesh Metal backend?
blend_equation_to_dawn_blend_op(skgpu::BlendEquation equation)233*c8dee2aaSAndroid Build Coastguard Worker static wgpu::BlendOperation blend_equation_to_dawn_blend_op(skgpu::BlendEquation equation) {
234*c8dee2aaSAndroid Build Coastguard Worker     static const wgpu::BlendOperation gTable[] = {
235*c8dee2aaSAndroid Build Coastguard Worker             wgpu::BlendOperation::Add,              // skgpu::BlendEquation::kAdd
236*c8dee2aaSAndroid Build Coastguard Worker             wgpu::BlendOperation::Subtract,         // skgpu::BlendEquation::kSubtract
237*c8dee2aaSAndroid Build Coastguard Worker             wgpu::BlendOperation::ReverseSubtract,  // skgpu::BlendEquation::kReverseSubtract
238*c8dee2aaSAndroid Build Coastguard Worker     };
239*c8dee2aaSAndroid Build Coastguard Worker     static_assert(std::size(gTable) == (int)skgpu::BlendEquation::kFirstAdvanced);
240*c8dee2aaSAndroid Build Coastguard Worker     static_assert(0 == (int)skgpu::BlendEquation::kAdd);
241*c8dee2aaSAndroid Build Coastguard Worker     static_assert(1 == (int)skgpu::BlendEquation::kSubtract);
242*c8dee2aaSAndroid Build Coastguard Worker     static_assert(2 == (int)skgpu::BlendEquation::kReverseSubtract);
243*c8dee2aaSAndroid Build Coastguard Worker 
244*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT((unsigned)equation < skgpu::kBlendEquationCnt);
245*c8dee2aaSAndroid Build Coastguard Worker     return gTable[(int)equation];
246*c8dee2aaSAndroid Build Coastguard Worker }
247*c8dee2aaSAndroid Build Coastguard Worker 
248*c8dee2aaSAndroid Build Coastguard Worker struct AsyncPipelineCreationBase {
249*c8dee2aaSAndroid Build Coastguard Worker     wgpu::RenderPipeline fRenderPipeline;
250*c8dee2aaSAndroid Build Coastguard Worker     bool fFinished = false;
251*c8dee2aaSAndroid Build Coastguard Worker #if SK_HISTOGRAMS_ENABLED
252*c8dee2aaSAndroid Build Coastguard Worker     // We need these three for the Graphite.PipelineCreationTimes.* histograms (cf.
253*c8dee2aaSAndroid Build Coastguard Worker     // log_pipeline_creation)
254*c8dee2aaSAndroid Build Coastguard Worker     skgpu::StdSteadyClock::time_point fStartTime;
255*c8dee2aaSAndroid Build Coastguard Worker     bool fFromPrecompile;
256*c8dee2aaSAndroid Build Coastguard Worker     bool fAsynchronous = false;
257*c8dee2aaSAndroid Build Coastguard Worker #endif
258*c8dee2aaSAndroid Build Coastguard Worker };
259*c8dee2aaSAndroid Build Coastguard Worker 
log_pipeline_creation(const AsyncPipelineCreationBase * apcb)260*c8dee2aaSAndroid Build Coastguard Worker void log_pipeline_creation(const AsyncPipelineCreationBase* apcb) {
261*c8dee2aaSAndroid Build Coastguard Worker #if SK_HISTOGRAMS_ENABLED
262*c8dee2aaSAndroid Build Coastguard Worker     [[maybe_unused]] static constexpr int kBucketCount = 100;
263*c8dee2aaSAndroid Build Coastguard Worker     [[maybe_unused]] static constexpr int kOneSecInUS = 1000000;
264*c8dee2aaSAndroid Build Coastguard Worker 
265*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(apcb->fFinished);
266*c8dee2aaSAndroid Build Coastguard Worker 
267*c8dee2aaSAndroid Build Coastguard Worker     if (!apcb->fRenderPipeline) {
268*c8dee2aaSAndroid Build Coastguard Worker         // A null fRenderPipeline means Pipeline creation failed
269*c8dee2aaSAndroid Build Coastguard Worker         return; // TODO: log failures to their own UMA stat
270*c8dee2aaSAndroid Build Coastguard Worker     }
271*c8dee2aaSAndroid Build Coastguard Worker 
272*c8dee2aaSAndroid Build Coastguard Worker     [[maybe_unused]] auto micros_since = [](skgpu::StdSteadyClock::time_point start) {
273*c8dee2aaSAndroid Build Coastguard Worker         skgpu::StdSteadyClock::duration elapsed = skgpu::StdSteadyClock::now() - start;
274*c8dee2aaSAndroid Build Coastguard Worker         return std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();
275*c8dee2aaSAndroid Build Coastguard Worker     };
276*c8dee2aaSAndroid Build Coastguard Worker 
277*c8dee2aaSAndroid Build Coastguard Worker     if (apcb->fFromPrecompile) {
278*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!apcb->fAsynchronous);     // precompile is done synchronously on a thread
279*c8dee2aaSAndroid Build Coastguard Worker         SK_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
280*c8dee2aaSAndroid Build Coastguard Worker             "Graphite.PipelineCreationTimes.Precompile",
281*c8dee2aaSAndroid Build Coastguard Worker             micros_since(apcb->fStartTime),
282*c8dee2aaSAndroid Build Coastguard Worker             /* minUSec= */ 1,
283*c8dee2aaSAndroid Build Coastguard Worker             /* maxUSec= */ kOneSecInUS,
284*c8dee2aaSAndroid Build Coastguard Worker             kBucketCount);
285*c8dee2aaSAndroid Build Coastguard Worker     } else if (apcb->fAsynchronous) {
286*c8dee2aaSAndroid Build Coastguard Worker         SK_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
287*c8dee2aaSAndroid Build Coastguard Worker             "Graphite.PipelineCreationTimes.Asynchronous",
288*c8dee2aaSAndroid Build Coastguard Worker             micros_since(apcb->fStartTime),
289*c8dee2aaSAndroid Build Coastguard Worker             /* minUSec= */ 1,
290*c8dee2aaSAndroid Build Coastguard Worker             /* maxUSec= */ kOneSecInUS,
291*c8dee2aaSAndroid Build Coastguard Worker             kBucketCount);
292*c8dee2aaSAndroid Build Coastguard Worker     } else {
293*c8dee2aaSAndroid Build Coastguard Worker         SK_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
294*c8dee2aaSAndroid Build Coastguard Worker             "Graphite.PipelineCreationTimes.Synchronous",
295*c8dee2aaSAndroid Build Coastguard Worker             micros_since(apcb->fStartTime),
296*c8dee2aaSAndroid Build Coastguard Worker             /* minUSec= */ 1,
297*c8dee2aaSAndroid Build Coastguard Worker             /* maxUSec= */ kOneSecInUS,
298*c8dee2aaSAndroid Build Coastguard Worker             kBucketCount);
299*c8dee2aaSAndroid Build Coastguard Worker     }
300*c8dee2aaSAndroid Build Coastguard Worker #endif // SK_HISTOGRAMS_ENABLED
301*c8dee2aaSAndroid Build Coastguard Worker }
302*c8dee2aaSAndroid Build Coastguard Worker 
303*c8dee2aaSAndroid Build Coastguard Worker } // anonymous namespace
304*c8dee2aaSAndroid Build Coastguard Worker 
305*c8dee2aaSAndroid Build Coastguard Worker #if defined(__EMSCRIPTEN__)
306*c8dee2aaSAndroid Build Coastguard Worker // For wasm, we don't use async compilation.
307*c8dee2aaSAndroid Build Coastguard Worker struct DawnGraphicsPipeline::AsyncPipelineCreation : public AsyncPipelineCreationBase {};
308*c8dee2aaSAndroid Build Coastguard Worker #else
309*c8dee2aaSAndroid Build Coastguard Worker struct DawnGraphicsPipeline::AsyncPipelineCreation : public AsyncPipelineCreationBase {
310*c8dee2aaSAndroid Build Coastguard Worker     wgpu::Future fFuture;
311*c8dee2aaSAndroid Build Coastguard Worker };
312*c8dee2aaSAndroid Build Coastguard Worker #endif
313*c8dee2aaSAndroid Build Coastguard Worker 
314*c8dee2aaSAndroid Build Coastguard Worker // static
Make(const DawnSharedContext * sharedContext,DawnResourceProvider * resourceProvider,const RuntimeEffectDictionary * runtimeDict,const GraphicsPipelineDesc & pipelineDesc,const RenderPassDesc & renderPassDesc,SkEnumBitMask<PipelineCreationFlags> pipelineCreationFlags)315*c8dee2aaSAndroid Build Coastguard Worker sk_sp<DawnGraphicsPipeline> DawnGraphicsPipeline::Make(
316*c8dee2aaSAndroid Build Coastguard Worker         const DawnSharedContext* sharedContext,
317*c8dee2aaSAndroid Build Coastguard Worker         DawnResourceProvider* resourceProvider,
318*c8dee2aaSAndroid Build Coastguard Worker         const RuntimeEffectDictionary* runtimeDict,
319*c8dee2aaSAndroid Build Coastguard Worker         const GraphicsPipelineDesc& pipelineDesc,
320*c8dee2aaSAndroid Build Coastguard Worker         const RenderPassDesc& renderPassDesc,
321*c8dee2aaSAndroid Build Coastguard Worker         SkEnumBitMask<PipelineCreationFlags> pipelineCreationFlags) {
322*c8dee2aaSAndroid Build Coastguard Worker     const DawnCaps& caps = *static_cast<const DawnCaps*>(sharedContext->caps());
323*c8dee2aaSAndroid Build Coastguard Worker     const auto& device = sharedContext->device();
324*c8dee2aaSAndroid Build Coastguard Worker 
325*c8dee2aaSAndroid Build Coastguard Worker     SkSL::Program::Interface vsInterface, fsInterface;
326*c8dee2aaSAndroid Build Coastguard Worker 
327*c8dee2aaSAndroid Build Coastguard Worker     SkSL::ProgramSettings settings;
328*c8dee2aaSAndroid Build Coastguard Worker     settings.fSharpenTextures = true;
329*c8dee2aaSAndroid Build Coastguard Worker     settings.fForceNoRTFlip = true;
330*c8dee2aaSAndroid Build Coastguard Worker 
331*c8dee2aaSAndroid Build Coastguard Worker     ShaderErrorHandler* errorHandler = caps.shaderErrorHandler();
332*c8dee2aaSAndroid Build Coastguard Worker 
333*c8dee2aaSAndroid Build Coastguard Worker     const RenderStep* step = sharedContext->rendererProvider()->lookup(pipelineDesc.renderStepID());
334*c8dee2aaSAndroid Build Coastguard Worker     const bool useStorageBuffers = caps.storageBufferSupport();
335*c8dee2aaSAndroid Build Coastguard Worker 
336*c8dee2aaSAndroid Build Coastguard Worker     std::string vsCode, fsCode;
337*c8dee2aaSAndroid Build Coastguard Worker     wgpu::ShaderModule fsModule, vsModule;
338*c8dee2aaSAndroid Build Coastguard Worker 
339*c8dee2aaSAndroid Build Coastguard Worker     // Some steps just render depth buffer but not color buffer, so the fragment
340*c8dee2aaSAndroid Build Coastguard Worker     // shader is null.
341*c8dee2aaSAndroid Build Coastguard Worker     UniquePaintParamsID paintID = pipelineDesc.paintParamsID();
342*c8dee2aaSAndroid Build Coastguard Worker 
343*c8dee2aaSAndroid Build Coastguard Worker     skia_private::TArray<SamplerDesc>* samplerDescArrPtr = nullptr;
344*c8dee2aaSAndroid Build Coastguard Worker #if !defined(__EMSCRIPTEN__)
345*c8dee2aaSAndroid Build Coastguard Worker     skia_private::TArray<SamplerDesc> samplerDescArr {};
346*c8dee2aaSAndroid Build Coastguard Worker     samplerDescArrPtr = &samplerDescArr;
347*c8dee2aaSAndroid Build Coastguard Worker #endif
348*c8dee2aaSAndroid Build Coastguard Worker 
349*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<ShaderInfo> shaderInfo = ShaderInfo::Make(&caps,
350*c8dee2aaSAndroid Build Coastguard Worker                                                               sharedContext->shaderCodeDictionary(),
351*c8dee2aaSAndroid Build Coastguard Worker                                                               runtimeDict,
352*c8dee2aaSAndroid Build Coastguard Worker                                                               step,
353*c8dee2aaSAndroid Build Coastguard Worker                                                               paintID,
354*c8dee2aaSAndroid Build Coastguard Worker                                                               useStorageBuffers,
355*c8dee2aaSAndroid Build Coastguard Worker                                                               renderPassDesc.fWriteSwizzle,
356*c8dee2aaSAndroid Build Coastguard Worker                                                               samplerDescArrPtr);
357*c8dee2aaSAndroid Build Coastguard Worker 
358*c8dee2aaSAndroid Build Coastguard Worker     const std::string& fsSkSL = shaderInfo->fragmentSkSL();
359*c8dee2aaSAndroid Build Coastguard Worker     const BlendInfo& blendInfo = shaderInfo->blendInfo();
360*c8dee2aaSAndroid Build Coastguard Worker     const int numTexturesAndSamplers = shaderInfo->numFragmentTexturesAndSamplers();
361*c8dee2aaSAndroid Build Coastguard Worker 
362*c8dee2aaSAndroid Build Coastguard Worker     const bool hasFragmentSkSL = !fsSkSL.empty();
363*c8dee2aaSAndroid Build Coastguard Worker     if (hasFragmentSkSL) {
364*c8dee2aaSAndroid Build Coastguard Worker         if (!skgpu::SkSLToWGSL(caps.shaderCaps(),
365*c8dee2aaSAndroid Build Coastguard Worker                                fsSkSL,
366*c8dee2aaSAndroid Build Coastguard Worker                                SkSL::ProgramKind::kGraphiteFragment,
367*c8dee2aaSAndroid Build Coastguard Worker                                settings,
368*c8dee2aaSAndroid Build Coastguard Worker                                &fsCode,
369*c8dee2aaSAndroid Build Coastguard Worker                                &fsInterface,
370*c8dee2aaSAndroid Build Coastguard Worker                                errorHandler)) {
371*c8dee2aaSAndroid Build Coastguard Worker             return {};
372*c8dee2aaSAndroid Build Coastguard Worker         }
373*c8dee2aaSAndroid Build Coastguard Worker         if (!DawnCompileWGSLShaderModule(sharedContext, shaderInfo->fsLabel().c_str(), fsCode,
374*c8dee2aaSAndroid Build Coastguard Worker                                          &fsModule, errorHandler)) {
375*c8dee2aaSAndroid Build Coastguard Worker             return {};
376*c8dee2aaSAndroid Build Coastguard Worker         }
377*c8dee2aaSAndroid Build Coastguard Worker     }
378*c8dee2aaSAndroid Build Coastguard Worker 
379*c8dee2aaSAndroid Build Coastguard Worker     const std::string& vsSkSL = shaderInfo->vertexSkSL();
380*c8dee2aaSAndroid Build Coastguard Worker     if (!skgpu::SkSLToWGSL(caps.shaderCaps(),
381*c8dee2aaSAndroid Build Coastguard Worker                            vsSkSL,
382*c8dee2aaSAndroid Build Coastguard Worker                            SkSL::ProgramKind::kGraphiteVertex,
383*c8dee2aaSAndroid Build Coastguard Worker                            settings,
384*c8dee2aaSAndroid Build Coastguard Worker                            &vsCode,
385*c8dee2aaSAndroid Build Coastguard Worker                            &vsInterface,
386*c8dee2aaSAndroid Build Coastguard Worker                            errorHandler)) {
387*c8dee2aaSAndroid Build Coastguard Worker         return {};
388*c8dee2aaSAndroid Build Coastguard Worker     }
389*c8dee2aaSAndroid Build Coastguard Worker     if (!DawnCompileWGSLShaderModule(sharedContext, shaderInfo->vsLabel().c_str(), vsCode,
390*c8dee2aaSAndroid Build Coastguard Worker                                      &vsModule, errorHandler)) {
391*c8dee2aaSAndroid Build Coastguard Worker         return {};
392*c8dee2aaSAndroid Build Coastguard Worker     }
393*c8dee2aaSAndroid Build Coastguard Worker 
394*c8dee2aaSAndroid Build Coastguard Worker     std::string pipelineLabel =
395*c8dee2aaSAndroid Build Coastguard Worker             GetPipelineLabel(sharedContext->shaderCodeDictionary(), renderPassDesc, step, paintID);
396*c8dee2aaSAndroid Build Coastguard Worker     wgpu::RenderPipelineDescriptor descriptor;
397*c8dee2aaSAndroid Build Coastguard Worker     // Always set the label for pipelines, dawn may need it for tracing.
398*c8dee2aaSAndroid Build Coastguard Worker     descriptor.label = pipelineLabel.c_str();
399*c8dee2aaSAndroid Build Coastguard Worker 
400*c8dee2aaSAndroid Build Coastguard Worker     // Fragment state
401*c8dee2aaSAndroid Build Coastguard Worker     skgpu::BlendEquation equation = blendInfo.fEquation;
402*c8dee2aaSAndroid Build Coastguard Worker     skgpu::BlendCoeff srcCoeff = blendInfo.fSrcBlend;
403*c8dee2aaSAndroid Build Coastguard Worker     skgpu::BlendCoeff dstCoeff = blendInfo.fDstBlend;
404*c8dee2aaSAndroid Build Coastguard Worker     bool blendOn = !skgpu::BlendShouldDisable(equation, srcCoeff, dstCoeff);
405*c8dee2aaSAndroid Build Coastguard Worker 
406*c8dee2aaSAndroid Build Coastguard Worker     wgpu::BlendState blend;
407*c8dee2aaSAndroid Build Coastguard Worker     if (blendOn) {
408*c8dee2aaSAndroid Build Coastguard Worker         blend.color.operation = blend_equation_to_dawn_blend_op(equation);
409*c8dee2aaSAndroid Build Coastguard Worker         blend.color.srcFactor = blend_coeff_to_dawn_blend(caps, srcCoeff);
410*c8dee2aaSAndroid Build Coastguard Worker         blend.color.dstFactor = blend_coeff_to_dawn_blend(caps, dstCoeff);
411*c8dee2aaSAndroid Build Coastguard Worker         blend.alpha.operation = blend_equation_to_dawn_blend_op(equation);
412*c8dee2aaSAndroid Build Coastguard Worker         blend.alpha.srcFactor = blend_coeff_to_dawn_blend_for_alpha(caps, srcCoeff);
413*c8dee2aaSAndroid Build Coastguard Worker         blend.alpha.dstFactor = blend_coeff_to_dawn_blend_for_alpha(caps, dstCoeff);
414*c8dee2aaSAndroid Build Coastguard Worker     }
415*c8dee2aaSAndroid Build Coastguard Worker 
416*c8dee2aaSAndroid Build Coastguard Worker     wgpu::ColorTargetState colorTarget;
417*c8dee2aaSAndroid Build Coastguard Worker     colorTarget.format =
418*c8dee2aaSAndroid Build Coastguard Worker             TextureInfos::GetDawnViewFormat(renderPassDesc.fColorAttachment.fTextureInfo);
419*c8dee2aaSAndroid Build Coastguard Worker     colorTarget.blend = blendOn ? &blend : nullptr;
420*c8dee2aaSAndroid Build Coastguard Worker     colorTarget.writeMask = blendInfo.fWritesColor && hasFragmentSkSL ? wgpu::ColorWriteMask::All
421*c8dee2aaSAndroid Build Coastguard Worker                                                                       : wgpu::ColorWriteMask::None;
422*c8dee2aaSAndroid Build Coastguard Worker 
423*c8dee2aaSAndroid Build Coastguard Worker #if !defined(__EMSCRIPTEN__)
424*c8dee2aaSAndroid Build Coastguard Worker     const bool loadMsaaFromResolve =
425*c8dee2aaSAndroid Build Coastguard Worker             renderPassDesc.fColorResolveAttachment.fTextureInfo.isValid() &&
426*c8dee2aaSAndroid Build Coastguard Worker             renderPassDesc.fColorResolveAttachment.fLoadOp == LoadOp::kLoad;
427*c8dee2aaSAndroid Build Coastguard Worker     // Special case: a render pass loading resolve texture requires additional settings for the
428*c8dee2aaSAndroid Build Coastguard Worker     // pipeline to make it compatible.
429*c8dee2aaSAndroid Build Coastguard Worker     wgpu::ColorTargetStateExpandResolveTextureDawn pipelineMSAALoadResolveTextureDesc;
430*c8dee2aaSAndroid Build Coastguard Worker     if (loadMsaaFromResolve && sharedContext->dawnCaps()->resolveTextureLoadOp().has_value()) {
431*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(device.HasFeature(wgpu::FeatureName::DawnLoadResolveTexture));
432*c8dee2aaSAndroid Build Coastguard Worker         colorTarget.nextInChain = &pipelineMSAALoadResolveTextureDesc;
433*c8dee2aaSAndroid Build Coastguard Worker         pipelineMSAALoadResolveTextureDesc.enabled = true;
434*c8dee2aaSAndroid Build Coastguard Worker     }
435*c8dee2aaSAndroid Build Coastguard Worker #endif
436*c8dee2aaSAndroid Build Coastguard Worker 
437*c8dee2aaSAndroid Build Coastguard Worker     wgpu::FragmentState fragment;
438*c8dee2aaSAndroid Build Coastguard Worker     // Dawn doesn't allow having a color attachment but without fragment shader, so have to use a
439*c8dee2aaSAndroid Build Coastguard Worker     // noop fragment shader, if fragment shader is null.
440*c8dee2aaSAndroid Build Coastguard Worker     fragment.module = hasFragmentSkSL ? std::move(fsModule) : sharedContext->noopFragment();
441*c8dee2aaSAndroid Build Coastguard Worker     fragment.entryPoint = "main";
442*c8dee2aaSAndroid Build Coastguard Worker     fragment.targetCount = 1;
443*c8dee2aaSAndroid Build Coastguard Worker     fragment.targets = &colorTarget;
444*c8dee2aaSAndroid Build Coastguard Worker     descriptor.fragment = &fragment;
445*c8dee2aaSAndroid Build Coastguard Worker 
446*c8dee2aaSAndroid Build Coastguard Worker     // Depth stencil state
447*c8dee2aaSAndroid Build Coastguard Worker     const auto& depthStencilSettings = step->depthStencilSettings();
448*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(depthStencilSettings.fDepthTestEnabled ||
449*c8dee2aaSAndroid Build Coastguard Worker              depthStencilSettings.fDepthCompareOp == CompareOp::kAlways);
450*c8dee2aaSAndroid Build Coastguard Worker     wgpu::DepthStencilState depthStencil;
451*c8dee2aaSAndroid Build Coastguard Worker     if (renderPassDesc.fDepthStencilAttachment.fTextureInfo.isValid()) {
452*c8dee2aaSAndroid Build Coastguard Worker         wgpu::TextureFormat dsFormat = TextureInfos::GetDawnViewFormat(
453*c8dee2aaSAndroid Build Coastguard Worker                 renderPassDesc.fDepthStencilAttachment.fTextureInfo);
454*c8dee2aaSAndroid Build Coastguard Worker         depthStencil.format =
455*c8dee2aaSAndroid Build Coastguard Worker                 DawnFormatIsDepthOrStencil(dsFormat) ? dsFormat : wgpu::TextureFormat::Undefined;
456*c8dee2aaSAndroid Build Coastguard Worker         if (depthStencilSettings.fDepthTestEnabled) {
457*c8dee2aaSAndroid Build Coastguard Worker             depthStencil.depthWriteEnabled = depthStencilSettings.fDepthWriteEnabled;
458*c8dee2aaSAndroid Build Coastguard Worker         }
459*c8dee2aaSAndroid Build Coastguard Worker         depthStencil.depthCompare = compare_op_to_dawn(depthStencilSettings.fDepthCompareOp);
460*c8dee2aaSAndroid Build Coastguard Worker 
461*c8dee2aaSAndroid Build Coastguard Worker         // Dawn validation fails if the stencil state is non-default and the
462*c8dee2aaSAndroid Build Coastguard Worker         // format doesn't have the stencil aspect.
463*c8dee2aaSAndroid Build Coastguard Worker         if (DawnFormatIsStencil(dsFormat) && depthStencilSettings.fStencilTestEnabled) {
464*c8dee2aaSAndroid Build Coastguard Worker             depthStencil.stencilFront = stencil_face_to_dawn(depthStencilSettings.fFrontStencil);
465*c8dee2aaSAndroid Build Coastguard Worker             depthStencil.stencilBack = stencil_face_to_dawn(depthStencilSettings.fBackStencil);
466*c8dee2aaSAndroid Build Coastguard Worker             depthStencil.stencilReadMask = depthStencilSettings.fFrontStencil.fReadMask;
467*c8dee2aaSAndroid Build Coastguard Worker             depthStencil.stencilWriteMask = depthStencilSettings.fFrontStencil.fWriteMask;
468*c8dee2aaSAndroid Build Coastguard Worker         }
469*c8dee2aaSAndroid Build Coastguard Worker 
470*c8dee2aaSAndroid Build Coastguard Worker         descriptor.depthStencil = &depthStencil;
471*c8dee2aaSAndroid Build Coastguard Worker     }
472*c8dee2aaSAndroid Build Coastguard Worker 
473*c8dee2aaSAndroid Build Coastguard Worker     // Determine the BindGroupLayouts that will be used to make up the pipeline layout.
474*c8dee2aaSAndroid Build Coastguard Worker     BindGroupLayouts groupLayouts;
475*c8dee2aaSAndroid Build Coastguard Worker     // If immutable samplers are used with this pipeline, they must be included in the pipeline
476*c8dee2aaSAndroid Build Coastguard Worker     // layout and passed in to the pipline constructor for lifetime management.
477*c8dee2aaSAndroid Build Coastguard Worker     skia_private::TArray<sk_sp<DawnSampler>> immutableSamplers;
478*c8dee2aaSAndroid Build Coastguard Worker     {
479*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(resourceProvider);
480*c8dee2aaSAndroid Build Coastguard Worker         groupLayouts[0] = resourceProvider->getOrCreateUniformBuffersBindGroupLayout();
481*c8dee2aaSAndroid Build Coastguard Worker         if (!groupLayouts[0]) {
482*c8dee2aaSAndroid Build Coastguard Worker             return {};
483*c8dee2aaSAndroid Build Coastguard Worker         }
484*c8dee2aaSAndroid Build Coastguard Worker 
485*c8dee2aaSAndroid Build Coastguard Worker         bool hasFragmentSamplers = hasFragmentSkSL && numTexturesAndSamplers > 0;
486*c8dee2aaSAndroid Build Coastguard Worker         if (hasFragmentSamplers) {
487*c8dee2aaSAndroid Build Coastguard Worker             // Check if we can optimize for the common case of a single texture + 1 dynamic sampler
488*c8dee2aaSAndroid Build Coastguard Worker             if (numTexturesAndSamplers == 2 &&
489*c8dee2aaSAndroid Build Coastguard Worker                 !(samplerDescArrPtr && samplerDescArrPtr->at(0).isImmutable())) {
490*c8dee2aaSAndroid Build Coastguard Worker                 groupLayouts[1] =
491*c8dee2aaSAndroid Build Coastguard Worker                         resourceProvider->getOrCreateSingleTextureSamplerBindGroupLayout();
492*c8dee2aaSAndroid Build Coastguard Worker             } else {
493*c8dee2aaSAndroid Build Coastguard Worker                 std::vector<wgpu::BindGroupLayoutEntry> entries(numTexturesAndSamplers);
494*c8dee2aaSAndroid Build Coastguard Worker #if !defined(__EMSCRIPTEN__)
495*c8dee2aaSAndroid Build Coastguard Worker                 // Static sampler layouts are passed into Dawn by address and therefore must stay
496*c8dee2aaSAndroid Build Coastguard Worker                 // alive until the BindGroupLayoutDescriptor is created. So, store them outside of
497*c8dee2aaSAndroid Build Coastguard Worker                 // the loop that iterates over each BindGroupLayoutEntry.
498*c8dee2aaSAndroid Build Coastguard Worker                 skia_private::TArray<wgpu::StaticSamplerBindingLayout> staticSamplerLayouts;
499*c8dee2aaSAndroid Build Coastguard Worker 
500*c8dee2aaSAndroid Build Coastguard Worker                 // Note that the number of samplers is equivalent to numTexturesAndSamplers / 2. So,
501*c8dee2aaSAndroid Build Coastguard Worker                 // a sampler's index within any container that only pertains to sampler information
502*c8dee2aaSAndroid Build Coastguard Worker                 // (as in, excludes textures) is equivalent to 1/2 of that sampler's binding index
503*c8dee2aaSAndroid Build Coastguard Worker                 // within the BindGroupLayout. Assert that we have analyzed the appropriate number
504*c8dee2aaSAndroid Build Coastguard Worker                 // of samplers by equating samplerDescArr size to sampler quantity.
505*c8dee2aaSAndroid Build Coastguard Worker                 SkASSERT(samplerDescArrPtr && samplerDescArr.size() == numTexturesAndSamplers / 2);
506*c8dee2aaSAndroid Build Coastguard Worker #endif
507*c8dee2aaSAndroid Build Coastguard Worker 
508*c8dee2aaSAndroid Build Coastguard Worker                 for (int i = 0; i < numTexturesAndSamplers;) {
509*c8dee2aaSAndroid Build Coastguard Worker                     entries[i].binding = i;
510*c8dee2aaSAndroid Build Coastguard Worker                     entries[i].visibility = wgpu::ShaderStage::Fragment;
511*c8dee2aaSAndroid Build Coastguard Worker #if !defined(__EMSCRIPTEN__)
512*c8dee2aaSAndroid Build Coastguard Worker                     // Index of sampler information = 1/2 of cumulative texture and sampler index.
513*c8dee2aaSAndroid Build Coastguard Worker                     // If we have a non-default-initialized SamplerDesc at that index,
514*c8dee2aaSAndroid Build Coastguard Worker                     // fetch an immutable sampler that matches that description to include in the
515*c8dee2aaSAndroid Build Coastguard Worker                     // pipeline layout.
516*c8dee2aaSAndroid Build Coastguard Worker                     const SamplerDesc& samplerDesc = samplerDescArr.at(i/2);
517*c8dee2aaSAndroid Build Coastguard Worker                     if (samplerDesc.isImmutable()) {
518*c8dee2aaSAndroid Build Coastguard Worker                         sk_sp<Sampler> immutableSampler =
519*c8dee2aaSAndroid Build Coastguard Worker                                 resourceProvider->findOrCreateCompatibleSampler(samplerDesc);
520*c8dee2aaSAndroid Build Coastguard Worker                         if (!immutableSampler) {
521*c8dee2aaSAndroid Build Coastguard Worker                             SKGPU_LOG_E("Failed to find/create immutable sampler for pipeline");
522*c8dee2aaSAndroid Build Coastguard Worker                             return {};
523*c8dee2aaSAndroid Build Coastguard Worker                         }
524*c8dee2aaSAndroid Build Coastguard Worker                         sk_sp<DawnSampler> dawnImmutableSampler = sk_ref_sp<DawnSampler>(
525*c8dee2aaSAndroid Build Coastguard Worker                                 static_cast<DawnSampler*>(immutableSampler.get()));
526*c8dee2aaSAndroid Build Coastguard Worker                         SkASSERT(dawnImmutableSampler);
527*c8dee2aaSAndroid Build Coastguard Worker 
528*c8dee2aaSAndroid Build Coastguard Worker                         wgpu::StaticSamplerBindingLayout& immutableSamplerBinding =
529*c8dee2aaSAndroid Build Coastguard Worker                                 staticSamplerLayouts.emplace_back();
530*c8dee2aaSAndroid Build Coastguard Worker                         immutableSamplerBinding.sampler = dawnImmutableSampler->dawnSampler();
531*c8dee2aaSAndroid Build Coastguard Worker                         // Static samplers sample from the subsequent texture in the BindGroupLayout
532*c8dee2aaSAndroid Build Coastguard Worker                         immutableSamplerBinding.sampledTextureBinding = i + 1;
533*c8dee2aaSAndroid Build Coastguard Worker 
534*c8dee2aaSAndroid Build Coastguard Worker                         immutableSamplers.push_back(std::move(dawnImmutableSampler));
535*c8dee2aaSAndroid Build Coastguard Worker                         entries[i].nextInChain = &immutableSamplerBinding;
536*c8dee2aaSAndroid Build Coastguard Worker                     } else {
537*c8dee2aaSAndroid Build Coastguard Worker #endif
538*c8dee2aaSAndroid Build Coastguard Worker                         entries[i].sampler.type = wgpu::SamplerBindingType::Filtering;
539*c8dee2aaSAndroid Build Coastguard Worker #if !defined(__EMSCRIPTEN__)
540*c8dee2aaSAndroid Build Coastguard Worker                     }
541*c8dee2aaSAndroid Build Coastguard Worker #endif
542*c8dee2aaSAndroid Build Coastguard Worker                     ++i;
543*c8dee2aaSAndroid Build Coastguard Worker 
544*c8dee2aaSAndroid Build Coastguard Worker                     entries[i].binding = i;
545*c8dee2aaSAndroid Build Coastguard Worker                     entries[i].visibility = wgpu::ShaderStage::Fragment;
546*c8dee2aaSAndroid Build Coastguard Worker                     entries[i].texture.sampleType = wgpu::TextureSampleType::Float;
547*c8dee2aaSAndroid Build Coastguard Worker                     entries[i].texture.viewDimension = wgpu::TextureViewDimension::e2D;
548*c8dee2aaSAndroid Build Coastguard Worker                     entries[i].texture.multisampled = false;
549*c8dee2aaSAndroid Build Coastguard Worker                     ++i;
550*c8dee2aaSAndroid Build Coastguard Worker                 }
551*c8dee2aaSAndroid Build Coastguard Worker 
552*c8dee2aaSAndroid Build Coastguard Worker                 wgpu::BindGroupLayoutDescriptor groupLayoutDesc;
553*c8dee2aaSAndroid Build Coastguard Worker                 if (sharedContext->caps()->setBackendLabels()) {
554*c8dee2aaSAndroid Build Coastguard Worker                     groupLayoutDesc.label = shaderInfo->vsLabel().c_str();
555*c8dee2aaSAndroid Build Coastguard Worker                 }
556*c8dee2aaSAndroid Build Coastguard Worker                 groupLayoutDesc.entryCount = entries.size();
557*c8dee2aaSAndroid Build Coastguard Worker                 groupLayoutDesc.entries = entries.data();
558*c8dee2aaSAndroid Build Coastguard Worker                 groupLayouts[1] = device.CreateBindGroupLayout(&groupLayoutDesc);
559*c8dee2aaSAndroid Build Coastguard Worker             }
560*c8dee2aaSAndroid Build Coastguard Worker             if (!groupLayouts[1]) {
561*c8dee2aaSAndroid Build Coastguard Worker                 return {};
562*c8dee2aaSAndroid Build Coastguard Worker             }
563*c8dee2aaSAndroid Build Coastguard Worker         }
564*c8dee2aaSAndroid Build Coastguard Worker 
565*c8dee2aaSAndroid Build Coastguard Worker         wgpu::PipelineLayoutDescriptor layoutDesc;
566*c8dee2aaSAndroid Build Coastguard Worker         if (sharedContext->caps()->setBackendLabels()) {
567*c8dee2aaSAndroid Build Coastguard Worker             layoutDesc.label = shaderInfo->fsLabel().c_str();
568*c8dee2aaSAndroid Build Coastguard Worker         }
569*c8dee2aaSAndroid Build Coastguard Worker         layoutDesc.bindGroupLayoutCount =
570*c8dee2aaSAndroid Build Coastguard Worker             hasFragmentSamplers ? groupLayouts.size() : groupLayouts.size() - 1;
571*c8dee2aaSAndroid Build Coastguard Worker         layoutDesc.bindGroupLayouts = groupLayouts.data();
572*c8dee2aaSAndroid Build Coastguard Worker         auto layout = device.CreatePipelineLayout(&layoutDesc);
573*c8dee2aaSAndroid Build Coastguard Worker         if (!layout) {
574*c8dee2aaSAndroid Build Coastguard Worker             return {};
575*c8dee2aaSAndroid Build Coastguard Worker         }
576*c8dee2aaSAndroid Build Coastguard Worker         descriptor.layout = std::move(layout);
577*c8dee2aaSAndroid Build Coastguard Worker     }
578*c8dee2aaSAndroid Build Coastguard Worker 
579*c8dee2aaSAndroid Build Coastguard Worker     // Vertex state
580*c8dee2aaSAndroid Build Coastguard Worker     std::array<wgpu::VertexBufferLayout, kNumVertexBuffers> vertexBufferLayouts;
581*c8dee2aaSAndroid Build Coastguard Worker     // Vertex buffer layout
582*c8dee2aaSAndroid Build Coastguard Worker     std::vector<wgpu::VertexAttribute> vertexAttributes;
583*c8dee2aaSAndroid Build Coastguard Worker     {
584*c8dee2aaSAndroid Build Coastguard Worker         auto arrayStride = create_vertex_attributes(step->vertexAttributes(),
585*c8dee2aaSAndroid Build Coastguard Worker                                                     0,
586*c8dee2aaSAndroid Build Coastguard Worker                                                     &vertexAttributes);
587*c8dee2aaSAndroid Build Coastguard Worker         auto& layout = vertexBufferLayouts[kVertexBufferIndex];
588*c8dee2aaSAndroid Build Coastguard Worker         if (arrayStride) {
589*c8dee2aaSAndroid Build Coastguard Worker             layout.arrayStride = arrayStride;
590*c8dee2aaSAndroid Build Coastguard Worker             layout.stepMode = wgpu::VertexStepMode::Vertex;
591*c8dee2aaSAndroid Build Coastguard Worker             layout.attributeCount = vertexAttributes.size();
592*c8dee2aaSAndroid Build Coastguard Worker             layout.attributes = vertexAttributes.data();
593*c8dee2aaSAndroid Build Coastguard Worker         } else {
594*c8dee2aaSAndroid Build Coastguard Worker             layout.arrayStride = 0;
595*c8dee2aaSAndroid Build Coastguard Worker             layout.stepMode = wgpu::VertexStepMode::VertexBufferNotUsed;
596*c8dee2aaSAndroid Build Coastguard Worker             layout.attributeCount = 0;
597*c8dee2aaSAndroid Build Coastguard Worker             layout.attributes = nullptr;
598*c8dee2aaSAndroid Build Coastguard Worker         }
599*c8dee2aaSAndroid Build Coastguard Worker     }
600*c8dee2aaSAndroid Build Coastguard Worker 
601*c8dee2aaSAndroid Build Coastguard Worker     // Instance buffer layout
602*c8dee2aaSAndroid Build Coastguard Worker     std::vector<wgpu::VertexAttribute> instanceAttributes;
603*c8dee2aaSAndroid Build Coastguard Worker     {
604*c8dee2aaSAndroid Build Coastguard Worker         auto arrayStride = create_vertex_attributes(step->instanceAttributes(),
605*c8dee2aaSAndroid Build Coastguard Worker                                                     step->vertexAttributes().size(),
606*c8dee2aaSAndroid Build Coastguard Worker                                                     &instanceAttributes);
607*c8dee2aaSAndroid Build Coastguard Worker         auto& layout = vertexBufferLayouts[kInstanceBufferIndex];
608*c8dee2aaSAndroid Build Coastguard Worker         if (arrayStride) {
609*c8dee2aaSAndroid Build Coastguard Worker             layout.arrayStride = arrayStride;
610*c8dee2aaSAndroid Build Coastguard Worker             layout.stepMode = wgpu::VertexStepMode::Instance;
611*c8dee2aaSAndroid Build Coastguard Worker             layout.attributeCount = instanceAttributes.size();
612*c8dee2aaSAndroid Build Coastguard Worker             layout.attributes = instanceAttributes.data();
613*c8dee2aaSAndroid Build Coastguard Worker         } else {
614*c8dee2aaSAndroid Build Coastguard Worker             layout.arrayStride = 0;
615*c8dee2aaSAndroid Build Coastguard Worker             layout.stepMode = wgpu::VertexStepMode::VertexBufferNotUsed;
616*c8dee2aaSAndroid Build Coastguard Worker             layout.attributeCount = 0;
617*c8dee2aaSAndroid Build Coastguard Worker             layout.attributes = nullptr;
618*c8dee2aaSAndroid Build Coastguard Worker         }
619*c8dee2aaSAndroid Build Coastguard Worker     }
620*c8dee2aaSAndroid Build Coastguard Worker 
621*c8dee2aaSAndroid Build Coastguard Worker     auto& vertex = descriptor.vertex;
622*c8dee2aaSAndroid Build Coastguard Worker     vertex.module = std::move(vsModule);
623*c8dee2aaSAndroid Build Coastguard Worker     vertex.entryPoint = "main";
624*c8dee2aaSAndroid Build Coastguard Worker     vertex.constantCount = 0;
625*c8dee2aaSAndroid Build Coastguard Worker     vertex.constants = nullptr;
626*c8dee2aaSAndroid Build Coastguard Worker     vertex.bufferCount = vertexBufferLayouts.size();
627*c8dee2aaSAndroid Build Coastguard Worker     vertex.buffers = vertexBufferLayouts.data();
628*c8dee2aaSAndroid Build Coastguard Worker 
629*c8dee2aaSAndroid Build Coastguard Worker     // Other state
630*c8dee2aaSAndroid Build Coastguard Worker     descriptor.primitive.frontFace = wgpu::FrontFace::CCW;
631*c8dee2aaSAndroid Build Coastguard Worker     descriptor.primitive.cullMode = wgpu::CullMode::None;
632*c8dee2aaSAndroid Build Coastguard Worker     switch (step->primitiveType()) {
633*c8dee2aaSAndroid Build Coastguard Worker         case PrimitiveType::kTriangles:
634*c8dee2aaSAndroid Build Coastguard Worker             descriptor.primitive.topology = wgpu::PrimitiveTopology::TriangleList;
635*c8dee2aaSAndroid Build Coastguard Worker             break;
636*c8dee2aaSAndroid Build Coastguard Worker         case PrimitiveType::kTriangleStrip:
637*c8dee2aaSAndroid Build Coastguard Worker             descriptor.primitive.topology = wgpu::PrimitiveTopology::TriangleStrip;
638*c8dee2aaSAndroid Build Coastguard Worker             descriptor.primitive.stripIndexFormat = wgpu::IndexFormat::Uint16;
639*c8dee2aaSAndroid Build Coastguard Worker             break;
640*c8dee2aaSAndroid Build Coastguard Worker         case PrimitiveType::kPoints:
641*c8dee2aaSAndroid Build Coastguard Worker             descriptor.primitive.topology = wgpu::PrimitiveTopology::PointList;
642*c8dee2aaSAndroid Build Coastguard Worker             break;
643*c8dee2aaSAndroid Build Coastguard Worker     }
644*c8dee2aaSAndroid Build Coastguard Worker 
645*c8dee2aaSAndroid Build Coastguard Worker     // Multisampled state
646*c8dee2aaSAndroid Build Coastguard Worker     descriptor.multisample.count = renderPassDesc.fSampleCount;
647*c8dee2aaSAndroid Build Coastguard Worker     descriptor.multisample.mask = 0xFFFFFFFF;
648*c8dee2aaSAndroid Build Coastguard Worker     descriptor.multisample.alphaToCoverageEnabled = false;
649*c8dee2aaSAndroid Build Coastguard Worker 
650*c8dee2aaSAndroid Build Coastguard Worker     const bool forPrecompilation =
651*c8dee2aaSAndroid Build Coastguard Worker             SkToBool(pipelineCreationFlags & PipelineCreationFlags::kForPrecompilation);
652*c8dee2aaSAndroid Build Coastguard Worker     // For Dawn, we want Precompilation to happen synchronously
653*c8dee2aaSAndroid Build Coastguard Worker     const bool useAsync = caps.useAsyncPipelineCreation() && !forPrecompilation;
654*c8dee2aaSAndroid Build Coastguard Worker 
655*c8dee2aaSAndroid Build Coastguard Worker     auto asyncCreation = std::make_unique<AsyncPipelineCreation>();
656*c8dee2aaSAndroid Build Coastguard Worker #if SK_HISTOGRAMS_ENABLED
657*c8dee2aaSAndroid Build Coastguard Worker     asyncCreation->fStartTime = skgpu::StdSteadyClock::now();
658*c8dee2aaSAndroid Build Coastguard Worker     asyncCreation->fFromPrecompile = forPrecompilation;
659*c8dee2aaSAndroid Build Coastguard Worker     asyncCreation->fAsynchronous = useAsync;
660*c8dee2aaSAndroid Build Coastguard Worker #endif
661*c8dee2aaSAndroid Build Coastguard Worker 
662*c8dee2aaSAndroid Build Coastguard Worker     if (useAsync) {
663*c8dee2aaSAndroid Build Coastguard Worker #if defined(__EMSCRIPTEN__)
664*c8dee2aaSAndroid Build Coastguard Worker         // We shouldn't use CreateRenderPipelineAsync in wasm.
665*c8dee2aaSAndroid Build Coastguard Worker         SKGPU_LOG_F("CreateRenderPipelineAsync shouldn't be used in WASM");
666*c8dee2aaSAndroid Build Coastguard Worker #else
667*c8dee2aaSAndroid Build Coastguard Worker         asyncCreation->fFuture = device.CreateRenderPipelineAsync(
668*c8dee2aaSAndroid Build Coastguard Worker                 &descriptor,
669*c8dee2aaSAndroid Build Coastguard Worker                 wgpu::CallbackMode::WaitAnyOnly,
670*c8dee2aaSAndroid Build Coastguard Worker                 [asyncCreationPtr = asyncCreation.get()](wgpu::CreatePipelineAsyncStatus status,
671*c8dee2aaSAndroid Build Coastguard Worker                                                          wgpu::RenderPipeline pipeline,
672*c8dee2aaSAndroid Build Coastguard Worker                                                          char const* message) {
673*c8dee2aaSAndroid Build Coastguard Worker                     if (status != wgpu::CreatePipelineAsyncStatus::Success) {
674*c8dee2aaSAndroid Build Coastguard Worker                         SKGPU_LOG_E("Failed to create render pipeline (%d): %s",
675*c8dee2aaSAndroid Build Coastguard Worker                                     static_cast<int>(status),
676*c8dee2aaSAndroid Build Coastguard Worker                                     message);
677*c8dee2aaSAndroid Build Coastguard Worker                         // invalidate AsyncPipelineCreation pointer to signal that this pipeline has
678*c8dee2aaSAndroid Build Coastguard Worker                         // failed.
679*c8dee2aaSAndroid Build Coastguard Worker                         asyncCreationPtr->fRenderPipeline = nullptr;
680*c8dee2aaSAndroid Build Coastguard Worker                     } else {
681*c8dee2aaSAndroid Build Coastguard Worker                         asyncCreationPtr->fRenderPipeline = std::move(pipeline);
682*c8dee2aaSAndroid Build Coastguard Worker                     }
683*c8dee2aaSAndroid Build Coastguard Worker 
684*c8dee2aaSAndroid Build Coastguard Worker                     asyncCreationPtr->fFinished = true;
685*c8dee2aaSAndroid Build Coastguard Worker 
686*c8dee2aaSAndroid Build Coastguard Worker                     log_pipeline_creation(asyncCreationPtr);
687*c8dee2aaSAndroid Build Coastguard Worker                 });
688*c8dee2aaSAndroid Build Coastguard Worker #endif
689*c8dee2aaSAndroid Build Coastguard Worker     } else {
690*c8dee2aaSAndroid Build Coastguard Worker         std::optional<DawnErrorChecker> errorChecker;
691*c8dee2aaSAndroid Build Coastguard Worker         if (sharedContext->dawnCaps()->allowScopedErrorChecks()) {
692*c8dee2aaSAndroid Build Coastguard Worker             errorChecker.emplace(sharedContext);
693*c8dee2aaSAndroid Build Coastguard Worker         }
694*c8dee2aaSAndroid Build Coastguard Worker         asyncCreation->fRenderPipeline = device.CreateRenderPipeline(&descriptor);
695*c8dee2aaSAndroid Build Coastguard Worker         asyncCreation->fFinished = true;
696*c8dee2aaSAndroid Build Coastguard Worker 
697*c8dee2aaSAndroid Build Coastguard Worker         if (errorChecker.has_value() && errorChecker->popErrorScopes() != DawnErrorType::kNoError) {
698*c8dee2aaSAndroid Build Coastguard Worker             asyncCreation->fRenderPipeline = nullptr;
699*c8dee2aaSAndroid Build Coastguard Worker         }
700*c8dee2aaSAndroid Build Coastguard Worker 
701*c8dee2aaSAndroid Build Coastguard Worker         log_pipeline_creation(asyncCreation.get());
702*c8dee2aaSAndroid Build Coastguard Worker     }
703*c8dee2aaSAndroid Build Coastguard Worker 
704*c8dee2aaSAndroid Build Coastguard Worker     PipelineInfo pipelineInfo{*shaderInfo, pipelineCreationFlags};
705*c8dee2aaSAndroid Build Coastguard Worker #if defined(GPU_TEST_UTILS)
706*c8dee2aaSAndroid Build Coastguard Worker     pipelineInfo.fNativeVertexShader = std::move(vsCode);
707*c8dee2aaSAndroid Build Coastguard Worker     pipelineInfo.fNativeFragmentShader = std::move(fsCode);
708*c8dee2aaSAndroid Build Coastguard Worker #endif
709*c8dee2aaSAndroid Build Coastguard Worker 
710*c8dee2aaSAndroid Build Coastguard Worker     return sk_sp<DawnGraphicsPipeline>(
711*c8dee2aaSAndroid Build Coastguard Worker             new DawnGraphicsPipeline(sharedContext,
712*c8dee2aaSAndroid Build Coastguard Worker                                      pipelineInfo,
713*c8dee2aaSAndroid Build Coastguard Worker                                      std::move(asyncCreation),
714*c8dee2aaSAndroid Build Coastguard Worker                                      std::move(groupLayouts),
715*c8dee2aaSAndroid Build Coastguard Worker                                      step->primitiveType(),
716*c8dee2aaSAndroid Build Coastguard Worker                                      depthStencilSettings.fStencilReferenceValue,
717*c8dee2aaSAndroid Build Coastguard Worker                                      std::move(immutableSamplers)));
718*c8dee2aaSAndroid Build Coastguard Worker }
719*c8dee2aaSAndroid Build Coastguard Worker 
DawnGraphicsPipeline(const skgpu::graphite::SharedContext * sharedContext,const PipelineInfo & pipelineInfo,std::unique_ptr<AsyncPipelineCreation> asyncCreationInfo,BindGroupLayouts groupLayouts,PrimitiveType primitiveType,uint32_t refValue,skia_private::TArray<sk_sp<DawnSampler>> immutableSamplers)720*c8dee2aaSAndroid Build Coastguard Worker DawnGraphicsPipeline::DawnGraphicsPipeline(
721*c8dee2aaSAndroid Build Coastguard Worker         const skgpu::graphite::SharedContext* sharedContext,
722*c8dee2aaSAndroid Build Coastguard Worker         const PipelineInfo& pipelineInfo,
723*c8dee2aaSAndroid Build Coastguard Worker         std::unique_ptr<AsyncPipelineCreation> asyncCreationInfo,
724*c8dee2aaSAndroid Build Coastguard Worker         BindGroupLayouts groupLayouts,
725*c8dee2aaSAndroid Build Coastguard Worker         PrimitiveType primitiveType,
726*c8dee2aaSAndroid Build Coastguard Worker         uint32_t refValue,
727*c8dee2aaSAndroid Build Coastguard Worker         skia_private::TArray<sk_sp<DawnSampler>> immutableSamplers)
728*c8dee2aaSAndroid Build Coastguard Worker     : GraphicsPipeline(sharedContext, pipelineInfo)
729*c8dee2aaSAndroid Build Coastguard Worker     , fAsyncPipelineCreation(std::move(asyncCreationInfo))
730*c8dee2aaSAndroid Build Coastguard Worker     , fGroupLayouts(std::move(groupLayouts))
731*c8dee2aaSAndroid Build Coastguard Worker     , fPrimitiveType(primitiveType)
732*c8dee2aaSAndroid Build Coastguard Worker     , fStencilReferenceValue(refValue)
733*c8dee2aaSAndroid Build Coastguard Worker     , fImmutableSamplers(std::move(immutableSamplers)) {}
734*c8dee2aaSAndroid Build Coastguard Worker 
~DawnGraphicsPipeline()735*c8dee2aaSAndroid Build Coastguard Worker DawnGraphicsPipeline::~DawnGraphicsPipeline() {
736*c8dee2aaSAndroid Build Coastguard Worker     this->freeGpuData();
737*c8dee2aaSAndroid Build Coastguard Worker }
738*c8dee2aaSAndroid Build Coastguard Worker 
freeGpuData()739*c8dee2aaSAndroid Build Coastguard Worker void DawnGraphicsPipeline::freeGpuData() {
740*c8dee2aaSAndroid Build Coastguard Worker     // Wait for async creation to finish before we can destroy this object.
741*c8dee2aaSAndroid Build Coastguard Worker     (void)this->dawnRenderPipeline();
742*c8dee2aaSAndroid Build Coastguard Worker     fAsyncPipelineCreation = nullptr;
743*c8dee2aaSAndroid Build Coastguard Worker }
744*c8dee2aaSAndroid Build Coastguard Worker 
dawnRenderPipeline() const745*c8dee2aaSAndroid Build Coastguard Worker const wgpu::RenderPipeline& DawnGraphicsPipeline::dawnRenderPipeline() const {
746*c8dee2aaSAndroid Build Coastguard Worker     if (!fAsyncPipelineCreation) {
747*c8dee2aaSAndroid Build Coastguard Worker         static const wgpu::RenderPipeline kNullPipeline = nullptr;
748*c8dee2aaSAndroid Build Coastguard Worker         return kNullPipeline;
749*c8dee2aaSAndroid Build Coastguard Worker     }
750*c8dee2aaSAndroid Build Coastguard Worker     if (fAsyncPipelineCreation->fFinished) {
751*c8dee2aaSAndroid Build Coastguard Worker         return fAsyncPipelineCreation->fRenderPipeline;
752*c8dee2aaSAndroid Build Coastguard Worker     }
753*c8dee2aaSAndroid Build Coastguard Worker #if defined(__EMSCRIPTEN__)
754*c8dee2aaSAndroid Build Coastguard Worker     // We shouldn't use CreateRenderPipelineAsync in wasm.
755*c8dee2aaSAndroid Build Coastguard Worker     SKGPU_LOG_F("CreateRenderPipelineAsync shouldn't be used in WASM");
756*c8dee2aaSAndroid Build Coastguard Worker #else
757*c8dee2aaSAndroid Build Coastguard Worker     wgpu::FutureWaitInfo waitInfo{};
758*c8dee2aaSAndroid Build Coastguard Worker     waitInfo.future = fAsyncPipelineCreation->fFuture;
759*c8dee2aaSAndroid Build Coastguard Worker     const auto& instance = static_cast<const DawnSharedContext*>(sharedContext())
760*c8dee2aaSAndroid Build Coastguard Worker                                    ->device()
761*c8dee2aaSAndroid Build Coastguard Worker                                    .GetAdapter()
762*c8dee2aaSAndroid Build Coastguard Worker                                    .GetInstance();
763*c8dee2aaSAndroid Build Coastguard Worker 
764*c8dee2aaSAndroid Build Coastguard Worker     [[maybe_unused]] auto status =
765*c8dee2aaSAndroid Build Coastguard Worker             instance.WaitAny(1, &waitInfo, /*timeoutNS=*/std::numeric_limits<uint64_t>::max());
766*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(status == wgpu::WaitStatus::Success);
767*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(waitInfo.completed);
768*c8dee2aaSAndroid Build Coastguard Worker #endif
769*c8dee2aaSAndroid Build Coastguard Worker 
770*c8dee2aaSAndroid Build Coastguard Worker     return fAsyncPipelineCreation->fRenderPipeline;
771*c8dee2aaSAndroid Build Coastguard Worker }
772*c8dee2aaSAndroid Build Coastguard Worker 
773*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite
774