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