Flutter Engine
The Flutter Engine
DawnCaps.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
10#include <algorithm>
11
24#include "src/sksl/SkSLUtil.h"
25
26namespace {
27
28// These are all the valid wgpu::TextureFormat that we currently support in Skia.
29// They are roughly ordered from most frequently used to least to improve lookup times in arrays.
30static constexpr wgpu::TextureFormat kFormats[skgpu::graphite::DawnCaps::kFormatCnt] = {
31 wgpu::TextureFormat::RGBA8Unorm,
32 wgpu::TextureFormat::R8Unorm,
33#if !defined(__EMSCRIPTEN__)
34 wgpu::TextureFormat::R16Unorm,
35#endif
36 wgpu::TextureFormat::BGRA8Unorm,
37 wgpu::TextureFormat::RGBA16Float,
38 wgpu::TextureFormat::R16Float,
39 wgpu::TextureFormat::RG8Unorm,
40#if !defined(__EMSCRIPTEN__)
41 wgpu::TextureFormat::RG16Unorm,
42#endif
43 wgpu::TextureFormat::RGB10A2Unorm,
44 wgpu::TextureFormat::RG16Float,
45
46 wgpu::TextureFormat::Stencil8,
47 wgpu::TextureFormat::Depth16Unorm,
48 wgpu::TextureFormat::Depth32Float,
49 wgpu::TextureFormat::Depth24PlusStencil8,
50
51 wgpu::TextureFormat::BC1RGBAUnorm,
52 wgpu::TextureFormat::ETC2RGB8Unorm,
53
54#if !defined(__EMSCRIPTEN__)
55 wgpu::TextureFormat::External,
56#endif
57
58 wgpu::TextureFormat::Undefined,
59};
60
61#if !defined(__EMSCRIPTEN__)
62bool IsMultiplanarFormat(wgpu::TextureFormat format) {
63 switch (format) {
64 case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
65 case wgpu::TextureFormat::R10X6BG10X6Biplanar420Unorm:
66 case wgpu::TextureFormat::R8BG8A8Triplanar420Unorm:
67 return true;
68 default:
69 return false;
70 }
71}
72#endif
73} // anonymous namespace
74
75namespace skgpu::graphite {
76
78 : Caps() {
79 this->initCaps(backendContext, options);
80 this->initShaderCaps(backendContext.fDevice);
81 this->initFormatTable(backendContext.fDevice);
82 this->finishInitialization(options);
83}
84
85DawnCaps::~DawnCaps() = default;
86
87uint32_t DawnCaps::channelMask(const TextureInfo& info) const {
88 return DawnFormatChannels(info.dawnTextureSpec().getViewFormat());
89}
90
91bool DawnCaps::onIsTexturable(const TextureInfo& info) const {
92 if (!info.isValid()) {
93 return false;
94 }
95
96 const auto& spec = info.dawnTextureSpec();
97
98 if (!(spec.fUsage & wgpu::TextureUsage::TextureBinding)) {
99 return false;
100 }
101
102#if !defined(__EMSCRIPTEN__)
103 switch (spec.fFormat) {
104 case wgpu::TextureFormat::R8BG8Biplanar420Unorm: {
105 if (spec.fAspect == wgpu::TextureAspect::Plane0Only &&
106 spec.getViewFormat() != wgpu::TextureFormat::R8Unorm) {
107 return false;
108 }
109 if (spec.fAspect == wgpu::TextureAspect::Plane1Only &&
110 spec.getViewFormat() != wgpu::TextureFormat::RG8Unorm) {
111 return false;
112 }
113 break;
114 }
115 case wgpu::TextureFormat::R10X6BG10X6Biplanar420Unorm: {
116 if (spec.fAspect == wgpu::TextureAspect::Plane0Only &&
117 spec.getViewFormat() != wgpu::TextureFormat::R16Unorm) {
118 return false;
119 }
120 if (spec.fAspect == wgpu::TextureAspect::Plane1Only &&
121 spec.getViewFormat() != wgpu::TextureFormat::RG16Unorm) {
122 return false;
123 }
124 break;
125 }
126 case wgpu::TextureFormat::R8BG8A8Triplanar420Unorm: {
127 if (spec.fAspect == wgpu::TextureAspect::Plane0Only &&
128 spec.getViewFormat() != wgpu::TextureFormat::R8Unorm) {
129 return false;
130 }
131 if (spec.fAspect == wgpu::TextureAspect::Plane1Only &&
132 spec.getViewFormat() != wgpu::TextureFormat::RG8Unorm) {
133 return false;
134 }
135 if (spec.fAspect == wgpu::TextureAspect::Plane2Only &&
136 spec.getViewFormat() != wgpu::TextureFormat::R8Unorm) {
137 return false;
138 }
139 break;
140 }
141 default:
142 break;
143 }
144#endif
145
146 return this->isTexturable(info.dawnTextureSpec().getViewFormat());
147}
148
149bool DawnCaps::isTexturable(wgpu::TextureFormat format) const {
150 const FormatInfo& formatInfo = this->getFormatInfo(format);
151 return SkToBool(FormatInfo::kTexturable_Flag & formatInfo.fFlags);
152}
153
155 return info.isValid() &&
156 (info.dawnTextureSpec().fUsage & wgpu::TextureUsage::RenderAttachment) &&
157 this->isRenderable(info.dawnTextureSpec().getViewFormat(), info.numSamples());
158}
159
161 if (!info.isValid()) {
162 return false;
163 }
164 if (!(info.dawnTextureSpec().fUsage & wgpu::TextureUsage::StorageBinding)) {
165 return false;
166 }
167 const FormatInfo& formatInfo = this->getFormatInfo(info.dawnTextureSpec().getViewFormat());
168 return info.numSamples() == 1 && SkToBool(FormatInfo::kStorage_Flag & formatInfo.fFlags);
169}
170
171uint32_t DawnCaps::maxRenderTargetSampleCount(wgpu::TextureFormat format) const {
172 const FormatInfo& formatInfo = this->getFormatInfo(format);
173 if (!SkToBool(formatInfo.fFlags & FormatInfo::kRenderable_Flag)) {
174 return 0;
175 }
176 if (SkToBool(formatInfo.fFlags & FormatInfo::kMSAA_Flag)) {
177 return 8;
178 } else {
179 return 1;
180 }
181}
182
183bool DawnCaps::isRenderable(wgpu::TextureFormat format, uint32_t sampleCount) const {
184 return sampleCount <= this->maxRenderTargetSampleCount(format);
185}
186
188 Mipmapped mipmapped,
189 Protected,
190 Renderable renderable) const {
191 wgpu::TextureUsage usage = wgpu::TextureUsage::TextureBinding |
192 wgpu::TextureUsage::CopyDst |
193 wgpu::TextureUsage::CopySrc;
194 if (renderable == Renderable::kYes) {
195 usage |= wgpu::TextureUsage::RenderAttachment;
196 }
197
198 wgpu::TextureFormat format = this->getFormatFromColorType(colorType);
199 if (format == wgpu::TextureFormat::Undefined) {
200 return {};
201 }
202
204 info.fSampleCount = 1;
205 info.fMipmapped = mipmapped;
206 info.fFormat = format;
207 info.fViewFormat = format;
208 info.fUsage = usage;
209
210 return info;
211}
212
214 Mipmapped mipmapped) const {
216 if (!textureInfo.getDawnTextureInfo(&info)) {
217 return {};
218 }
219
220 info.fSampleCount = 1;
221 info.fMipmapped = mipmapped;
222 info.fUsage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopyDst |
223 wgpu::TextureUsage::CopySrc;
224
225 return info;
226}
227
228namespace {
229wgpu::TextureFormat format_from_compression(SkTextureCompressionType compression) {
230 switch (compression) {
232 return wgpu::TextureFormat::ETC2RGB8Unorm;
234 return wgpu::TextureFormat::BC1RGBAUnorm;
235 default:
236 return wgpu::TextureFormat::Undefined;
237 }
238}
239}
240
242 Mipmapped mipmapped,
243 Protected) const {
244 wgpu::TextureUsage usage = wgpu::TextureUsage::TextureBinding |
245 wgpu::TextureUsage::CopyDst |
246 wgpu::TextureUsage::CopySrc;
247
248 wgpu::TextureFormat format = format_from_compression(compression);
249 if (format == wgpu::TextureFormat::Undefined) {
250 return {};
251 }
252
254 info.fSampleCount = 1;
255 info.fMipmapped = mipmapped;
256 info.fFormat = format;
257 info.fViewFormat = format;
258 info.fUsage = usage;
259
260 return info;
261}
262
264 Discardable discardable) const {
265 if (fDefaultMSAASamples <= 1) {
266 return {};
267 }
268 const DawnTextureSpec& singleSpec = singleSampledInfo.dawnTextureSpec();
269
271 info.fSampleCount = fDefaultMSAASamples;
272 info.fMipmapped = Mipmapped::kNo;
273 info.fFormat = singleSpec.fFormat;
274 info.fViewFormat = singleSpec.fFormat;
275 info.fUsage = wgpu::TextureUsage::RenderAttachment;
276
277 if (fSupportedTransientAttachmentUsage != wgpu::TextureUsage::None &&
278 discardable == Discardable::kYes) {
279 info.fUsage |= fSupportedTransientAttachmentUsage;
280 }
281
282 return info;
283}
284
286 SkEnumBitMask<DepthStencilFlags> depthStencilType,
287 uint32_t sampleCount,
288 Protected) const {
290 info.fSampleCount = sampleCount;
291 info.fMipmapped = Mipmapped::kNo;
292 info.fFormat = DawnDepthStencilFlagsToFormat(depthStencilType);
293 info.fViewFormat = info.fFormat;
294 info.fUsage = wgpu::TextureUsage::RenderAttachment;
295
296 if (fSupportedTransientAttachmentUsage != wgpu::TextureUsage::None) {
297 info.fUsage |= fSupportedTransientAttachmentUsage;
298 }
299
300 return info;
301}
302
304 wgpu::TextureFormat format = this->getFormatFromColorType(colorType);
305 if (format == wgpu::TextureFormat::Undefined) {
306 SkDebugf("colorType=%d is not supported\n", static_cast<int>(colorType));
307 return {};
308 }
309
310 const FormatInfo& formatInfo = this->getFormatInfo(format);
311 if (!SkToBool(FormatInfo::kStorage_Flag & formatInfo.fFlags)) {
312 return {};
313 }
314
315 wgpu::TextureUsage usage = wgpu::TextureUsage::StorageBinding |
316 wgpu::TextureUsage::TextureBinding |
317 wgpu::TextureUsage::CopySrc;
319 info.fSampleCount = 1;
320 info.fMipmapped = Mipmapped::kNo;
321 info.fFormat = format;
322 info.fViewFormat = format;
323 info.fUsage = usage;
324
325 return info;
326}
327
329 const SkISize colorAttachmentDimensions) const {
330#if !defined(__EMSCRIPTEN__)
331 // For multiplanar textures, texture->textureInfo() uses the format of planes instead of
332 // textures (R8, R8G8, vs R8BG8Biplanar420Unorm), so we have to query texture format from
333 // wgpu::Texture object, and then use it reconstruct the full dimensions.
334 const auto& dawnTextureSpec = textureInfo.dawnTextureSpec();
335 wgpu::TextureFormat format = dawnTextureSpec.fFormat;
336 if (IsMultiplanarFormat(format) && dawnTextureSpec.fAspect == wgpu::TextureAspect::Plane1Only) {
337 // Dawn requires depth attachment to match the size of Y plane (texture size).
338 return SkISize::Make(colorAttachmentDimensions.width() * 2,
339 colorAttachmentDimensions.height() * 2);
340 }
341#endif
342
343 return colorAttachmentDimensions;
344}
345
346const Caps::ColorTypeInfo* DawnCaps::getColorTypeInfo(SkColorType colorType,
347 const TextureInfo& textureInfo) const {
348 auto dawnFormat = textureInfo.dawnTextureSpec().getViewFormat();
349 if (dawnFormat == wgpu::TextureFormat::Undefined) {
350 SkASSERT(false);
351 return nullptr;
352 }
353
354 const FormatInfo& info = this->getFormatInfo(dawnFormat);
355 for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
356 const ColorTypeInfo& ctInfo = info.fColorTypeInfos[i];
357 if (ctInfo.fColorType == colorType) {
358 return &ctInfo;
359 }
360 }
361
362 return nullptr;
363}
364
365bool DawnCaps::supportsWritePixels(const TextureInfo& textureInfo) const {
366 const auto& spec = textureInfo.dawnTextureSpec();
367 return spec.fUsage & wgpu::TextureUsage::CopyDst;
368}
369
370bool DawnCaps::supportsReadPixels(const TextureInfo& textureInfo) const {
371 const auto& spec = textureInfo.dawnTextureSpec();
372 return spec.fUsage & wgpu::TextureUsage::CopySrc;
373}
374
375std::pair<SkColorType, bool /*isRGBFormat*/> DawnCaps::supportedWritePixelsColorType(
376 SkColorType dstColorType,
377 const TextureInfo& dstTextureInfo,
378 SkColorType srcColorType) const {
379 return {dstColorType, false};
380}
381
382std::pair<SkColorType, bool /*isRGBFormat*/> DawnCaps::supportedReadPixelsColorType(
383 SkColorType srcColorType,
384 const TextureInfo& srcTextureInfo,
385 SkColorType dstColorType) const {
386 auto dawnFormat = getFormatFromColorType(srcColorType);
387 const FormatInfo& info = this->getFormatInfo(dawnFormat);
388 for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
389 const auto& ctInfo = info.fColorTypeInfos[i];
390 if (ctInfo.fColorType == srcColorType) {
391 return {srcColorType, false};
392 }
393 }
394 return {kUnknown_SkColorType, false};
395}
396
397void DawnCaps::initCaps(const DawnBackendContext& backendContext, const ContextOptions& options) {
398 // GetAdapter() is not available in WASM and there's no way to get AdapterInfo off of
399 // the WGPUDevice directly.
400#if !defined(__EMSCRIPTEN__)
401 wgpu::AdapterInfo info;
402 backendContext.fDevice.GetAdapter().GetInfo(&info);
403
404#if defined(GRAPHITE_TEST_UTILS)
405 this->setDeviceName(info.device);
406#endif
407#endif // defined(__EMSCRIPTEN__)
408
409 wgpu::SupportedLimits limits;
410#if defined(__EMSCRIPTEN__)
411 // TODO(crbug.com/42241199): Update Emscripten path with when webgpu.h in Emscripten is updated.
412 [[maybe_unused]] bool limitsSucceeded = backendContext.fDevice.GetLimits(&limits);
413#if (__EMSCRIPTEN_major__ > 3 || (__EMSCRIPTEN_major__ == 3 && __EMSCRIPTEN_minor__ > 1) || \
414 (__EMSCRIPTEN_major__ == 3 && __EMSCRIPTEN_minor__ == 1 && __EMSCRIPTEN_tiny__ > 50))
415 // In Emscripten this always "fails" until
416 // https://github.com/emscripten-core/emscripten/pull/20808, which was first included in 3.1.51.
417 SkASSERT(limitsSucceeded);
418#endif
419#else
420 [[maybe_unused]] wgpu::Status status = backendContext.fDevice.GetLimits(&limits);
421 SkASSERT(status == wgpu::Status::Success);
422#endif
423
424 fMaxTextureSize = limits.limits.maxTextureDimension2D;
425
429
430 // Dawn requires 256 bytes per row alignment for buffer texture copies.
432
434 // The WGSL generator assumes tightly packed std430 layout for SSBOs which is also the default
435 // for all types outside the uniform address space in WGSL.
438
439#if !defined(__EMSCRIPTEN__)
440 // TODO(b/318817249): SSBOs trigger FXC compiler failures when attempting to unroll loops
441 fStorageBufferSupport = info.backendType != wgpu::BackendType::D3D11;
442 fStorageBufferPreferred = info.backendType != wgpu::BackendType::D3D11;
443#else
444 // WASM doesn't provide a way to query the backend, so can't tell if we are on d3d11 or not.
445 // Pessimistically assume we could be. Once b/318817249 is fixed, this can go away and SSBOs
446 // can always be enabled.
447 fStorageBufferSupport = false;
449#endif
450
452
453 fComputeSupport = true;
454
455 // TODO: support clamp to border.
456 fClampToBorderSupport = false;
457
458#if defined(GRAPHITE_TEST_UTILS)
459 fDrawBufferCanBeMappedForReadback = false;
460#endif
461
462#if defined(__EMSCRIPTEN__)
463 // For wasm, we use async map.
464 fBufferMapsAreAsync = true;
465#else
466 // For Dawn native, we use direct mapping.
467 fBufferMapsAreAsync = false;
469 backendContext.fDevice.HasFeature(wgpu::FeatureName::BufferMapExtendedUsages);
470
472 backendContext.fDevice.HasFeature(wgpu::FeatureName::MSAARenderToSingleSampled);
473
474 if (backendContext.fDevice.HasFeature(wgpu::FeatureName::TransientAttachments)) {
475 fSupportedTransientAttachmentUsage = wgpu::TextureUsage::TransientAttachment;
476 }
477 if (backendContext.fDevice.HasFeature(wgpu::FeatureName::DawnLoadResolveTexture)) {
478 fSupportedResolveTextureLoadOp = wgpu::LoadOp::ExpandResolveTexture;
479 }
480#endif
481
482 if (!backendContext.fTick) {
483 fAllowCpuSync = false;
484 // This seems paradoxical. However, if we use the async pipeline creation methods (e.g
485 // Device::CreateRenderPipelineAsync) then we may have to synchronize before a submit that
486 // uses the pipeline. If we use the methods that look synchronous (e.g.
487 // Device::CreateRenderPipeline) they actually operate asynchronously on WebGPU but the
488 // browser becomes responsible for synchronizing when we call submit.
489 fUseAsyncPipelineCreation = false;
490
491 // The implementation busy waits after popping.
492 fAllowScopedErrorChecks = false;
493 }
494
496}
497
498void DawnCaps::initShaderCaps(const wgpu::Device& device) {
500
501 // WGSL does not support infinities regardless of hardware support. There are discussions around
502 // enabling it using an extension in the future.
504
505 // WGSL supports shader derivatives in the fragment shader
507
508#if !defined(__EMSCRIPTEN__)
509 if (device.HasFeature(wgpu::FeatureName::DualSourceBlending)) {
511 }
512 if (device.HasFeature(wgpu::FeatureName::FramebufferFetch)) {
514 }
515#endif
516
517 shaderCaps->fFloatBufferArrayName = "fsGradientBuffer";
518}
519
520void DawnCaps::initFormatTable(const wgpu::Device& device) {
521 FormatInfo* info;
522 // Format: RGBA8Unorm
523 {
524 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::RGBA8Unorm)];
525 info->fFlags = FormatInfo::kAllFlags;
526 info->fColorTypeInfoCount = 2;
527 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
528 int ctIdx = 0;
529 // Format: RGBA8Unorm, Surface: kRGBA_8888
530 {
531 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
532 ctInfo.fColorType = kRGBA_8888_SkColorType;
534 }
535 // Format: RGBA8Unorm, Surface: kRGB_888x
536 {
537 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
538 ctInfo.fColorType = kRGB_888x_SkColorType;
539 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
540 ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1();
541 }
542 }
543
544 // Format: R8Unorm
545 {
546 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::R8Unorm)];
547#if !defined(__EMSCRIPTEN__)
548 info->fFlags = FormatInfo::kAllFlags;
549 if (!device.HasFeature(wgpu::FeatureName::R8UnormStorage)) {
550 info->fFlags &= ~FormatInfo::kStorage_Flag;
551 }
552#else
553 info->fFlags = FormatInfo::kAllFlags & ~FormatInfo::kStorage_Flag;
554#endif
555 info->fColorTypeInfoCount = 3;
556 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
557 int ctIdx = 0;
558 // Format: R8Unorm, Surface: kR8_unorm
559 {
560 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
561 ctInfo.fColorType = kR8_unorm_SkColorType;
563 }
564 // Format: R8Unorm, Surface: kAlpha_8
565 {
566 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
567 ctInfo.fColorType = kAlpha_8_SkColorType;
569 ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
570 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
571 }
572 // Format: R8Unorm, Surface: kGray_8
573 {
574 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
575 ctInfo.fColorType = kGray_8_SkColorType;
576 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
577 ctInfo.fReadSwizzle = skgpu::Swizzle("rrr1");
578 }
579 }
580
581#if !defined(__EMSCRIPTEN__)
582 const bool supportUnorm16 = device.HasFeature(wgpu::FeatureName::Unorm16TextureFormats);
583 // TODO(crbug.com/dawn/1856): Support storage binding for compute shader in Dawn.
584 // Format: R16Unorm
585 {
586 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::R16Unorm)];
587 if (supportUnorm16) {
588 info->fFlags = FormatInfo::kAllFlags & ~FormatInfo::kStorage_Flag;
589 info->fColorTypeInfoCount = 1;
590 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
591 int ctIdx = 0;
592 // Format: R16Unorm, Surface: kA16_unorm
593 {
594 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
595 ctInfo.fColorType = kA16_unorm_SkColorType;
597 ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
598 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
599 }
600 }
601 }
602#endif
603
604 // Format: BGRA8Unorm
605 {
606 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::BGRA8Unorm)];
607 info->fFlags = FormatInfo::kAllFlags;
608 info->fColorTypeInfoCount = 2;
609 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
610 int ctIdx = 0;
611 // Format: BGRA8Unorm, Surface: kBGRA_8888
612 {
613 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
614 ctInfo.fColorType = kBGRA_8888_SkColorType;
616 }
617 // Format: BGRA8Unorm, Surface: kRGB_888x
618 {
619 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
620 ctInfo.fColorType = kRGB_888x_SkColorType;
621 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
622 }
623 }
624
625 // Format: RGBA16Float
626 {
627 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::RGBA16Float)];
628 info->fFlags = FormatInfo::kAllFlags;
629 info->fColorTypeInfoCount = 1;
630 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
631 int ctIdx = 0;
632 // Format: RGBA16Float, Surface: RGBA_F16
633 {
634 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
635 ctInfo.fColorType = kRGBA_F16_SkColorType;
637 }
638 }
639
640 // Format: R16Float
641 {
642 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::R16Float)];
643 info->fFlags = FormatInfo::kAllFlags;
644 info->fColorTypeInfoCount = 1;
645 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
646 int ctIdx = 0;
647 // Format: R16Float, Surface: kA16_float
648 {
649 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
650 ctInfo.fColorType = kA16_float_SkColorType;
652 ctInfo.fReadSwizzle = skgpu::Swizzle("000r");
653 ctInfo.fWriteSwizzle = skgpu::Swizzle("a000");
654 }
655 }
656
657 // TODO(crbug.com/dawn/1856): Support storage binding for compute shader in Dawn.
658 // Format: RG8Unorm
659 {
660 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::RG8Unorm)];
661 info->fFlags = FormatInfo::kAllFlags;
662 info->fColorTypeInfoCount = 1;
663 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
664 int ctIdx = 0;
665 // Format: RG8Unorm, Surface: kR8G8_unorm
666 {
667 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
668 ctInfo.fColorType = kR8G8_unorm_SkColorType;
670 }
671 }
672
673#if !defined(__EMSCRIPTEN__)
674 // TODO(crbug.com/dawn/1856): Support storage binding for compute shader in Dawn.
675 // Format: RG16Unorm
676 {
677 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::RG16Unorm)];
678 if (supportUnorm16) {
679 info->fFlags = FormatInfo::kAllFlags;
680 info->fColorTypeInfoCount = 1;
681 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
682 int ctIdx = 0;
683 // Format: RG16Unorm, Surface: kR16G16_unorm
684 {
685 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
686 ctInfo.fColorType = kR16G16_unorm_SkColorType;
688 }
689 }
690 }
691#endif
692
693 // Format: RGB10A2Unorm
694 {
695 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::RGB10A2Unorm)];
696 info->fFlags = FormatInfo::kAllFlags;
697 info->fColorTypeInfoCount = 1;
698 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
699 int ctIdx = 0;
700 // Format: RGB10A2Unorm, Surface: kRGBA_1010102
701 {
702 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
703 ctInfo.fColorType = kRGBA_1010102_SkColorType;
705 }
706 }
707
708 // Format: RG16Float
709 {
710 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::RG16Float)];
711 info->fFlags = FormatInfo::kAllFlags;
712 info->fColorTypeInfoCount = 1;
713 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
714 int ctIdx = 0;
715 // Format: RG16Float, Surface: kR16G16_float
716 {
717 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
718 ctInfo.fColorType = kR16G16_float_SkColorType;
720 }
721 }
722
723 // Format: ETC2RGB8Unorm
724 {
725 if (device.HasFeature(wgpu::FeatureName::TextureCompressionETC2)) {
726 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::ETC2RGB8Unorm)];
727 info->fFlags = FormatInfo::kTexturable_Flag;
728 info->fColorTypeInfoCount = 1;
729 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
730 int ctIdx = 0;
731 // Format: ETC2RGB8Unorm, Surface: kRGB_888x
732 {
733 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
734 ctInfo.fColorType = kRGB_888x_SkColorType;
735 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
736 }
737 }
738 }
739
740 // Format: BC1RGBAUnorm
741 {
742 if (device.HasFeature(wgpu::FeatureName::TextureCompressionBC)) {
743 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::BC1RGBAUnorm)];
744 info->fFlags = FormatInfo::kTexturable_Flag;
745 info->fColorTypeInfoCount = 1;
746 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
747 int ctIdx = 0;
748 // Format: BC1RGBAUnorm, Surface: kRGBA_8888
749 {
750 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
751 ctInfo.fColorType = kRGBA_8888_SkColorType;
752 ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag;
753 }
754 }
755 }
756
757 /*
758 * Non-color formats
759 */
760
761 // Format: Stencil8
762 {
763 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::Stencil8)];
764 info->fFlags = FormatInfo::kMSAA_Flag;
765 info->fColorTypeInfoCount = 0;
766 }
767
768 // Format: Depth16UNorm
769 {
770 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::Depth16Unorm)];
771 info->fFlags = FormatInfo::kMSAA_Flag;
772 info->fColorTypeInfoCount = 0;
773 }
774
775 // Format: Depth32Float
776 {
777 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::Depth32Float)];
778 info->fFlags = FormatInfo::kMSAA_Flag;
779 info->fColorTypeInfoCount = 0;
780 }
781
782 // Format: Depth24PlusStencil8
783 {
784 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::Depth24PlusStencil8)];
785 info->fFlags = FormatInfo::kMSAA_Flag;
786 info->fColorTypeInfoCount = 0;
787 }
788
789#if !defined(__EMSCRIPTEN__)
790 // Format: External
791 {
792 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::External)];
793 info->fFlags = FormatInfo::kTexturable_Flag;
794 info->fColorTypeInfoCount = 1;
795 info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount);
796 int ctIdx = 0;
797 // Format: External, Surface: kRGBA_8888
798 {
799 auto& ctInfo = info->fColorTypeInfos[ctIdx++];
800 ctInfo.fColorType = kRGBA_8888_SkColorType;
801 }
802 }
803#endif
804
805 // Format: Undefined
806 {
807 info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::Undefined)];
808 info->fFlags = 0;
809 info->fColorTypeInfoCount = 0;
810 }
811
812 ////////////////////////////////////////////////////////////////////////////
813 // Map SkColorTypes (used for creating SkSurfaces) to wgpu::TextureFormat.
814 // The order in which the formats are passed into the setColorType function
815 // indicates the priority in selecting which format we use for a given
816 // SkColorType.
817
818 std::fill_n(fColorTypeToFormatTable, kSkColorTypeCnt, wgpu::TextureFormat::Undefined);
819
820 this->setColorType(kAlpha_8_SkColorType, { wgpu::TextureFormat::R8Unorm });
821 this->setColorType(kRGBA_8888_SkColorType, { wgpu::TextureFormat::RGBA8Unorm });
822 this->setColorType(kRGB_888x_SkColorType,
823 {wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureFormat::BGRA8Unorm});
824 this->setColorType(kBGRA_8888_SkColorType, { wgpu::TextureFormat::BGRA8Unorm });
825 this->setColorType(kGray_8_SkColorType, { wgpu::TextureFormat::R8Unorm });
826 this->setColorType(kR8_unorm_SkColorType, { wgpu::TextureFormat::R8Unorm });
827 this->setColorType(kRGBA_F16_SkColorType, { wgpu::TextureFormat::RGBA16Float });
828 this->setColorType(kA16_float_SkColorType, { wgpu::TextureFormat::R16Float });
829 this->setColorType(kR8G8_unorm_SkColorType, { wgpu::TextureFormat::RG8Unorm });
830 this->setColorType(kRGBA_1010102_SkColorType, { wgpu::TextureFormat::RGB10A2Unorm });
831 this->setColorType(kR16G16_float_SkColorType, { wgpu::TextureFormat::RG16Float });
832
833#if !defined(__EMSCRIPTEN__)
834 this->setColorType(kA16_unorm_SkColorType, { wgpu::TextureFormat::R16Unorm });
835 this->setColorType(kR16G16_unorm_SkColorType, { wgpu::TextureFormat::RG16Unorm });
836#endif
837}
838
839// static
840size_t DawnCaps::GetFormatIndex(wgpu::TextureFormat format) {
841 for (size_t i = 0; i < std::size(kFormats); ++i) {
842 if (format == kFormats[i]) {
843 return i;
844 }
845 if (kFormats[i] == wgpu::TextureFormat::Undefined) {
846 SkDEBUGFAILF("Unsupported wgpu::TextureFormat: %d\n", static_cast<int>(format));
847 return i;
848 }
849 }
851 return 0;
852}
853
854void DawnCaps::setColorType(SkColorType colorType,
855 std::initializer_list<wgpu::TextureFormat> formats) {
856 static_assert(std::size(kFormats) == kFormatCnt,
857 "Size is not same for DawnCaps::fFormatTable and kFormats");
858 int idx = static_cast<int>(colorType);
859 for (auto it = formats.begin(); it != formats.end(); ++it) {
860 const auto& info = this->getFormatInfo(*it);
861 for (int i = 0; i < info.fColorTypeInfoCount; ++i) {
862 if (info.fColorTypeInfos[i].fColorType == colorType) {
863 fColorTypeToFormatTable[idx] = *it;
864 return;
865 }
866 }
867 }
868}
869
870uint64_t DawnCaps::getRenderPassDescKeyForPipeline(const RenderPassDesc& renderPassDesc) const {
871 DawnTextureInfo colorInfo, depthStencilInfo;
872 renderPassDesc.fColorAttachment.fTextureInfo.getDawnTextureInfo(&colorInfo);
873 renderPassDesc.fDepthStencilAttachment.fTextureInfo.getDawnTextureInfo(&depthStencilInfo);
874 SkASSERT(static_cast<uint32_t>(colorInfo.getViewFormat()) <= 0xffff &&
875 static_cast<uint32_t>(depthStencilInfo.getViewFormat()) <= 0xffff &&
876 colorInfo.fSampleCount < 0x7fff);
877
878 // Note: if Dawn supports ExpandResolveTexture load op and the render pass uses it to load
879 // the resolve texture, a render pipeline will need to be created with
880 // wgpu::ColorTargetStateExpandResolveTextureDawn chained struct in order to be compatible.
881 // Hence a render pipeline created for a render pass using ExpandResolveTexture load op will
882 // be different from the one created for a render pass not using that load op.
883 // So we need to include a bit flag to differentiate the two kinds of pipelines.
884 // Also avoid returning a cached pipeline that is not compatible with the render pass using
885 // ExpandResolveTexture load op and vice versa.
886 const bool shouldIncludeLoadResolveAttachmentBit = this->resolveTextureLoadOp().has_value();
887 uint32_t loadResolveAttachmentKey = 0;
888 if (shouldIncludeLoadResolveAttachmentBit &&
891 loadResolveAttachmentKey = 1;
892 }
893
894 uint32_t colorAttachmentKey = static_cast<uint32_t>(colorInfo.getViewFormat()) << 16 |
895 colorInfo.fSampleCount << 1 | loadResolveAttachmentKey;
896
897 uint32_t dsAttachmentKey = static_cast<uint32_t>(depthStencilInfo.getViewFormat()) << 16 |
898 depthStencilInfo.fSampleCount;
899 return (((uint64_t)colorAttachmentKey) << 32) | dsAttachmentKey;
900}
901
903 const RenderPassDesc& renderPassDesc) const {
904 UniqueKey pipelineKey;
905 {
907 // 5 uint32_t's (render step id, paint id, uint64 RenderPass desc, uint16 write swizzle)
908 UniqueKey::Builder builder(&pipelineKey, kGraphicsPipelineDomain, 5, "GraphicsPipeline");
909 // add GraphicsPipelineDesc key
910 builder[0] = pipelineDesc.renderStepID();
911 builder[1] = pipelineDesc.paintParamsID().asUInt();
912
913 // Add RenderPassDesc key.
914 uint64_t renderPassKey = this->getRenderPassDescKeyForPipeline(renderPassDesc);
915 builder[2] = renderPassKey & 0xFFFFFFFF;
916 builder[3] = (renderPassKey >> 32) & 0xFFFFFFFF;
917 builder[4] = renderPassDesc.fWriteSwizzle.asKey();
918 builder.finish();
919 }
920
921 return pipelineKey;
922}
923
925 UniqueKey pipelineKey;
926 {
927 static const skgpu::UniqueKey::Domain kComputePipelineDomain = UniqueKey::GenerateDomain();
928 // The key is made up of a single uint32_t corresponding to the compute step ID.
929 UniqueKey::Builder builder(&pipelineKey, kComputePipelineDomain, 1, "ComputePipeline");
930 builder[0] = pipelineDesc.computeStep()->uniqueID();
931
932 // TODO(b/240615224): The local work group size should factor into the key here since it is
933 // specified in the shader text on Dawn/SPIR-V. This is not a problem right now since
934 // ComputeSteps don't vary their workgroup size dynamically.
935
936 builder.finish();
937 }
938 return pipelineKey;
939}
940
942 const TextureInfo& info,
944 Shareable shareable,
945 GraphiteResourceKey* key) const {
946 const DawnTextureSpec& dawnSpec = info.dawnTextureSpec();
947
948 SkASSERT(!dimensions.isEmpty());
949
950 SkASSERT(dawnSpec.getViewFormat() != wgpu::TextureFormat::Undefined);
951 uint32_t formatKey = static_cast<uint32_t>(dawnSpec.getViewFormat());
952
953 uint32_t samplesKey = SamplesToKey(info.numSamples());
954 // We don't have to key the number of mip levels because it is inherit in the combination of
955 // isMipped and dimensions.
956 bool isMipped = info.mipmapped() == Mipmapped::kYes;
957
958 // Confirm all the below parts of the key can fit in a single uint32_t. The sum of the shift
959 // amounts in the asserts must be less than or equal to 32.
960 SkASSERT(samplesKey < (1u << 3)); // sample key is first 3 bits
961 SkASSERT(static_cast<uint32_t>(isMipped) < (1u << 1)); // isMapped is 4th bit
962 SkASSERT(static_cast<uint32_t>(dawnSpec.fUsage) < (1u << 28)); // usage is remaining 28 bits
963
964 // We need two uint32_ts for dimensions, 1 for format, and 1 for the rest of the key;
965 static int kNum32DataCnt = 2 + 1 + 1;
966
967 GraphiteResourceKey::Builder builder(key, type, kNum32DataCnt, shareable);
968
969 builder[0] = dimensions.width();
970 builder[1] = dimensions.height();
971 builder[2] = formatKey;
972 builder[3] = (samplesKey << 0) |
973 (static_cast<uint32_t>(isMipped) << 3) |
974 (static_cast<uint32_t>(dawnSpec.fUsage) << 4);
975}
976
977} // namespace skgpu::graphite
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
#define SkUNREACHABLE
Definition: SkAssert.h:135
#define SkDEBUGFAILF(fmt,...)
Definition: SkAssert.h:119
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkColorType
Definition: SkColorType.h:19
@ kR8_unorm_SkColorType
Definition: SkColorType.h:54
@ kR8G8_unorm_SkColorType
pixel with a uint8_t for red and green
Definition: SkColorType.h:43
@ kBGRA_8888_SkColorType
pixel with 8 bits for blue, green, red, alpha; in 32-bit word
Definition: SkColorType.h:26
@ kA16_unorm_SkColorType
pixel with a little endian uint16_t for alpha
Definition: SkColorType.h:48
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
Definition: SkColorType.h:38
@ kAlpha_8_SkColorType
pixel with alpha in 8-bit byte
Definition: SkColorType.h:21
@ kGray_8_SkColorType
pixel with grayscale level in 8-bit byte
Definition: SkColorType.h:35
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
@ kRGB_888x_SkColorType
pixel with 8 bits each for red, green, blue; in 32-bit word
Definition: SkColorType.h:25
@ kA16_float_SkColorType
pixel with a half float for alpha
Definition: SkColorType.h:45
@ kRGBA_1010102_SkColorType
10 bits for red, green, blue; 2 bits for alpha; in 32-bit word
Definition: SkColorType.h:27
@ kR16G16_unorm_SkColorType
pixel with a little endian uint16_t for red and green
Definition: SkColorType.h:49
@ kUnknown_SkColorType
uninitialized
Definition: SkColorType.h:20
@ kR16G16_float_SkColorType
pixel with a half float for red and green
Definition: SkColorType.h:46
static constexpr int kSkColorTypeCnt
Definition: SkColorType.h:68
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
SkTextureCompressionType
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
GLenum type
constexpr uint16_t asKey() const
Definition: Swizzle.h:43
static constexpr Swizzle RGB1()
Definition: Swizzle.h:69
static Domain GenerateDomain()
Definition: ResourceKey.cpp:27
size_t fRequiredStorageBufferAlignment
Definition: Caps.h:359
bool fDrawBufferCanBeMapped
Definition: Caps.h:371
size_t fRequiredUniformBufferAlignment
Definition: Caps.h:358
bool fBufferMapsAreAsync
Definition: Caps.h:372
bool fStorageBufferPreferred
Definition: Caps.h:370
bool fClampToBorderSupport
Definition: Caps.h:365
bool fMSAARenderToSingleSampledSupport
Definition: Caps.h:373
bool fComputeSupport
Definition: Caps.h:375
bool fFullCompressedUploadSizeMustAlignToBlockDims
Definition: Caps.h:377
std::unique_ptr< SkSL::ShaderCaps > fShaderCaps
Definition: Caps.h:363
bool fStorageBufferSupport
Definition: Caps.h:369
static uint32_t SamplesToKey(uint32_t numSamples)
Definition: Caps.h:314
void finishInitialization(const ContextOptions &)
Definition: Caps.cpp:29
size_t fRequiredTransferBufferAlignment
Definition: Caps.h:360
const SkSL::ShaderCaps * shaderCaps() const
Definition: Caps.h:75
ResourceBindingRequirements fResourceBindingReqs
Definition: Caps.h:383
int fDefaultMSAASamples
Definition: Caps.h:357
size_t fTextureDataRowBytesAlignment
Definition: Caps.h:361
const ComputeStep * computeStep() const
uint32_t uniqueID() const
Definition: ComputeStep.h:241
static constexpr size_t kFormatCnt
Definition: DawnCaps.h:65
void buildKeyForTexture(SkISize dimensions, const TextureInfo &, ResourceType, Shareable, GraphiteResourceKey *) const override
Definition: DawnCaps.cpp:941
TextureInfo getDefaultStorageTextureInfo(SkColorType) const override
Definition: DawnCaps.cpp:303
bool isStorage(const TextureInfo &) const override
Definition: DawnCaps.cpp:160
bool isRenderable(const TextureInfo &) const override
Definition: DawnCaps.cpp:154
TextureInfo getDefaultSampledTextureInfo(SkColorType, Mipmapped mipmapped, Protected, Renderable) const override
Definition: DawnCaps.cpp:187
SkISize getDepthAttachmentDimensions(const TextureInfo &, const SkISize colorAttachmentDimensions) const override
Definition: DawnCaps.cpp:328
TextureInfo getDefaultDepthStencilTextureInfo(SkEnumBitMask< DepthStencilFlags >, uint32_t sampleCount, Protected) const override
Definition: DawnCaps.cpp:285
uint32_t channelMask(const TextureInfo &) const override
Definition: DawnCaps.cpp:87
UniqueKey makeComputePipelineKey(const ComputePipelineDesc &) const override
Definition: DawnCaps.cpp:924
DawnCaps(const DawnBackendContext &, const ContextOptions &)
Definition: DawnCaps.cpp:77
UniqueKey makeGraphicsPipelineKey(const GraphicsPipelineDesc &, const RenderPassDesc &) const override
Definition: DawnCaps.cpp:902
TextureInfo getTextureInfoForSampledCopy(const TextureInfo &textureInfo, Mipmapped mipmapped) const override
Definition: DawnCaps.cpp:213
uint64_t getRenderPassDescKeyForPipeline(const RenderPassDesc &renderPassDesc) const
Definition: DawnCaps.cpp:870
TextureInfo getDefaultCompressedTextureInfo(SkTextureCompressionType, Mipmapped mipmapped, Protected) const override
Definition: DawnCaps.cpp:241
std::optional< wgpu::LoadOp > resolveTextureLoadOp() const
Definition: DawnCaps.h:31
TextureInfo getDefaultMSAATextureInfo(const TextureInfo &singleSampledInfo, Discardable discardable) const override
Definition: DawnCaps.cpp:263
UniquePaintParamsID paintParamsID() const
VkDevice device
Definition: main.cc:53
uint32_t uint32_t * format
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
TextureUsage
Definition: formats.h:300
uint32_t ResourceType
wgpu::TextureFormat DawnDepthStencilFlagsToFormat(SkEnumBitMask< DepthStencilFlags > mask)
uint32_t DawnFormatChannels(wgpu::TextureFormat format)
Definition: DawnUtils.cpp:63
static const skgpu::UniqueKey::Domain kGraphicsPipelineDomain
Definition: MtlCaps.mm:895
Task::Status Status
Definition: TaskList.cpp:15
Renderable
Definition: GpuTypes.h:69
Mipmapped
Definition: GpuTypes.h:53
Protected
Definition: GpuTypes.h:61
static void usage(char *argv0)
Definition: SkSize.h:16
bool isEmpty() const
Definition: SkSize.h:31
static constexpr SkISize Make(int32_t w, int32_t h)
Definition: SkSize.h:20
constexpr int32_t width() const
Definition: SkSize.h:36
constexpr int32_t height() const
Definition: SkSize.h:37
bool fFBFetchSupport
Definition: SkSLUtil.h:93
bool fDualSourceBlendingSupport
Definition: SkSLUtil.h:84
const char * fFloatBufferArrayName
Definition: SkSLUtil.h:160
bool fInfinitySupport
Definition: SkSLUtil.h:103
bool fShaderDerivativeSupport
Definition: SkSLUtil.h:85
wgpu::TextureFormat getViewFormat() const
Definition: DawnTypes.h:37
wgpu::TextureFormat getViewFormat() const
Definition: DawnTypesPriv.h:49
AttachmentDesc fDepthStencilAttachment
AttachmentDesc fColorResolveAttachment