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