Flutter Engine
The Flutter Engine
DawnGraphicsPipeline.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
12#include "src/gpu/Swizzle.h"
27#include "src/sksl/SkSLUtil.h"
29
30#include <vector>
31
32namespace skgpu::graphite {
33
34namespace {
35
36inline wgpu::VertexFormat attribute_type_to_dawn(VertexAttribType type) {
37 switch (type) {
39 return wgpu::VertexFormat::Float32;
41 return wgpu::VertexFormat::Float32x2;
43 return wgpu::VertexFormat::Float32x3;
45 return wgpu::VertexFormat::Float32x4;
47 return wgpu::VertexFormat::Float16x2;
49 return wgpu::VertexFormat::Float16x4;
51 return wgpu::VertexFormat::Sint32x2;
53 return wgpu::VertexFormat::Sint32x3;
55 return wgpu::VertexFormat::Sint32x4;
57 return wgpu::VertexFormat::Sint8x2;
59 return wgpu::VertexFormat::Sint8x4;
61 return wgpu::VertexFormat::Uint8x2;
63 return wgpu::VertexFormat::Uint8x4;
65 return wgpu::VertexFormat::Unorm8x4;
67 return wgpu::VertexFormat::Sint16x2;
69 return wgpu::VertexFormat::Sint16x4;
71 return wgpu::VertexFormat::Uint16x2;
73 return wgpu::VertexFormat::Unorm16x2;
75 return wgpu::VertexFormat::Sint32;
77 return wgpu::VertexFormat::Uint32;
79 return wgpu::VertexFormat::Unorm16x4;
85 // Not supported.
86 break;
87 }
89}
90
91wgpu::CompareFunction compare_op_to_dawn(CompareOp op) {
92 switch (op) {
94 return wgpu::CompareFunction::Always;
96 return wgpu::CompareFunction::Never;
98 return wgpu::CompareFunction::Greater;
100 return wgpu::CompareFunction::GreaterEqual;
101 case CompareOp::kLess:
102 return wgpu::CompareFunction::Less;
104 return wgpu::CompareFunction::LessEqual;
106 return wgpu::CompareFunction::Equal;
108 return wgpu::CompareFunction::NotEqual;
109 }
111}
112
113wgpu::StencilOperation stencil_op_to_dawn(StencilOp op) {
114 switch (op) {
115 case StencilOp::kKeep:
116 return wgpu::StencilOperation::Keep;
117 case StencilOp::kZero:
118 return wgpu::StencilOperation::Zero;
120 return wgpu::StencilOperation::Replace;
122 return wgpu::StencilOperation::Invert;
124 return wgpu::StencilOperation::IncrementWrap;
126 return wgpu::StencilOperation::DecrementWrap;
128 return wgpu::StencilOperation::IncrementClamp;
130 return wgpu::StencilOperation::DecrementClamp;
131 }
133}
134
135wgpu::StencilFaceState stencil_face_to_dawn(DepthStencilSettings::Face face) {
136 wgpu::StencilFaceState state;
137 state.compare = compare_op_to_dawn(face.fCompareOp);
138 state.failOp = stencil_op_to_dawn(face.fStencilFailOp);
139 state.depthFailOp = stencil_op_to_dawn(face.fDepthFailOp);
140 state.passOp = stencil_op_to_dawn(face.fDepthStencilPassOp);
141 return state;
142}
143
144size_t create_vertex_attributes(SkSpan<const Attribute> attrs,
145 int shaderLocationOffset,
146 std::vector<wgpu::VertexAttribute>* out) {
147 SkASSERT(out && out->empty());
148 out->resize(attrs.size());
149 size_t vertexAttributeOffset = 0;
150 int attributeIndex = 0;
151 for (const auto& attr : attrs) {
152 wgpu::VertexAttribute& vertexAttribute = (*out)[attributeIndex];
153 vertexAttribute.format = attribute_type_to_dawn(attr.cpuType());
154 vertexAttribute.offset = vertexAttributeOffset;
155 vertexAttribute.shaderLocation = shaderLocationOffset + attributeIndex;
156 vertexAttributeOffset += attr.sizeAlign4();
157 attributeIndex++;
158 }
159 return vertexAttributeOffset;
160}
161
162// TODO: share this w/ Ganesh dawn backend?
163static wgpu::BlendFactor blend_coeff_to_dawn_blend(const DawnCaps& caps, skgpu::BlendCoeff coeff) {
164#if defined(__EMSCRIPTEN__)
165#define VALUE_IF_DSB_OR_ZERO(VALUE) wgpu::BlendFactor::Zero
166#else
167#define VALUE_IF_DSB_OR_ZERO(VALUE) \
168 ((caps.shaderCaps()->fDualSourceBlendingSupport) ? (VALUE) : wgpu::BlendFactor::Zero)
169#endif
170 switch (coeff) {
172 return wgpu::BlendFactor::Zero;
174 return wgpu::BlendFactor::One;
176 return wgpu::BlendFactor::Src;
178 return wgpu::BlendFactor::OneMinusSrc;
180 return wgpu::BlendFactor::Dst;
182 return wgpu::BlendFactor::OneMinusDst;
184 return wgpu::BlendFactor::SrcAlpha;
186 return wgpu::BlendFactor::OneMinusSrcAlpha;
188 return wgpu::BlendFactor::DstAlpha;
190 return wgpu::BlendFactor::OneMinusDstAlpha;
192 return wgpu::BlendFactor::Constant;
194 return wgpu::BlendFactor::OneMinusConstant;
196 return VALUE_IF_DSB_OR_ZERO(wgpu::BlendFactor::Src1);
198 return VALUE_IF_DSB_OR_ZERO(wgpu::BlendFactor::OneMinusSrc1);
200 return VALUE_IF_DSB_OR_ZERO(wgpu::BlendFactor::Src1Alpha);
202 return VALUE_IF_DSB_OR_ZERO(wgpu::BlendFactor::OneMinusSrc1Alpha);
204 return wgpu::BlendFactor::Zero;
205 }
207#undef VALUE_IF_DSB_OR_ZERO
208}
209
210static wgpu::BlendFactor blend_coeff_to_dawn_blend_for_alpha(const DawnCaps& caps,
211 skgpu::BlendCoeff coeff) {
212 switch (coeff) {
213 // Force all srcColor used in alpha slot to alpha version.
215 return wgpu::BlendFactor::SrcAlpha;
217 return wgpu::BlendFactor::OneMinusSrcAlpha;
219 return wgpu::BlendFactor::DstAlpha;
221 return wgpu::BlendFactor::OneMinusDstAlpha;
222 default:
223 return blend_coeff_to_dawn_blend(caps, coeff);
224 }
225}
226
227// TODO: share this w/ Ganesh Metal backend?
228static wgpu::BlendOperation blend_equation_to_dawn_blend_op(skgpu::BlendEquation equation) {
229 static const wgpu::BlendOperation gTable[] = {
230 wgpu::BlendOperation::Add, // skgpu::BlendEquation::kAdd
231 wgpu::BlendOperation::Subtract, // skgpu::BlendEquation::kSubtract
232 wgpu::BlendOperation::ReverseSubtract, // skgpu::BlendEquation::kReverseSubtract
233 };
234 static_assert(std::size(gTable) == (int)skgpu::BlendEquation::kFirstAdvanced);
235 static_assert(0 == (int)skgpu::BlendEquation::kAdd);
236 static_assert(1 == (int)skgpu::BlendEquation::kSubtract);
237 static_assert(2 == (int)skgpu::BlendEquation::kReverseSubtract);
238
239 SkASSERT((unsigned)equation < skgpu::kBlendEquationCnt);
240 return gTable[(int)equation];
241}
242
243struct AsyncPipelineCreationBase {
244 wgpu::RenderPipeline fRenderPipeline;
245 bool fFinished = false;
246};
247
248} // anonymous namespace
249
250#if defined(__EMSCRIPTEN__)
251// For wasm, we don't use async compilation.
252struct DawnGraphicsPipeline::AsyncPipelineCreation : public AsyncPipelineCreationBase {};
253#else
254struct DawnGraphicsPipeline::AsyncPipelineCreation : public AsyncPipelineCreationBase {
255 wgpu::Future fFuture;
256};
257#endif
258
259// static
261 DawnResourceProvider* resourceProvider,
262 const RuntimeEffectDictionary* runtimeDict,
263 const GraphicsPipelineDesc& pipelineDesc,
264 const RenderPassDesc& renderPassDesc) {
265 const DawnCaps& caps = *static_cast<const DawnCaps*>(sharedContext->caps());
266 const auto& device = sharedContext->device();
267
268 SkSL::Program::Interface vsInterface, fsInterface;
270
271 settings.fForceNoRTFlip = true;
272
273 ShaderErrorHandler* errorHandler = caps.shaderErrorHandler();
274
276 const bool useStorageBuffers = caps.storageBufferPreferred();
277
278 std::string vsCode, fsCode;
279 wgpu::ShaderModule fsModule, vsModule;
280
281 // Some steps just render depth buffer but not color buffer, so the fragment
282 // shader is null.
283 UniquePaintParamsID paintID = pipelineDesc.paintParamsID();
284 FragSkSLInfo fsSkSLInfo = BuildFragmentSkSL(&caps,
286 runtimeDict,
287 step,
288 paintID,
289 useStorageBuffers,
290 renderPassDesc.fWriteSwizzle);
291 std::string& fsSkSL = fsSkSLInfo.fSkSL;
292 const BlendInfo& blendInfo = fsSkSLInfo.fBlendInfo;
293 const bool localCoordsNeeded = fsSkSLInfo.fRequiresLocalCoords;
294 const int numTexturesAndSamplers = fsSkSLInfo.fNumTexturesAndSamplers;
295
296 bool hasFragmentSkSL = !fsSkSL.empty();
297 if (hasFragmentSkSL) {
298 if (!skgpu::SkSLToWGSL(caps.shaderCaps(),
299 fsSkSL,
301 settings,
302 &fsCode,
303 &fsInterface,
304 errorHandler)) {
305 return {};
306 }
307 if (!DawnCompileWGSLShaderModule(sharedContext, fsSkSLInfo.fLabel.c_str(), fsCode,
308 &fsModule, errorHandler)) {
309 return {};
310 }
311 }
312
314 step,
315 useStorageBuffers,
316 localCoordsNeeded);
317 const std::string& vsSkSL = vsSkSLInfo.fSkSL;
318 if (!skgpu::SkSLToWGSL(caps.shaderCaps(),
319 vsSkSL,
321 settings,
322 &vsCode,
323 &vsInterface,
324 errorHandler)) {
325 return {};
326 }
327 if (!DawnCompileWGSLShaderModule(sharedContext, vsSkSLInfo.fLabel.c_str(), vsCode,
328 &vsModule, errorHandler)) {
329 return {};
330 }
331
332 std::string pipelineLabel =
333 GetPipelineLabel(sharedContext->shaderCodeDictionary(), renderPassDesc, step, paintID);
334 wgpu::RenderPipelineDescriptor descriptor;
335 // Always set the label for pipelines, dawn may need it for tracing.
336 descriptor.label = pipelineLabel.c_str();
337
338 // Fragment state
339 skgpu::BlendEquation equation = blendInfo.fEquation;
340 skgpu::BlendCoeff srcCoeff = blendInfo.fSrcBlend;
341 skgpu::BlendCoeff dstCoeff = blendInfo.fDstBlend;
342 bool blendOn = !skgpu::BlendShouldDisable(equation, srcCoeff, dstCoeff);
343
344 wgpu::BlendState blend;
345 if (blendOn) {
346 blend.color.operation = blend_equation_to_dawn_blend_op(equation);
347 blend.color.srcFactor = blend_coeff_to_dawn_blend(caps, srcCoeff);
348 blend.color.dstFactor = blend_coeff_to_dawn_blend(caps, dstCoeff);
349 blend.alpha.operation = blend_equation_to_dawn_blend_op(equation);
350 blend.alpha.srcFactor = blend_coeff_to_dawn_blend_for_alpha(caps, srcCoeff);
351 blend.alpha.dstFactor = blend_coeff_to_dawn_blend_for_alpha(caps, dstCoeff);
352 }
353
354 wgpu::ColorTargetState colorTarget;
355 colorTarget.format =
356 renderPassDesc.fColorAttachment.fTextureInfo.dawnTextureSpec().getViewFormat();
357 colorTarget.blend = blendOn ? &blend : nullptr;
358 colorTarget.writeMask = blendInfo.fWritesColor && hasFragmentSkSL ? wgpu::ColorWriteMask::All
359 : wgpu::ColorWriteMask::None;
360
361#if !defined(__EMSCRIPTEN__)
362 const bool loadMsaaFromResolve =
365 // Special case: a render pass loading resolve texture requires additional settings for the
366 // pipeline to make it compatible.
367 wgpu::ColorTargetStateExpandResolveTextureDawn pipelineMSAALoadResolveTextureDesc;
368 if (loadMsaaFromResolve && sharedContext->dawnCaps()->resolveTextureLoadOp().has_value()) {
369 SkASSERT(device.HasFeature(wgpu::FeatureName::DawnLoadResolveTexture));
370 colorTarget.nextInChain = &pipelineMSAALoadResolveTextureDesc;
371 pipelineMSAALoadResolveTextureDesc.enabled = true;
372 }
373#endif
374
375 wgpu::FragmentState fragment;
376 // Dawn doesn't allow having a color attachment but without fragment shader, so have to use a
377 // noop fragment shader, if fragment shader is null.
378 fragment.module = hasFragmentSkSL ? std::move(fsModule) : sharedContext->noopFragment();
379 fragment.entryPoint = "main";
380 fragment.targetCount = 1;
381 fragment.targets = &colorTarget;
382 descriptor.fragment = &fragment;
383
384 // Depth stencil state
385 const auto& depthStencilSettings = step->depthStencilSettings();
386 SkASSERT(depthStencilSettings.fDepthTestEnabled ||
387 depthStencilSettings.fDepthCompareOp == CompareOp::kAlways);
388 wgpu::DepthStencilState depthStencil;
389 if (renderPassDesc.fDepthStencilAttachment.fTextureInfo.isValid()) {
390 wgpu::TextureFormat dsFormat =
391 renderPassDesc.fDepthStencilAttachment.fTextureInfo.dawnTextureSpec()
392 .getViewFormat();
393 depthStencil.format =
394 DawnFormatIsDepthOrStencil(dsFormat) ? dsFormat : wgpu::TextureFormat::Undefined;
395 if (depthStencilSettings.fDepthTestEnabled) {
396 depthStencil.depthWriteEnabled = depthStencilSettings.fDepthWriteEnabled;
397 }
398 depthStencil.depthCompare = compare_op_to_dawn(depthStencilSettings.fDepthCompareOp);
399
400 // Dawn validation fails if the stencil state is non-default and the
401 // format doesn't have the stencil aspect.
402 if (DawnFormatIsStencil(dsFormat) && depthStencilSettings.fStencilTestEnabled) {
403 depthStencil.stencilFront = stencil_face_to_dawn(depthStencilSettings.fFrontStencil);
404 depthStencil.stencilBack = stencil_face_to_dawn(depthStencilSettings.fBackStencil);
405 depthStencil.stencilReadMask = depthStencilSettings.fFrontStencil.fReadMask;
406 depthStencil.stencilWriteMask = depthStencilSettings.fFrontStencil.fWriteMask;
407 }
408
409 descriptor.depthStencil = &depthStencil;
410 }
411
412 // Pipeline layout
413 BindGroupLayouts groupLayouts;
414 {
415 groupLayouts[0] = resourceProvider->getOrCreateUniformBuffersBindGroupLayout();
416 if (!groupLayouts[0]) {
417 return {};
418 }
419
420 bool hasFragmentSamplers = hasFragmentSkSL && numTexturesAndSamplers > 0;
421 if (hasFragmentSamplers) {
422 if (numTexturesAndSamplers == 2) {
423 // Common case: single texture + sampler.
424 groupLayouts[1] =
426 } else {
427 std::vector<wgpu::BindGroupLayoutEntry> entries(numTexturesAndSamplers);
428 for (int i = 0; i < numTexturesAndSamplers;) {
429 entries[i].binding = static_cast<uint32_t>(i);
430 entries[i].visibility = wgpu::ShaderStage::Fragment;
431 entries[i].sampler.type = wgpu::SamplerBindingType::Filtering;
432 ++i;
433 entries[i].binding = i;
434 entries[i].visibility = wgpu::ShaderStage::Fragment;
435 entries[i].texture.sampleType = wgpu::TextureSampleType::Float;
436 entries[i].texture.viewDimension = wgpu::TextureViewDimension::e2D;
437 entries[i].texture.multisampled = false;
438 ++i;
439 }
440
441 wgpu::BindGroupLayoutDescriptor groupLayoutDesc;
443 groupLayoutDesc.label = vsSkSLInfo.fLabel.c_str();
444 }
445 groupLayoutDesc.entryCount = entries.size();
446 groupLayoutDesc.entries = entries.data();
447 groupLayouts[1] = device.CreateBindGroupLayout(&groupLayoutDesc);
448 }
449 if (!groupLayouts[1]) {
450 return {};
451 }
452 }
453
454 wgpu::PipelineLayoutDescriptor layoutDesc;
456 layoutDesc.label = fsSkSLInfo.fLabel.c_str();
457 }
458 layoutDesc.bindGroupLayoutCount =
459 hasFragmentSamplers ? groupLayouts.size() : groupLayouts.size() - 1;
460 layoutDesc.bindGroupLayouts = groupLayouts.data();
461 auto layout = device.CreatePipelineLayout(&layoutDesc);
462 if (!layout) {
463 return {};
464 }
465 descriptor.layout = std::move(layout);
466 }
467
468 // Vertex state
469 std::array<wgpu::VertexBufferLayout, kNumVertexBuffers> vertexBufferLayouts;
470 // Vertex buffer layout
471 std::vector<wgpu::VertexAttribute> vertexAttributes;
472 {
473 auto arrayStride = create_vertex_attributes(step->vertexAttributes(),
474 0,
475 &vertexAttributes);
476 auto& layout = vertexBufferLayouts[kVertexBufferIndex];
477 if (arrayStride) {
478 layout.arrayStride = arrayStride;
479 layout.stepMode = wgpu::VertexStepMode::Vertex;
480 layout.attributeCount = vertexAttributes.size();
481 layout.attributes = vertexAttributes.data();
482 } else {
483 layout.arrayStride = 0;
484 layout.stepMode = wgpu::VertexStepMode::VertexBufferNotUsed;
485 layout.attributeCount = 0;
486 layout.attributes = nullptr;
487 }
488 }
489
490 // Instance buffer layout
491 std::vector<wgpu::VertexAttribute> instanceAttributes;
492 {
493 auto arrayStride = create_vertex_attributes(step->instanceAttributes(),
494 step->vertexAttributes().size(),
495 &instanceAttributes);
496 auto& layout = vertexBufferLayouts[kInstanceBufferIndex];
497 if (arrayStride) {
498 layout.arrayStride = arrayStride;
499 layout.stepMode = wgpu::VertexStepMode::Instance;
500 layout.attributeCount = instanceAttributes.size();
501 layout.attributes = instanceAttributes.data();
502 } else {
503 layout.arrayStride = 0;
504 layout.stepMode = wgpu::VertexStepMode::VertexBufferNotUsed;
505 layout.attributeCount = 0;
506 layout.attributes = nullptr;
507 }
508 }
509
510 auto& vertex = descriptor.vertex;
511 vertex.module = std::move(vsModule);
512 vertex.entryPoint = "main";
513 vertex.constantCount = 0;
514 vertex.constants = nullptr;
515 vertex.bufferCount = vertexBufferLayouts.size();
516 vertex.buffers = vertexBufferLayouts.data();
517
518 // Other state
519 descriptor.primitive.frontFace = wgpu::FrontFace::CCW;
520 descriptor.primitive.cullMode = wgpu::CullMode::None;
521 switch (step->primitiveType()) {
523 descriptor.primitive.topology = wgpu::PrimitiveTopology::TriangleList;
524 break;
526 descriptor.primitive.topology = wgpu::PrimitiveTopology::TriangleStrip;
527 descriptor.primitive.stripIndexFormat = wgpu::IndexFormat::Uint16;
528 break;
530 descriptor.primitive.topology = wgpu::PrimitiveTopology::PointList;
531 break;
532 }
533
534 // Multisampled state
535 descriptor.multisample.count = renderPassDesc.fSampleCount;
536 descriptor.multisample.mask = 0xFFFFFFFF;
537 descriptor.multisample.alphaToCoverageEnabled = false;
538
539 auto asyncCreation = std::make_unique<AsyncPipelineCreation>();
540
541 if (caps.useAsyncPipelineCreation()) {
542#if defined(__EMSCRIPTEN__)
543 // We shouldn't use CreateRenderPipelineAsync in wasm.
544 SKGPU_LOG_F("CreateRenderPipelineAsync shouldn't be used in WASM");
545#else
546 asyncCreation->fFuture = device.CreateRenderPipelineAsync(
547 &descriptor,
548 wgpu::CallbackMode::WaitAnyOnly,
549 [asyncCreationPtr = asyncCreation.get()](wgpu::CreatePipelineAsyncStatus status,
550 wgpu::RenderPipeline pipeline,
551 char const* message) {
552 if (status != wgpu::CreatePipelineAsyncStatus::Success) {
553 SKGPU_LOG_E("Failed to create render pipeline (%d): %s",
554 static_cast<int>(status),
555 message);
556 // invalidate AsyncPipelineCreation pointer to signal that this pipeline has
557 // failed.
558 asyncCreationPtr->fRenderPipeline = nullptr;
559 } else {
560 asyncCreationPtr->fRenderPipeline = std::move(pipeline);
561 }
562
563 asyncCreationPtr->fFinished = true;
564 });
565#endif
566 } else {
567 std::optional<DawnErrorChecker> errorChecker;
568 if (sharedContext->dawnCaps()->allowScopedErrorChecks()) {
569 errorChecker.emplace(sharedContext);
570 }
571 asyncCreation->fRenderPipeline = device.CreateRenderPipeline(&descriptor);
572 asyncCreation->fFinished = true;
573
574 if (errorChecker.has_value() && errorChecker->popErrorScopes() != DawnErrorType::kNoError) {
575 asyncCreation->fRenderPipeline = nullptr;
576 }
577 }
578#if defined(GRAPHITE_TEST_UTILS)
579 GraphicsPipeline::PipelineInfo pipelineInfo = {pipelineDesc.renderStepID(),
580 pipelineDesc.paintParamsID(),
581 std::move(vsSkSL),
582 std::move(fsSkSL),
583 std::move(vsCode),
584 std::move(fsCode)};
585 GraphicsPipeline::PipelineInfo* pipelineInfoPtr = &pipelineInfo;
586#else
587 GraphicsPipeline::PipelineInfo* pipelineInfoPtr = nullptr;
588#endif
589
591 new DawnGraphicsPipeline(sharedContext,
592 pipelineInfoPtr,
593 std::move(asyncCreation),
594 std::move(groupLayouts),
595 step->primitiveType(),
596 depthStencilSettings.fStencilReferenceValue,
597 /*hasStepUniforms=*/!step->uniforms().empty(),
598 /*hasPaintUniforms=*/fsSkSLInfo.fNumPaintUniforms > 0,
599 /*hasGradientbuffer=*/fsSkSLInfo.fHasGradientBuffer,
600 numTexturesAndSamplers));
601}
602
603DawnGraphicsPipeline::DawnGraphicsPipeline(const skgpu::graphite::SharedContext* sharedContext,
604 PipelineInfo* pipelineInfo,
605 std::unique_ptr<AsyncPipelineCreation> asyncCreationInfo,
606 BindGroupLayouts groupLayouts,
607 PrimitiveType primitiveType,
608 uint32_t refValue,
609 bool hasStepUniforms,
610 bool hasPaintUniforms,
611 bool hasGradientBuffer,
612 int numFragmentTexturesAndSamplers)
613 : GraphicsPipeline(sharedContext, pipelineInfo)
614 , fAsyncPipelineCreation(std::move(asyncCreationInfo))
615 , fGroupLayouts(std::move(groupLayouts))
616 , fPrimitiveType(primitiveType)
617 , fStencilReferenceValue(refValue)
618 , fHasStepUniforms(hasStepUniforms)
619 , fHasPaintUniforms(hasPaintUniforms)
620 , fHasGradientBuffer(hasGradientBuffer)
621 , fNumFragmentTexturesAndSamplers(numFragmentTexturesAndSamplers) {}
622
624 this->freeGpuData();
625}
626
627void DawnGraphicsPipeline::freeGpuData() {
628 // Wait for async creation to finish before we can destroy this object.
629 (void)this->dawnRenderPipeline();
630 fAsyncPipelineCreation = nullptr;
631}
632
633const wgpu::RenderPipeline& DawnGraphicsPipeline::dawnRenderPipeline() const {
634 if (!fAsyncPipelineCreation) {
635 static const wgpu::RenderPipeline kNullPipeline = nullptr;
636 return kNullPipeline;
637 }
638 if (fAsyncPipelineCreation->fFinished) {
639 return fAsyncPipelineCreation->fRenderPipeline;
640 }
641#if defined(__EMSCRIPTEN__)
642 // We shouldn't use CreateRenderPipelineAsync in wasm.
643 SKGPU_LOG_F("CreateRenderPipelineAsync shouldn't be used in WASM");
644#else
645 wgpu::FutureWaitInfo waitInfo{};
646 waitInfo.future = fAsyncPipelineCreation->fFuture;
647 const auto& instance = static_cast<const DawnSharedContext*>(sharedContext())
648 ->device()
649 .GetAdapter()
650 .GetInstance();
651
652 [[maybe_unused]] auto status =
653 instance.WaitAny(1, &waitInfo, /*timeoutNS=*/std::numeric_limits<uint64_t>::max());
654 SkASSERT(status == wgpu::WaitStatus::Success);
655 SkASSERT(waitInfo.completed);
656#endif
657
658 return fAsyncPipelineCreation->fRenderPipeline;
659}
660
661} // namespace skgpu::graphite
static int step(int x, SkScalar min, SkScalar max)
Definition: BlurTest.cpp:215
wgpu::RenderPipeline fRenderPipeline
bool fFinished
#define VALUE_IF_DSB_OR_ZERO(VALUE)
GrTriangulator::Vertex Vertex
#define SKGPU_LOG_F(fmt,...)
Definition: Log.h:36
#define SkUNREACHABLE
Definition: SkAssert.h:135
#define SkASSERT(cond)
Definition: SkAssert.h:116
GLenum type
constexpr size_t size() const
Definition: SkSpan_impl.h:95
skgpu::ShaderErrorHandler * shaderErrorHandler() const
Definition: Caps.h:273
const ResourceBindingRequirements & resourceBindingRequirements() const
Definition: Caps.h:150
bool setBackendLabels() const
Definition: Caps.h:297
bool storageBufferPreferred() const
Definition: Caps.h:239
const SkSL::ShaderCaps * shaderCaps() const
Definition: Caps.h:75
bool useAsyncPipelineCreation() const
Definition: DawnCaps.h:27
std::array< wgpu::BindGroupLayout, kBindGroupCount > BindGroupLayouts
const wgpu::RenderPipeline & dawnRenderPipeline() const
static constexpr unsigned int kInstanceBufferIndex
static sk_sp< DawnGraphicsPipeline > Make(const DawnSharedContext *sharedContext, DawnResourceProvider *resourceProvider, const RuntimeEffectDictionary *runtimeDict, const GraphicsPipelineDesc &pipelineDesc, const RenderPassDesc &renderPassDesc)
static constexpr unsigned int kVertexBufferIndex
const wgpu::BindGroupLayout & getOrCreateSingleTextureSamplerBindGroupLayout()
const wgpu::BindGroupLayout & getOrCreateUniformBuffersBindGroupLayout()
UniquePaintParamsID paintParamsID() const
const RenderStep * lookup(uint32_t uniqueID) const
const SharedContext * sharedContext() const
Definition: Resource.h:189
const Caps * caps() const
Definition: SharedContext.h:39
ShaderCodeDictionary * shaderCodeDictionary()
Definition: SharedContext.h:49
const RendererProvider * rendererProvider() const
Definition: SharedContext.h:47
VkDevice device
Definition: main.cc:53
VkInstance instance
Definition: main.cc:48
AtkStateType state
static SkColor blend(SkColor dst, SkColor src, void(*mode)(float, float, float, float *, float *, float *))
Definition: hsl.cpp:142
static float max(float r, float g, float b)
Definition: hsl.cpp:49
Win32Message message
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
BlendFactor
Definition: formats.h:178
PrimitiveType
Decides how backend draws pixels based on input vertices.
Definition: formats.h:352
CompareFunction
Definition: formats.h:546
StencilOperation
Definition: formats.h:565
BlendOperation
Definition: formats.h:196
VertSkSLInfo BuildVertexSkSL(const ResourceBindingRequirements &bindingReqs, const RenderStep *step, bool useStorageBuffers, bool defineLocalCoordsVarying)
bool DawnFormatIsDepthOrStencil(wgpu::TextureFormat format)
FragSkSLInfo BuildFragmentSkSL(const Caps *caps, const ShaderCodeDictionary *dict, const RuntimeEffectDictionary *rteDict, const RenderStep *step, UniquePaintParamsID paintID, bool useStorageBuffers, skgpu::Swizzle writeSwizzle)
std::string GetPipelineLabel(const ShaderCodeDictionary *dict, const RenderPassDesc &renderPassDesc, const RenderStep *renderStep, UniquePaintParamsID paintID)
bool DawnCompileWGSLShaderModule(const DawnSharedContext *sharedContext, const char *label, const std::string &wgsl, wgpu::ShaderModule *module, ShaderErrorHandler *errorHandler)
bool DawnFormatIsStencil(wgpu::TextureFormat format)
static constexpr bool BlendShouldDisable(BlendEquation equation, BlendCoeff srcCoeff, BlendCoeff dstCoeff)
Definition: Blend.h:145
static const int kBlendEquationCnt
Definition: Blend.h:55
BlendEquation
Definition: Blend.h:26
BlendCoeff
Definition: Blend.h:60
bool SkSLToWGSL(const SkSL::ShaderCaps *caps, const std::string &sksl, SkSL::ProgramKind programKind, const SkSL::ProgramSettings &settings, std::string *wgsl, SkSL::ProgramInterface *outInterface, ShaderErrorHandler *errorHandler)
Definition: DawnUtilsPriv.h:29
Definition: ref_ptr.h:256
skgpu::BlendCoeff fDstBlend
Definition: Blend.h:96
bool fWritesColor
Definition: Blend.h:98
skgpu::BlendCoeff fSrcBlend
Definition: Blend.h:95
AttachmentDesc fDepthStencilAttachment
AttachmentDesc fColorResolveAttachment