[graphite] Add TextureFormat unit tests Fixed a bug in the colortype -> format lookup that wasn't taking renderability into account. This is only an issue until https://skia-review.git.corp.google.com/c/skia/+/1165836 lands, which removes these in favor of a static lookup map. Added many format rules in Mtl, Dawn, and VulkanCaps that were inconsistently declared between the different backends even though they all had a backend format matching the TextureFormat. Additionally, it adds rules to make the BGRA vs RGBA ordering more relaxed, which is the eventual set of matches that the TextureFormat unit tests lay out. The color -> format rules are minimally done to get the unit tests passing; formats are marked compatible with color types but I didn't change how color types were mapped to formats. Bug: b/390473370 Change-Id: I1851bedad6083e577fb8c0e9e096844582d86206 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1167440 Reviewed-by: Thomas Smith <thomsmit@google.com> Reviewed-by: Nicolette Prevost <nicolettep@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/gn/tests.gni b/gn/tests.gni index 346cf0c..73a119d 100644 --- a/gn/tests.gni +++ b/gn/tests.gni
@@ -323,6 +323,7 @@ "$_tests/graphite/RecordingSurfacesTest.cpp", "$_tests/graphite/RectTest.cpp", "$_tests/graphite/ShapeTest.cpp", + "$_tests/graphite/TextureFormatTest.h", "$_tests/graphite/TextureProxyTest.cpp", "$_tests/graphite/TransformTest.cpp", "$_tests/graphite/UniformManagerTest.cpp", @@ -352,9 +353,16 @@ "$_tests/graphite/precompile/UserdefinedStableKeyTest.cpp", ] -graphite_dawn_tests_sources = [ "$_tests/graphite/DawnBackendTextureTest.cpp" ] -graphite_metal_tests_sources = [ "$_tests/graphite/MtlBackendTextureTest.mm" ] +graphite_dawn_tests_sources = [ + "$_tests/graphite/DawnBackendTextureTest.cpp", + "$_tests/graphite/TextureFormatTest_dawn.cpp", +] +graphite_metal_tests_sources = [ + "$_tests/graphite/MtlBackendTextureTest.mm", + "$_tests/graphite/TextureFormatTest_mtl.mm", +] graphite_vulkan_tests_sources = [ + "$_tests/graphite/TextureFormatTest_vk.cpp", "$_tests/graphite/VulkanBackendTextureTest.cpp", "$_tests/graphite/VulkanDstReadRenderpassReuseTest.cpp", ]
diff --git a/src/gpu/graphite/Caps.cpp b/src/gpu/graphite/Caps.cpp index 3b120d3..a06bcbd 100644 --- a/src/gpu/graphite/Caps.cpp +++ b/src/gpu/graphite/Caps.cpp
@@ -255,7 +255,7 @@ } return this->getDefaultTextureInfo(usage, - this->getFormatForColorType(colorType), + this->getFormatForColorType(colorType, renderable), SampleCount::k1, mipmapped, isProtected, @@ -289,7 +289,7 @@ return this->getDefaultTextureInfo(TextureUsage::kStorage | TextureUsage::kSample | TextureUsage::kCopySrc, - this->getFormatForColorType(colorType), + this->getFormatForColorType(colorType, Renderable::kNo), SampleCount::k1, Mipmapped::kNo, Protected::kNo,
diff --git a/src/gpu/graphite/Caps.h b/src/gpu/graphite/Caps.h index c7e557b..99f93c4 100644 --- a/src/gpu/graphite/Caps.h +++ b/src/gpu/graphite/Caps.h
@@ -565,7 +565,7 @@ // approach to textures and color types. const ColorTypeInfo* getColorTypeInfo(SkColorType, const TextureInfo&) const; virtual SkSpan<const ColorTypeInfo> getColorTypeInfos(const TextureInfo&) const = 0; - virtual TextureFormat getFormatForColorType(SkColorType) const = 0; + virtual TextureFormat getFormatForColorType(SkColorType, Renderable) const = 0; // Return a TextureInfo that is configured to support the given usages with the requested format // and other properties. This is only called if getTextureSupport() matches for kOptimal tiling.
diff --git a/src/gpu/graphite/TextureFormat.cpp b/src/gpu/graphite/TextureFormat.cpp index 9c95465..2ed90bf 100644 --- a/src/gpu/graphite/TextureFormat.cpp +++ b/src/gpu/graphite/TextureFormat.cpp
@@ -121,7 +121,7 @@ case TextureFormat::kD16: return 2; case TextureFormat::kD32F: return 4; case TextureFormat::kD24_S8: return 4; - case TextureFormat::kD32F_S8: return 8; + case TextureFormat::kD32F_S8: return 5; // assuming it's multiplanar // NOTE: For compressed formats, the block size refers to an actual compressed block of // multiple texels, whereas with other formats the block size represents a single pixel. case TextureFormat::kRGB8_ETC2:
diff --git a/src/gpu/graphite/dawn/DawnCaps.cpp b/src/gpu/graphite/dawn/DawnCaps.cpp index 901f355..6bc64af 100644 --- a/src/gpu/graphite/dawn/DawnCaps.cpp +++ b/src/gpu/graphite/dawn/DawnCaps.cpp
@@ -57,17 +57,33 @@ wgpu::TextureFormat::RG8Unorm, #if !defined(__EMSCRIPTEN__) wgpu::TextureFormat::RG16Unorm, + wgpu::TextureFormat::RGBA16Unorm, #endif wgpu::TextureFormat::RGB10A2Unorm, wgpu::TextureFormat::RG16Float, + wgpu::TextureFormat::R32Float, + wgpu::TextureFormat::RG32Float, + wgpu::TextureFormat::RGBA32Float, + + wgpu::TextureFormat::RGBA8UnormSrgb, + wgpu::TextureFormat::BGRA8UnormSrgb, + wgpu::TextureFormat::Stencil8, wgpu::TextureFormat::Depth16Unorm, wgpu::TextureFormat::Depth32Float, wgpu::TextureFormat::Depth24PlusStencil8, + wgpu::TextureFormat::Depth32FloatStencil8, wgpu::TextureFormat::BC1RGBAUnorm, + wgpu::TextureFormat::BC1RGBAUnormSrgb, wgpu::TextureFormat::ETC2RGB8Unorm, + wgpu::TextureFormat::ETC2RGB8UnormSrgb, + wgpu::TextureFormat::ETC2RGBA8Unorm, + wgpu::TextureFormat::ETC2RGBA8UnormSrgb, + + wgpu::TextureFormat::R8BG8Biplanar420Unorm, + wgpu::TextureFormat::R10X6BG10X6Biplanar420Unorm, #if !defined(__EMSCRIPTEN__) wgpu::TextureFormat::OpaqueYCbCrAndroid, @@ -258,8 +274,40 @@ return TextureInfos::MakeDawn(info); } -TextureFormat DawnCaps::getFormatForColorType(SkColorType colorType) const { - return DawnFormatToTextureFormat(this->getFormatFromColorType(colorType)); +TextureFormat DawnCaps::getFormatForColorType(SkColorType colorType, Renderable renderable) const { + wgpu::TextureFormat dawnFormat = this->getFormatFromColorType(colorType); + if (dawnFormat == wgpu::TextureFormat::Undefined) { + return TextureFormat::kUnsupported; + } + + auto supportsColorType = [colorType, renderable](const FormatInfo& info) { + for (int i = 0; i < info.fColorTypeInfoCount; ++i) { + const ColorTypeInfo& ctInfo = info.fColorTypeInfos[i]; + if (ctInfo.fColorType == colorType && + (renderable == Renderable::kNo || + ctInfo.fFlags & Caps::ColorTypeInfo::kRenderable_Flag)) { + return true; + } + } + return false; + }; + + const FormatInfo& preferredInfo = this->getFormatInfo(dawnFormat); + if (supportsColorType(preferredInfo)) { + return DawnFormatToTextureFormat(dawnFormat); + } + + // We don't just use getFormatFromColorType(), since that returns the first format that + // initialized the color type, but is not necessarily the color type that supports the + // renderability requirement, e.g. RGBA8 can support RGBx but is not renderable; RGB8 also + // supports RGBx and is renderable. + for (int j = 0; j < kFormatCount; ++j) { + if (supportsColorType(fFormatTable[j])) { + return DawnFormatToTextureFormat(kFormats[j]); + } + } + + return TextureFormat::kUnsupported; } SkISize DawnCaps::getDepthAttachmentDimensions(const TextureInfo& textureInfo, @@ -294,7 +342,6 @@ const TextureInfo& textureInfo) const { auto dawnFormat = TextureInfoPriv::Get<DawnTextureInfo>(textureInfo).getViewFormat(); if (dawnFormat == wgpu::TextureFormat::Undefined) { - SkASSERT(false); return {}; } @@ -508,7 +555,7 @@ { info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::RGBA8Unorm)]; info->fFlags = FormatInfo::kAllFlags; - info->fColorTypeInfoCount = 2; + info->fColorTypeInfoCount = 3; info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); int ctIdx = 0; // Format: RGBA8Unorm, Surface: kRGBA_8888 @@ -518,6 +565,13 @@ ctInfo.fTransferColorType = kRGBA_8888_SkColorType; ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; } + // Format: RGBA8Unorm, Surface: kBGRA_8888 + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kBGRA_8888_SkColorType; + ctInfo.fTransferColorType = kRGBA_8888_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; + } // Format: RGBA8Unorm, Surface: kRGB_888x { auto& ctInfo = info->fColorTypeInfos[ctIdx++]; @@ -599,7 +653,7 @@ { info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::BGRA8Unorm)]; info->fFlags = FormatInfo::kAllFlags; - info->fColorTypeInfoCount = 2; + info->fColorTypeInfoCount = 3; info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); int ctIdx = 0; // Format: BGRA8Unorm, Surface: kBGRA_8888 @@ -609,6 +663,13 @@ ctInfo.fTransferColorType = kBGRA_8888_SkColorType; ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; } + // Format: BGRA8Unorm, Surface: kRGBA_8888 + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kRGBA_8888_SkColorType; + ctInfo.fTransferColorType = kBGRA_8888_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; + } // Format: BGRA8Unorm, Surface: kRGB_888x { auto& ctInfo = info->fColorTypeInfos[ctIdx++]; @@ -617,6 +678,7 @@ // SkConvertPixels to force alpha to opaque when kRGB_888x is either the src or dst type ctInfo.fTransferColorType = kBGRA_8888_SkColorType; ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; + ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1(); } } @@ -624,7 +686,7 @@ { info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::RGBA16Float)]; info->fFlags = FormatInfo::kAllFlags; - info->fColorTypeInfoCount = 2; + info->fColorTypeInfoCount = 3; info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); int ctIdx = 0; // Format: RGBA16Float, Surface: RGBA_F16 @@ -634,6 +696,13 @@ ctInfo.fTransferColorType = kRGBA_F16_SkColorType; ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; } + // Format: RGBA16Float, Surface: RGBA_F16Norm + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kRGBA_F16Norm_SkColorType; + ctInfo.fTransferColorType = kRGBA_F16Norm_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; + } // Format: RGBA16Float, Surface: RGB_F16F16F16x { auto& ctInfo = info->fColorTypeInfos[ctIdx++]; @@ -704,7 +773,7 @@ { info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::RGB10A2Unorm)]; info->fFlags = FormatInfo::kAllFlags; - info->fColorTypeInfoCount = 2; + info->fColorTypeInfoCount = 4; info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); int ctIdx = 0; // Format: RGB10A2Unorm, Surface: kRGBA_1010102 @@ -714,6 +783,13 @@ ctInfo.fTransferColorType = kRGBA_1010102_SkColorType; ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; } + // Format: RGB10A2Unorm, Surface: kBGRA_1010102 + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kBGRA_1010102_SkColorType; + ctInfo.fTransferColorType = kRGBA_1010102_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; + } // Format: RGB10A2Unorm, Surface: kRGB_101010x { auto& ctInfo = info->fColorTypeInfos[ctIdx++]; @@ -722,6 +798,46 @@ ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1(); } + // Format: RGB10A2Unorm, Surface: kBGR_101010x + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kBGR_101010x_SkColorType; + ctInfo.fTransferColorType = kRGB_101010x_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; + ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1(); + } + } + + // Format RGBA32Float + { + info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::RGBA32Float)]; + info->fFlags = FormatInfo::kAllFlags; + info->fColorTypeInfoCount = 1; + info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); + int ctIdx = 0; + // Format: RGBA32Float, Surface: kRGBA_F32 + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kRGBA_F32_SkColorType; + ctInfo.fTransferColorType = kRGBA_F32_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; + } + } + + // Format: RGBA8UnormSrgb + { + info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::RGBA8UnormSrgb)]; + info->fFlags = FormatInfo::kAllFlags; + info->fColorTypeInfoCount = 1; + info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); + int ctIdx = 0; + // Format: RGBA8UnormSrgb, Surface: kSRGBA_8888 + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kSRGBA_8888_SkColorType; + ctInfo.fTransferColorType = kSRGBA_8888_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; + } } // Format: RG16Float @@ -740,38 +856,110 @@ } } - // Format: ETC2RGB8Unorm + // ETC2 { if (device.HasFeature(wgpu::FeatureName::TextureCompressionETC2)) { - info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::ETC2RGB8Unorm)]; - info->fFlags = FormatInfo::kTexturable_Flag; - info->fColorTypeInfoCount = 1; - info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); - int ctIdx = 0; - // Format: ETC2RGB8Unorm, Surface: kRGB_888x + // Format: ETC2RGB8Unorm { - auto& ctInfo = info->fColorTypeInfos[ctIdx++]; - ctInfo.fColorType = kRGB_888x_SkColorType; - ctInfo.fTransferColorType = kRGB_888x_SkColorType; - ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; + info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::ETC2RGB8Unorm)]; + info->fFlags = FormatInfo::kTexturable_Flag; + info->fColorTypeInfoCount = 1; + info->fColorTypeInfos = + std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); + int ctIdx = 0; + // Format: ETC2RGB8Unorm, Surface: kRGB_888x + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kRGB_888x_SkColorType; + ctInfo.fTransferColorType = kRGB_888x_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; + } + } + // Format: ETC2RGB8UnormSrgb + { + info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::ETC2RGB8UnormSrgb)]; + info->fFlags = FormatInfo::kTexturable_Flag; + info->fColorTypeInfoCount = 1; + info->fColorTypeInfos = + std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); + int ctIdx = 0; + // Format: ETC2RGB8UnormSrgb, Surface: kSRGBA_8888 + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kSRGBA_8888_SkColorType; + ctInfo.fTransferColorType = kSRGBA_8888_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; + } + } + // Format: ETC2RGBA8Unorm + { + info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::ETC2RGBA8Unorm)]; + info->fFlags = FormatInfo::kTexturable_Flag; + info->fColorTypeInfoCount = 1; + info->fColorTypeInfos = + std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); + int ctIdx = 0; + // Format: ETC2RGBA8Unorm, Surface: kRGBA_8888 + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kRGBA_8888_SkColorType; + ctInfo.fTransferColorType = kRGBA_8888_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; + } + } + // Format: ETC2RGB8UnormSrgb + { + info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::ETC2RGBA8UnormSrgb)]; + info->fFlags = FormatInfo::kTexturable_Flag; + info->fColorTypeInfoCount = 1; + info->fColorTypeInfos = + std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); + int ctIdx = 0; + // Format: ETC2RGBA8UnormSrgb, Surface: kSRGBA_8888 + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kSRGBA_8888_SkColorType; + ctInfo.fTransferColorType = kSRGBA_8888_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; + } } } } - // Format: BC1RGBAUnorm + // BC1 { if (device.HasFeature(wgpu::FeatureName::TextureCompressionBC)) { - info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::BC1RGBAUnorm)]; - info->fFlags = FormatInfo::kTexturable_Flag; - info->fColorTypeInfoCount = 1; - info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); - int ctIdx = 0; - // Format: BC1RGBAUnorm, Surface: kRGBA_8888 + // Format: BC1RGBAUnorm { - auto& ctInfo = info->fColorTypeInfos[ctIdx++]; - ctInfo.fColorType = kRGBA_8888_SkColorType; - ctInfo.fTransferColorType = kRGBA_8888_SkColorType; - ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; + info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::BC1RGBAUnorm)]; + info->fFlags = FormatInfo::kTexturable_Flag; + info->fColorTypeInfoCount = 1; + info->fColorTypeInfos = + std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); + int ctIdx = 0; + // Format: BC1RGBAUnorm, Surface: kRGBA_8888 + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kRGBA_8888_SkColorType; + ctInfo.fTransferColorType = kRGBA_8888_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; + } + } + // Format: BC1RGBAUnormSrgb + { + info = &fFormatTable[GetFormatIndex(wgpu::TextureFormat::BC1RGBAUnormSrgb)]; + info->fFlags = FormatInfo::kTexturable_Flag; + info->fColorTypeInfoCount = 1; + info->fColorTypeInfos = + std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); + int ctIdx = 0; + // Format: BC1RGBAUnorm, Surface: kSRGBA_8888 + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kSRGBA_8888_SkColorType; + ctInfo.fTransferColorType = kSRGBA_8888_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; + } } } } @@ -825,6 +1013,7 @@ { auto& ctInfo = info->fColorTypeInfos[ctIdx++]; ctInfo.fColorType = kRGB_888x_SkColorType; + ctInfo.fReadSwizzle = Swizzle::RGB1(); } } #endif @@ -872,7 +1061,7 @@ void DawnCaps::setColorType(SkColorType colorType, std::initializer_list<wgpu::TextureFormat> formats) { - static_assert(std::size(kFormats) <= kFormatCount, + static_assert(std::size(kFormats) == kFormatCount, "Size is not compatible for DawnCaps::fFormatTable and kFormats"); int idx = static_cast<int>(colorType); for (auto it = formats.begin(); it != formats.end(); ++it) {
diff --git a/src/gpu/graphite/dawn/DawnCaps.h b/src/gpu/graphite/dawn/DawnCaps.h index 9431102..c7f98e8 100644 --- a/src/gpu/graphite/dawn/DawnCaps.h +++ b/src/gpu/graphite/dawn/DawnCaps.h
@@ -69,7 +69,7 @@ private: SkSpan<const ColorTypeInfo> getColorTypeInfos(const TextureInfo&) const override; - TextureFormat getFormatForColorType(SkColorType) const override; + TextureFormat getFormatForColorType(SkColorType, Renderable) const override; TextureInfo onGetDefaultTextureInfo(SkEnumBitMask<TextureUsage> usage, TextureFormat, SampleCount, @@ -116,7 +116,7 @@ int fColorTypeInfoCount = 0; }; // Size here must be at least the size of kFormats in DawnCaps.cpp. - static constexpr size_t kFormatCount = 18; + static constexpr int kFormatCount = 31; std::array<FormatInfo, kFormatCount> fFormatTable; static size_t GetFormatIndex(wgpu::TextureFormat format);
diff --git a/src/gpu/graphite/mtl/MtlCaps.h b/src/gpu/graphite/mtl/MtlCaps.h index aa3d00d..23b8cd8 100644 --- a/src/gpu/graphite/mtl/MtlCaps.h +++ b/src/gpu/graphite/mtl/MtlCaps.h
@@ -65,7 +65,7 @@ } SkSpan<const ColorTypeInfo> getColorTypeInfos(const TextureInfo&) const override; - TextureFormat getFormatForColorType(SkColorType) const override; + TextureFormat getFormatForColorType(SkColorType, Renderable) const override; TextureInfo onGetDefaultTextureInfo(SkEnumBitMask<TextureUsage> usage, TextureFormat, SampleCount, @@ -103,9 +103,9 @@ int fColorTypeInfoCount = 0; }; #ifdef SK_BUILD_FOR_MAC - inline static constexpr size_t kNumMtlFormats = 23; + inline static constexpr int kNumMtlFormats = 23; #else - inline static constexpr size_t kNumMtlFormats = 21; + inline static constexpr int kNumMtlFormats = 21; #endif static size_t GetFormatIndex(MTLPixelFormat);
diff --git a/src/gpu/graphite/mtl/MtlCaps.mm b/src/gpu/graphite/mtl/MtlCaps.mm index d9c36ed..2ab77bb 100644 --- a/src/gpu/graphite/mtl/MtlCaps.mm +++ b/src/gpu/graphite/mtl/MtlCaps.mm
@@ -319,7 +319,7 @@ { info = &fFormatTable[GetFormatIndex(MTLPixelFormatRGBA8Unorm)]; info->fFlags = FormatInfo::kAllFlags; - info->fColorTypeInfoCount = 2; + info->fColorTypeInfoCount = 3; info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); int ctIdx = 0; // Format: RGBA8Unorm, Surface: kRGBA_8888 @@ -329,6 +329,13 @@ ctInfo.fTransferColorType = kRGBA_8888_SkColorType; ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; } + // Format: RGBA8Unorm, Surface: kBGRA_8888 + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kBGRA_8888_SkColorType; + ctInfo.fTransferColorType = kRGBA_8888_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; + } // Format: RGBA8Unorm, Surface: kRGB_888x { auto& ctInfo = info->fColorTypeInfos[ctIdx++]; @@ -392,7 +399,7 @@ { info = &fFormatTable[GetFormatIndex(MTLPixelFormatBGRA8Unorm)]; info->fFlags = FormatInfo::kAllFlags; - info->fColorTypeInfoCount = 1; + info->fColorTypeInfoCount = 3; info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); int ctIdx = 0; // Format: BGRA8Unorm, Surface: kBGRA_8888 @@ -402,6 +409,23 @@ ctInfo.fTransferColorType = kBGRA_8888_SkColorType; ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; } + // Format: BGRA8Unorm, Surface: kRGBA_8888 + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kRGBA_8888_SkColorType; + ctInfo.fTransferColorType = kBGRA_8888_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; + } + // Format: BGRA8Unorm, Surface: kRGB_888x + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kRGB_888x_SkColorType; + // There is no kBGR_888x color type, so report that the data is BGRA and rely on + // SkConvertPixels to force alpha to opaque when kRGB_888x is either the src or dst type + ctInfo.fTransferColorType = kBGRA_8888_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; + ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1(); + } } if (@available(macOS 11.0, iOS 8.0, tvOS 9.0, *)) { @@ -468,7 +492,7 @@ } else { info->fFlags = FormatInfo::kTexturable_Flag; } - info->fColorTypeInfoCount = 2; + info->fColorTypeInfoCount = 4; info->fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info->fColorTypeInfoCount); int ctIdx = 0; // Format: RGB10A2Unorm, Surface: kRGBA_1010102 @@ -478,6 +502,13 @@ ctInfo.fTransferColorType = kRGBA_1010102_SkColorType; ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; } + // Format: RGB10A2Unorm, Surface: kBGRA_1010102 + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kBGRA_1010102_SkColorType; + ctInfo.fTransferColorType = kRGBA_1010102_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; + } // Format: RGB10A2Unorm, Surface: kRGB_101010x { auto& ctInfo = info->fColorTypeInfos[ctIdx++]; @@ -486,6 +517,14 @@ ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1(); } + // Format: BGR10A2Unorm, Surface: kBGR_101010x + { + auto& ctInfo = info->fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = kBGR_101010x_SkColorType; + ctInfo.fTransferColorType = kRGB_101010x_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; + ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1(); + } } // Format: RGBA16Float @@ -894,8 +933,40 @@ return TextureInfos::MakeMetal(info); } -TextureFormat MtlCaps::getFormatForColorType(SkColorType colorType) const { - return MTLPixelFormatToTextureFormat(this->getFormatFromColorType(colorType)); +TextureFormat MtlCaps::getFormatForColorType(SkColorType colorType, Renderable renderable) const { + MTLPixelFormat mtlFormat = this->getFormatFromColorType(colorType); + if (mtlFormat == MTLPixelFormatInvalid) { + return TextureFormat::kUnsupported; + } + + auto supportsColorType = [colorType, renderable](const FormatInfo& info) { + for (int i = 0; i < info.fColorTypeInfoCount; ++i) { + const ColorTypeInfo& ctInfo = info.fColorTypeInfos[i]; + if (ctInfo.fColorType == colorType && + (renderable == Renderable::kNo || + ctInfo.fFlags & Caps::ColorTypeInfo::kRenderable_Flag)) { + return true; + } + } + return false; + }; + + const FormatInfo& preferredInfo = this->getFormatInfo(mtlFormat); + if (supportsColorType(preferredInfo)) { + return MTLPixelFormatToTextureFormat(mtlFormat); + } + + // We don't just use getFormatFromColorType(), since that returns the first format that + // initialized the color type, but is not necessarily the color type that supports the + // renderability requirement, e.g. RGBA8 can support RGBx but is not renderable; RGB8 also + // supports RGBx and is renderable. + for (int j = 0; j < kNumMtlFormats; ++j) { + if (supportsColorType(fFormatTable[j])) { + return MTLPixelFormatToTextureFormat(kMtlFormats[j]); + } + } + + return TextureFormat::kUnsupported; } namespace {
diff --git a/src/gpu/graphite/vk/VulkanCaps.cpp b/src/gpu/graphite/vk/VulkanCaps.cpp index 214a4f0..43ee2b7 100644 --- a/src/gpu/graphite/vk/VulkanCaps.cpp +++ b/src/gpu/graphite/vk/VulkanCaps.cpp
@@ -894,8 +894,40 @@ return TextureInfos::MakeVulkan(info); } -TextureFormat VulkanCaps::getFormatForColorType(SkColorType colorType) const { - return VkFormatToTextureFormat(this->getFormatFromColorType(colorType)); +TextureFormat VulkanCaps::getFormatForColorType(SkColorType colorType, Renderable renderable) const { + VkFormat vkFormat = this->getFormatFromColorType(colorType); + if (vkFormat == VK_FORMAT_UNDEFINED) { + return TextureFormat::kUnsupported; + } + + auto supportsColorType = [colorType, renderable](const FormatInfo& info) { + for (int i = 0; i < info.fColorTypeInfoCount; ++i) { + const ColorTypeInfo& ctInfo = info.fColorTypeInfos[i]; + if (ctInfo.fColorType == colorType && + (renderable == Renderable::kNo || + ctInfo.fFlags & Caps::ColorTypeInfo::kRenderable_Flag)) { + return true; + } + } + return false; + }; + + const FormatInfo& preferredInfo = this->getFormatInfo(vkFormat); + if (supportsColorType(preferredInfo)) { + return VkFormatToTextureFormat(vkFormat); + } + + // We don't just use getFormatFromColorType(), since that returns the first format that + // initialized the color type, but is not necessarily the color type that supports the + // renderability requirement, e.g. RGBA8 can support RGBx but is not renderable; RGB8 also + // supports RGBx and is renderable. + for (int j = 0; j < kNumVkFormats; ++j) { + if (supportsColorType(fFormatTable[j])) { + return VkFormatToTextureFormat(kVkFormats[j]); + } + } + + return TextureFormat::kUnsupported; } void VulkanCaps::initShaderCaps(const EnabledFeatures enabledFeatures, const uint32_t vendorID) { @@ -931,7 +963,7 @@ auto& info = this->getFormatInfoForInit(format); info.init(interface, *this, physDev, format); if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) { - info.fColorTypeInfoCount = 2; + info.fColorTypeInfoCount = 3; info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount); int ctIdx = 0; // Format: VK_FORMAT_R8G8B8A8_UNORM, Surface: kRGBA_8888 @@ -942,6 +974,14 @@ ctInfo.fTransferColorType = ct; ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; } + // Format: VK_FORMAT_R8G8B8A8_UNORM, Surface: kBGRA_8888 + { + constexpr SkColorType ct = SkColorType::kBGRA_8888_SkColorType; + auto& ctInfo = info.fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = ct; + ctInfo.fTransferColorType = kRGBA_8888_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; + } // Format: VK_FORMAT_R8G8B8A8_UNORM, Surface: kRGB_888x { constexpr SkColorType ct = SkColorType::kRGB_888x_SkColorType; @@ -999,7 +1039,7 @@ auto& info = this->getFormatInfoForInit(format); info.init(interface, *this, physDev, format); if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) { - info.fColorTypeInfoCount = 2; + info.fColorTypeInfoCount = 3; info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount); int ctIdx = 0; // Format: VK_FORMAT_B8G8R8A8_UNORM, Surface: kBGRA_8888 @@ -1064,6 +1104,15 @@ ctInfo.fTransferColorType = transferColorType; ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; } + // Format: VK_FORMAT_B8G8R8A8_UNORM, Surface: kRGB_888x + { + constexpr SkColorType ct = SkColorType::kRGB_888x_SkColorType; + auto& ctInfo = info.fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = ct; + ctInfo.fTransferColorType = SkColorType::kBGRA_8888_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; + ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1(); + } } } // Format: VK_FORMAT_R5G6B5_UNORM_PACK16 @@ -1091,7 +1140,7 @@ auto& info = this->getFormatInfoForInit(format); info.init(interface, *this, physDev, format); if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) { - info.fColorTypeInfoCount = 2; + info.fColorTypeInfoCount = 3; info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount); int ctIdx = 0; // Format: VK_FORMAT_R16G16B16A16_SFLOAT, Surface: kRGBA_F16_SkColorType @@ -1102,6 +1151,14 @@ ctInfo.fTransferColorType = ct; ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; } + // Format: VK_FORMAT_R16G16B16A16_SFLOAT, Surface: kRGBA_F16Norm_SkColorType + { + constexpr SkColorType ct = SkColorType::kRGBA_F16Norm_SkColorType; + auto& ctInfo = info.fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = ct; + ctInfo.fTransferColorType = ct; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; + } // Format: VK_FORMAT_R16G16B16A16_SFLOAT, Surface: kRGB_F16F16F16x_SkColorType { constexpr SkColorType ct = SkColorType::kRGB_F16F16F16x_SkColorType; @@ -1182,7 +1239,7 @@ auto& info = this->getFormatInfoForInit(format); info.init(interface, *this, physDev, format); if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) { - info.fColorTypeInfoCount = 2; + info.fColorTypeInfoCount = 4; info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount); int ctIdx = 0; // Format: VK_FORMAT_A2B10G10R10_UNORM_PACK32, Surface: kRGBA_1010102 @@ -1193,6 +1250,14 @@ ctInfo.fTransferColorType = ct; ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; } + // Format: VK_FORMAT_A2B10G10R10_UNORM_PACK32, Surface: kBGRA_1010102 + { + constexpr SkColorType ct = SkColorType::kBGRA_1010102_SkColorType; + auto& ctInfo = info.fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = ct; + ctInfo.fTransferColorType = SkColorType::kRGBA_1010102_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; + } // Format: VK_FORMAT_A2B10G10R10_UNORM_PACK32, Surface: kRGB_101010x { constexpr SkColorType ct = SkColorType::kRGB_101010x_SkColorType; @@ -1202,6 +1267,15 @@ ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1(); } + // Format: VK_FORMAT_A2B10G10R10_UNORM_PACK32, Surface: kBGR_101010x + { + constexpr SkColorType ct = SkColorType::kBGR_101010x_SkColorType; + auto& ctInfo = info.fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = ct; + ctInfo.fTransferColorType = SkColorType::kRGB_101010x_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; + ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1(); + } } } // Format: VK_FORMAT_A2R10G10B10_UNORM_PACK32 @@ -1210,7 +1284,7 @@ auto& info = this->getFormatInfoForInit(format); info.init(interface, *this, physDev, format); if (info.isTexturable(VK_IMAGE_TILING_OPTIMAL)) { - info.fColorTypeInfoCount = 1; + info.fColorTypeInfoCount = 4; info.fColorTypeInfos = std::make_unique<ColorTypeInfo[]>(info.fColorTypeInfoCount); int ctIdx = 0; // Format: VK_FORMAT_A2R10G10B10_UNORM_PACK32, Surface: kBGRA_1010102 @@ -1221,6 +1295,32 @@ ctInfo.fTransferColorType = ct; ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; } + // Format: VK_FORMAT_A2R10G10B10_UNORM_PACK32, Surface: kRGBA_1010102 + { + constexpr SkColorType ct = SkColorType::kRGBA_1010102_SkColorType; + auto& ctInfo = info.fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = ct; + ctInfo.fTransferColorType = SkColorType::kBGRA_1010102_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag | ColorTypeInfo::kRenderable_Flag; + } + // Format: VK_FORMAT_A2R10G10B10_UNORM_PACK32, Surface: kBGR_101010x + { + constexpr SkColorType ct = SkColorType::kBGR_101010x_SkColorType; + auto& ctInfo = info.fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = ct; + ctInfo.fTransferColorType = ct; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; + ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1(); + } + // Format: VK_FORMAT_A2R10G10B10_UNORM_PACK32, Surface: kRGB_101010x + { + constexpr SkColorType ct = SkColorType::kRGB_101010x_SkColorType; + auto& ctInfo = info.fColorTypeInfos[ctIdx++]; + ctInfo.fColorType = ct; + ctInfo.fTransferColorType = kBGR_101010x_SkColorType; + ctInfo.fFlags = ColorTypeInfo::kUploadData_Flag; + ctInfo.fReadSwizzle = skgpu::Swizzle::RGB1(); + } } } // Format: VK_FORMAT_B4G4R4A4_UNORM_PACK16 @@ -1244,6 +1344,9 @@ // rendering into it has it match the reported transfer color type, but we have to // swap R and B when sampling as well. This only works so long as we don't present // textures of this format to a screen that would not know about this swap. + // TODO(b/b/390473370): When data transfers can apply an RG swizzle outside of the + // SkColorType representation, we should instead apply the swizzle on upload and + // preserve the expected order for any GPU use. ctInfo.fReadSwizzle = skgpu::Swizzle::BGRA(); ctInfo.fWriteSwizzle = skgpu::Swizzle::BGRA(); }
diff --git a/src/gpu/graphite/vk/VulkanCaps.h b/src/gpu/graphite/vk/VulkanCaps.h index e5c2fc6..4d3d611 100644 --- a/src/gpu/graphite/vk/VulkanCaps.h +++ b/src/gpu/graphite/vk/VulkanCaps.h
@@ -167,7 +167,7 @@ const VkPhysicalDeviceProperties&); SkSpan<const ColorTypeInfo> getColorTypeInfos(const TextureInfo&) const override; - TextureFormat getFormatForColorType(SkColorType) const override; + TextureFormat getFormatForColorType(SkColorType, Renderable) const override; TextureInfo onGetDefaultTextureInfo(SkEnumBitMask<TextureUsage> usage, TextureFormat, SampleCount, @@ -244,7 +244,7 @@ VkFormat getFormatFromColorType(SkColorType) const; // Map VkFormat to FormatInfo. - static const size_t kNumVkFormats = 24; + static const int kNumVkFormats = 24; FormatInfo fFormatTable[kNumVkFormats]; FormatInfo& getFormatInfoForInit(VkFormat);
diff --git a/tests/graphite/TextureFormatTest.h b/tests/graphite/TextureFormatTest.h new file mode 100644 index 0000000..1ede7c5 --- /dev/null +++ b/tests/graphite/TextureFormatTest.h
@@ -0,0 +1,560 @@ +/* + * Copyright 2026 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "tests/Test.h" + +#include "include/core/SkColorType.h" +#include "include/gpu/graphite/TextureInfo.h" +#include "include/private/base/SkTArray.h" +#include "src/gpu/Swizzle.h" +#include "src/gpu/graphite/Caps.h" +#include "src/gpu/graphite/TextureFormat.h" +#include "src/gpu/graphite/TextureInfoPriv.h" + +namespace skgpu::graphite { + +struct ColorTypeExpectation { + SkColorType fColorType; + Swizzle fReadSwizzle; + std::optional<Swizzle> fWriteSwizzle; // not set implies not renderable +}; + +struct FormatExpectation { + TextureFormat fFormat; + + // Fixed properties + SkTextureCompressionType fCompressionType; + size_t fBytesPerBlock; + uint32_t fChannelMask; + bool fHasDepth; + bool fHasStencil; + bool fMultiplanar; + bool fAutoClamps; + bool fIsFloatingPoint; + + // The first color type expectation is assumed to be the best fit. + skia_private::TArray<ColorTypeExpectation> fCompatibleColorTypes; +}; + +inline +FormatExpectation MakeColor(TextureFormat format, + size_t bytesPerBlock, + uint32_t channels, + bool multiplanar, + bool autoClamps, + bool isFloatingPoint, + std::initializer_list<ColorTypeExpectation> compatibleColorTypes) { + return {format, SkTextureCompressionType::kNone, bytesPerBlock, channels, /*fHasDepth=*/false, + /*fHasStencil=*/false, multiplanar, autoClamps, isFloatingPoint, compatibleColorTypes}; +} + +inline +FormatExpectation MakeCompressed(TextureFormat format, + SkTextureCompressionType compressionType, + size_t bytesPerBlock, + uint32_t channels, + std::initializer_list<ColorTypeExpectation> compatibleColorTypes) { + return {format, compressionType, bytesPerBlock, channels, /*fHasDepth=*/false, + /*fHasStencil=*/false, /*fMultiplanar=*/false, /*fAutoClamps=*/true, + /*fIsFloatingPoint=*/false, compatibleColorTypes}; +} + +inline +FormatExpectation MakeDepthStencil(TextureFormat format, size_t + bytesPerBlock, + bool hasDepth, + bool hasStencil, + bool autoClamps, + bool isFloatingPoint) { + return {format, SkTextureCompressionType::kNone, bytesPerBlock, /*fChannelMask=*/0, hasDepth, + hasStencil, /*fMultiplanar=*/false, autoClamps, isFloatingPoint, + /*compatibleColorTypes=*/{}}; +} + +static const FormatExpectation kExpectations[] { + MakeColor(TextureFormat::kUnsupported, + /*bytesPerBlock=*/0, + /*channels=*/0, + /*multiplanar=*/false, + /*autoClamps=*/true, // true is the "default" for auto-clamping behavior + /*isFloatingPoint=*/false, + {}), + + // TODO(michaelludwig): Right now the alpha-only color types are the expected defaults for + // red formats. In the future this will be changed to red-only color type. + MakeColor(TextureFormat::kR8, + /*bytesPerBlock=*/1, + kRed_SkColorChannelFlag, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kAlpha_8_SkColorType, Swizzle("000r"), Swizzle("a000")}, + {kR8_unorm_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}, + {kGray_8_SkColorType, Swizzle("rrr1"), std::nullopt}}), + + MakeColor(TextureFormat::kR16, + /*bytesPerBlock=*/2, + kRed_SkColorChannelFlag, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kA16_unorm_SkColorType, Swizzle("000r"), Swizzle("a000")}, + {kR16_unorm_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kR16F, + /*bytesPerBlock=*/2, + kRed_SkColorChannelFlag, + /*multiplanar=*/false, + /*autoClamps=*/false, + /*isFloatingPoint=*/true, + {{kA16_float_SkColorType, Swizzle("000r"), Swizzle("a000")}}), + + MakeColor(TextureFormat::kR32F, + /*bytesPerBlock=*/4, + kRed_SkColorChannelFlag, + /*multiplanar=*/false, + /*autoClamps=*/false, + /*isFloatingPoint=*/true, + // TODO(michaelludwig): Use kR16_float_SkColorType once + // https://skia-review.git.corp.google.com/c/skia/+/1165337 is landed. + {{kA16_float_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kA8, + /*bytesPerBlock=*/1, + kAlpha_SkColorChannelFlag, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kAlpha_8_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kRG8, + /*bytesPerBlock=*/2, + kRed_SkColorChannelFlag | kGreen_SkColorChannelFlag, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kR8G8_unorm_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kRG16, + /*bytesPerBlock=*/4, + kRed_SkColorChannelFlag | kGreen_SkColorChannelFlag, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kR16G16_unorm_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kRG16F, + /*bytesPerBlock=*/4, + kRed_SkColorChannelFlag | kGreen_SkColorChannelFlag, + /*multiplanar=*/false, + /*autoClamps=*/false, + /*isFloatingPoint=*/true, + {{kR16G16_float_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kRG32F, + /*bytesPerBlock=*/8, + kRed_SkColorChannelFlag | kGreen_SkColorChannelFlag, + /*multiplanar=*/false, + /*autoClamps=*/false, + /*isFloatingPoint=*/true, + {{kR16G16_float_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kRGB8, + /*bytesPerBlock=*/3, + kRGB_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kRGB_888x_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kBGR8, + /*bytesPerBlock=*/3, + kRGB_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kRGB_888x_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kB5_G6_R5, + /*bytesPerBlock=*/2, + kRGB_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kRGB_565_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kR5_G6_B5, + /*bytesPerBlock=*/2, + kRGB_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kRGB_565_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kRGB16, + /*bytesPerBlock=*/6, + kRGB_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kR16G16B16A16_unorm_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kRGB16F, + /*bytesPerBlock=*/6, + kRGB_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/false, + /*isFloatingPoint=*/true, + {{kRGB_F16F16F16x_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kRGB32F, + /*bytesPerBlock=*/12, + kRGB_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/false, + /*isFloatingPoint=*/true, + {{kRGBA_F32_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kRGB8_sRGB, + /*bytesPerBlock=*/3, + kRGB_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kSRGBA_8888_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kBGR10_XR, + /*bytesPerBlock=*/4, + kRGB_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/false, + /*isFloatingPoint=*/false, + {{kBGR_101010x_XR_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kRGBA8, + /*bytesPerBlock=*/4, + kRGBA_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kRGBA_8888_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}, + {kBGRA_8888_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}, + {kRGB_888x_SkColorType, Swizzle::RGB1(), std::nullopt}}), + + MakeColor(TextureFormat::kRGBA16, + /*bytesPerBlock=*/8, + kRGBA_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kR16G16B16A16_unorm_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kRGBA16F, + /*bytesPerBlock=*/8, + kRGBA_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/false, + /*isFloatingPoint=*/true, + {{kRGBA_F16_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}, + {kRGBA_F16Norm_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}, + {kRGB_F16F16F16x_SkColorType, Swizzle::RGB1(), std::nullopt}}), + + MakeColor(TextureFormat::kRGBA32F, + /*bytesPerBlock=*/16, + kRGBA_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/false, + /*isFloatingPoint=*/true, + {{kRGBA_F32_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kRGB10_A2, + /*bytesPerBlock=*/4, + kRGBA_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kRGBA_1010102_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}, + {kRGB_101010x_SkColorType, Swizzle::RGB1(), std::nullopt}, + {kBGRA_1010102_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}, + {kBGR_101010x_SkColorType, Swizzle::RGB1(), std::nullopt}}), + + MakeColor(TextureFormat::kRGBA10x6, + /*bytesPerBlock=*/8, + kRGBA_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kRGBA_10x6_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kRGBA8_sRGB, + /*bytesPerBlock=*/4, + kRGBA_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kSRGBA_8888_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kBGRA8, + /*bytesPerBlock=*/4, + kRGBA_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kBGRA_8888_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}, + {kRGBA_8888_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}, + {kRGB_888x_SkColorType, Swizzle::RGB1(), std::nullopt}}), + + MakeColor(TextureFormat::kBGR10_A2, + /*bytesPerBlock=*/4, + kRGBA_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kBGRA_1010102_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}, + {kBGR_101010x_SkColorType, Swizzle::RGB1(), std::nullopt}, + {kRGBA_1010102_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}, + {kRGB_101010x_SkColorType, Swizzle::RGB1(), std::nullopt}}), + + MakeColor(TextureFormat::kBGRA8_sRGB, + /*bytesPerBlock=*/4, + kRGBA_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kSRGBA_8888_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kABGR4, + /*bytesPerBlock=*/2, + kRGBA_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kARGB_4444_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + MakeColor(TextureFormat::kARGB4, + /*bytesPerBlock=*/2, + kRGBA_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + // TODO(michaelludwig): kARGB_4444 color type is actually BGRA order. Historically, + // we configured kARGB4 format to swizzle the channels on read and write in the + // shader so that the CPU data could be uploaded directly. When we can perform a RB + // channel swap as part of upload/readback, then this can change to RGBA swizzles. + {{kARGB_4444_SkColorType, Swizzle::BGRA(), Swizzle::BGRA()}}), + + MakeColor(TextureFormat::kBGRA10x6_XR, + /*bytesPerBlock=*/8, + kRGBA_SkColorChannelFlags, + /*multiplanar=*/false, + /*autoClamps=*/false, + /*isFloatingPoint=*/false, + {{kBGRA_10101010_XR_SkColorType, Swizzle::RGBA(), Swizzle::RGBA()}}), + + // For compressed formats, the bytes per block represents actual compressed block size, not + // just the size of a pixel. + MakeCompressed(TextureFormat::kRGB8_ETC2, + SkTextureCompressionType::kETC2_RGB8_UNORM, + /*bytesPerBlock=*/8, + kRGB_SkColorChannelFlags, + {{kRGB_888x_SkColorType, Swizzle::RGBA(), std::nullopt}}), + + MakeCompressed(TextureFormat::kRGB8_ETC2_sRGB, + SkTextureCompressionType::kETC2_RGB8_UNORM, + /*bytesPerBlock=*/8, + kRGB_SkColorChannelFlags, + {{kSRGBA_8888_SkColorType, Swizzle::RGBA(), std::nullopt}}), + + MakeCompressed(TextureFormat::kRGB8_BC1, + SkTextureCompressionType::kBC1_RGB8_UNORM, + /*bytesPerBlock=*/8, + kRGB_SkColorChannelFlags, + {{kRGB_888x_SkColorType, Swizzle::RGBA(), std::nullopt}}), + + MakeCompressed(TextureFormat::kRGBA8_BC1, + SkTextureCompressionType::kBC1_RGBA8_UNORM, + /*bytesPerBlock=*/8, + kRGBA_SkColorChannelFlags, + {{kRGBA_8888_SkColorType, Swizzle::RGBA(), std::nullopt}}), + + MakeCompressed(TextureFormat::kRGBA8_BC1_sRGB, + SkTextureCompressionType::kBC1_RGBA8_UNORM, + /*bytesPerBlock=*/8, + kRGBA_SkColorChannelFlags, + {{kSRGBA_8888_SkColorType, Swizzle::RGBA(), std::nullopt}}), + + // For these multiplanar formats, we set the bytes per block assuming the UV planes are the + // same size as the Y plane, which is an overestimate of the total texture memory. + MakeColor(TextureFormat::kYUV8_P2_420, + /*bytesPerBlock=*/3, + kRGB_SkColorChannelFlags, + /*multiplanar=*/true, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kRGB_888x_SkColorType, Swizzle::RGBA(), std::nullopt}}), + + MakeColor(TextureFormat::kYUV8_P3_420, + /*bytesPerBlock=*/3, + kRGB_SkColorChannelFlags, + /*multiplanar=*/true, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kRGB_888x_SkColorType, Swizzle::RGBA(), std::nullopt}}), + + MakeColor(TextureFormat::kYUV10x6_P2_420, + /*bytesPerBlock=*/6, + kRGB_SkColorChannelFlags, + /*multiplanar=*/true, + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kRGBA_10x6_SkColorType, Swizzle::RGBA(), std::nullopt}}), + + MakeColor(TextureFormat::kExternal, + /*bytesPerBlock=*/4, // this is meaningless but is what we report + kRGBA_SkColorChannelFlags, + /*multiplanar=*/false, // probably actually true, but hidden from us + /*autoClamps=*/true, + /*isFloatingPoint=*/false, + {{kRGBA_8888_SkColorType, Swizzle::RGBA(), std::nullopt}, + {kRGB_888x_SkColorType, Swizzle::RGB1(), std::nullopt}}), + + MakeDepthStencil(TextureFormat::kS8, + /*bytesPerBlock=*/1, + /*hasDepth=*/false, + /*hasStencil=*/true, + /*autoClamps=*/false, + /*isFloatingPoint=*/false), + + MakeDepthStencil(TextureFormat::kD16, + /*bytesPerBlock=*/2, + /*hasDepth=*/true, + /*hasStencil=*/false, + /*autoClamps=*/true, + /*isFloatingPoint=*/false), + + MakeDepthStencil(TextureFormat::kD32F, + /*bytesPerBlock=*/4, + /*hasDepth=*/true, + /*hasStencil=*/false, + /*autoClamps=*/false, + /*isFloatingPoint=*/true), + + MakeDepthStencil(TextureFormat::kD24_S8, + /*bytesPerBlock=*/4, + /*hasDepth=*/true, + /*hasStencil=*/true, + /*autoClamps=*/true, // referring to main depth channel + /*isFloatingPoint=*/false), + + MakeDepthStencil(TextureFormat::kD32F_S8, + /*bytesPerBlock=*/5, + /*hasDepth=*/true, + /*hasStencil=*/true, + /*autoClamps=*/false, + /*isFloatingPoint=*/true), +}; + +// TODO(michaelludwig): For now format-colortype validation relies on Caps APIs that require a full +// TextureInfo, but they will be moved to fixed rules by TextureFormat. At that point, the +// backend-specific test files can also go away. +using TextureInfoFactoryFn = TextureInfo(*)(TextureFormat); + +inline +void RunTextureFormatTest(skiatest::Reporter* r, + const Caps* caps, + TextureFormat format, + TextureInfoFactoryFn texInfoFactory) { + bool foundExpectation = false; + for (auto&& e : kExpectations) { + if (e.fFormat != format) { + continue; + } + + // Should only find it once + REPORTER_ASSERT(r, !foundExpectation, "Format expectation listed multiple times"); + foundExpectation = true; + + skiatest::ReporterContext scope(r, SkStringPrintf("Format %s", TextureFormatName(format))); + + // Found the expectation for the requested format. Check fixed properties first. + REPORTER_ASSERT(r, e.fCompressionType == TextureFormatCompressionType(format)); + REPORTER_ASSERT(r, e.fBytesPerBlock == TextureFormatBytesPerBlock(format)); + REPORTER_ASSERT(r, e.fChannelMask == TextureFormatChannelMask(format)); + REPORTER_ASSERT(r, (e.fHasDepth || e.fHasStencil) == TextureFormatIsDepthOrStencil(format)); + REPORTER_ASSERT(r, e.fHasDepth == TextureFormatHasDepth(format)); + REPORTER_ASSERT(r, e.fHasStencil == TextureFormatHasStencil(format)); + REPORTER_ASSERT(r, e.fMultiplanar == TextureFormatIsMultiplanar(format)); + REPORTER_ASSERT(r, e.fAutoClamps == TextureFormatAutoClamps(format)); + REPORTER_ASSERT(r, e.fIsFloatingPoint == TextureFormatIsFloatingPoint(format)); + + // Verify compatible color types + TextureInfo texInfo = texInfoFactory(format); + + SkColorType baseColorType = caps->getDefaultColorType(texInfo); + if (baseColorType == kUnknown_SkColorType) { + // TODO(michaelludwig): Caps excludes color type infos for formats that aren't + // supported, so we could see kUnknown on a given device. When compatibility is + // separated from format support, we can instead assert this only happens when there + // really are no compatible color types. + // REPORTER_ASSERT(r, e.fCompatibleColorTypes.empty()); + continue; + } else { + // Should be the first listed compatible color type + REPORTER_ASSERT(r, !e.fCompatibleColorTypes.empty()); + REPORTER_ASSERT(r, e.fCompatibleColorTypes[0].fColorType == baseColorType); + } + + for (int c = 0; c <= kLastEnum_SkColorType; ++c) { + SkColorType ct = static_cast<SkColorType>(c); + + skiatest::ReporterContext ctScope{r, SkStringPrintf("color type %d\n", c)}; + + bool foundColorExpectation = false; + for (auto&& ec : e.fCompatibleColorTypes) { + if (ec.fColorType == ct) { + // Expected to be compatible (and should only find it once) + REPORTER_ASSERT(r, !foundColorExpectation, + "Color type listed multiple times: %d", + (int) ec.fColorType); + foundColorExpectation = true; + + // Check swizzles here, the rest of the color type checks happen outside the + // loop based on `foundColorExpectation`. + REPORTER_ASSERT(r, ec.fReadSwizzle == caps->getReadSwizzle(ct, texInfo), + "actual %s vs. expected %s", + caps->getReadSwizzle(ct, texInfo).asString().c_str(), + ec.fReadSwizzle.asString().c_str()); + + if (ec.fWriteSwizzle.has_value()) { + REPORTER_ASSERT(r, ec.fWriteSwizzle == caps->getWriteSwizzle(ct, texInfo), + "actual %s vs. expected %s", + caps->getWriteSwizzle(ct, texInfo).asString().c_str(), + ec.fWriteSwizzle->asString().c_str()); + } else { + // getWriteSwizzle asserts if there is no color info rule so test other ways + // to verify that it's not renderable with the given color type. This is a + // proxy for "the format can represent CT, and there are some formats that + // can render CT, but this format does not render w/ CT". + TextureInfo renderableInfo = caps->getDefaultSampledTextureInfo( + ct, Mipmapped::kNo, Protected::kNo, Renderable::kYes); + REPORTER_ASSERT(r, format != TextureInfoPriv::ViewFormat(renderableInfo)); + } + } + } + + // If we found an expectation, it should be detected as compatible (and false otherwise) + const bool actualCompatible = caps->areColorTypeAndTextureInfoCompatible(ct, texInfo); + REPORTER_ASSERT(r, foundColorExpectation == actualCompatible, + "actual (%d) vs expected (%d)", actualCompatible, foundExpectation); + } + } + + // All formats should have expectations + REPORTER_ASSERT(r, foundExpectation, "Missing expectation for %s", TextureFormatName(format)); +} + +} // namespace skgpu::graphite
diff --git a/tests/graphite/TextureFormatTest_dawn.cpp b/tests/graphite/TextureFormatTest_dawn.cpp new file mode 100644 index 0000000..412f6af --- /dev/null +++ b/tests/graphite/TextureFormatTest_dawn.cpp
@@ -0,0 +1,37 @@ +/* + * Copyright 2026 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "tests/graphite/TextureFormatTest.h" + +#include "include/gpu/graphite/Context.h" +#include "include/gpu/graphite/dawn/DawnGraphiteTypes.h" +#include "src/gpu/graphite/ContextPriv.h" +#include "src/gpu/graphite/dawn/DawnGraphiteUtils.h" + +#include "webgpu/webgpu_cpp.h" + +namespace skgpu::graphite { + +WGPU_IMPORT_BITMASK_OPERATORS + +static TextureInfo create_dawn_texture_info(TextureFormat format) { + DawnTextureInfo info; + info.fFormat = TextureFormatToDawnFormat(format); + info.fUsage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment; + + return TextureInfos::MakeDawn(info); +} + +DEF_GRAPHITE_TEST_FOR_DAWN_CONTEXT(TextureFormatTest_Dawn, r, ctx, testCtx) { + for (int i = 0; i < kTextureFormatCount; ++i) { + RunTextureFormatTest(r, ctx->priv().caps(), + static_cast<TextureFormat>(i), + create_dawn_texture_info); + } +} + +} // namespace skgpu::graphite
diff --git a/tests/graphite/TextureFormatTest_mtl.mm b/tests/graphite/TextureFormatTest_mtl.mm new file mode 100644 index 0000000..8d5f7db --- /dev/null +++ b/tests/graphite/TextureFormatTest_mtl.mm
@@ -0,0 +1,33 @@ +/* + * Copyright 2026 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "tests/graphite/TextureFormatTest.h" + +#include "include/gpu/graphite/Context.h" +#include "include/gpu/graphite/mtl/MtlGraphiteTypes.h" +#include "src/gpu/graphite/ContextPriv.h" +#include "src/gpu/graphite/mtl/MtlGraphiteUtils.h" + +namespace skgpu::graphite { + +static TextureInfo create_mtl_texture_info(TextureFormat format) { + MtlTextureInfo info; + info.fFormat = TextureFormatToMTLPixelFormat(format); + info.fUsage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget; + + return TextureInfos::MakeMetal(info); +} + +DEF_GRAPHITE_TEST_FOR_METAL_CONTEXT(TextureFormatTest_Metal, r, ctx, testCtx) { + for (int i = 0; i < kTextureFormatCount; ++i) { + RunTextureFormatTest(r, ctx->priv().caps(), + static_cast<TextureFormat>(i), + create_mtl_texture_info); + } +} + +} // namespace skgpu::graphite
diff --git a/tests/graphite/TextureFormatTest_vk.cpp b/tests/graphite/TextureFormatTest_vk.cpp new file mode 100644 index 0000000..207dc2c --- /dev/null +++ b/tests/graphite/TextureFormatTest_vk.cpp
@@ -0,0 +1,39 @@ +/* + * Copyright 2026 Google LLC + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "tests/graphite/TextureFormatTest.h" + +#include "include/gpu/graphite/Context.h" +#include "include/gpu/graphite/vk/VulkanGraphiteTypes.h" +#include "src/gpu/graphite/ContextPriv.h" +#include "src/gpu/graphite/vk/VulkanGraphiteUtils.h" + +namespace skgpu::graphite { + +static TextureInfo create_vulkan_texture_info(TextureFormat format) { + VulkanTextureInfo info; + info.fFormat = TextureFormatToVkFormat(format); + info.fImageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT; + if (TextureFormatIsDepthOrStencil(format)) { + info.fImageUsageFlags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + } else { + info.fImageUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | + VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; + } + + return TextureInfos::MakeVulkan(info); +} + +DEF_GRAPHITE_TEST_FOR_VULKAN_CONTEXT(TextureFormatTest_Vulkan, r, ctx, CtsEnforcement::kNextRelease) { + for (int i = 0; i < kTextureFormatCount; ++i) { + RunTextureFormatTest(r, ctx->priv().caps(), + static_cast<TextureFormat>(i), + create_vulkan_texture_info); + } +} + +} // namespace skgpu::graphite