Adds ASTC texture compression formats and Vulkan support for them.

The end to end texture tests with the binary information for the textures are generated using the open source astc-encoder tool.

Also: Refactors end2end compressed texture tests to allow for non-4x4 texel compression formats (ASTC formats are not all 4x4).

Bug: dawn:955
Change-Id: I5311a5aa7bd017de72300bf7c87fba6c869b1db5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/63121
Commit-Queue: Loko Kung <lokokung@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Loko Kung 2021-09-07 18:39:04 +00:00 committed by Dawn LUCI CQ
parent e1f5934c1c
commit 37a8649f92
12 changed files with 934 additions and 491 deletions

View File

@ -1998,7 +1998,36 @@
{"value": 62, "name": "EAC R11 unorm"},
{"value": 63, "name": "EAC R11 snorm"},
{"value": 64, "name": "EAC RG11 unorm"},
{"value": 65, "name": "EAC RG11 snorm"}
{"value": 65, "name": "EAC RG11 snorm"},
{"value": 66, "name": "ASTC 4x4 unorm"},
{"value": 67, "name": "ASTC 4x4 unorm srgb"},
{"value": 68, "name": "ASTC 5x4 unorm"},
{"value": 69, "name": "ASTC 5x4 unorm srgb"},
{"value": 70, "name": "ASTC 5x5 unorm"},
{"value": 71, "name": "ASTC 5x5 unorm srgb"},
{"value": 72, "name": "ASTC 6x5 unorm"},
{"value": 73, "name": "ASTC 6x5 unorm srgb"},
{"value": 74, "name": "ASTC 6x6 unorm"},
{"value": 75, "name": "ASTC 6x6 unorm srgb"},
{"value": 76, "name": "ASTC 8x5 unorm"},
{"value": 77, "name": "ASTC 8x5 unorm srgb"},
{"value": 78, "name": "ASTC 8x6 unorm"},
{"value": 79, "name": "ASTC 8x6 unorm srgb"},
{"value": 80, "name": "ASTC 8x8 unorm"},
{"value": 81, "name": "ASTC 8x8 unorm srgb"},
{"value": 82, "name": "ASTC 10x5 unorm"},
{"value": 83, "name": "ASTC 10x5 unorm srgb"},
{"value": 84, "name": "ASTC 10x6 unorm"},
{"value": 85, "name": "ASTC 10x6 unorm srgb"},
{"value": 86, "name": "ASTC 10x8 unorm"},
{"value": 87, "name": "ASTC 10x8 unorm srgb"},
{"value": 88, "name": "ASTC 10x10 unorm"},
{"value": 89, "name": "ASTC 10x10 unorm srgb"},
{"value": 90, "name": "ASTC 12x10 unorm"},
{"value": 91, "name": "ASTC 12x10 unorm srgb"},
{"value": 92, "name": "ASTC 12x12 unorm"},
{"value": 93, "name": "ASTC 12x12 unorm srgb"}
]
},
"texture usage": {

View File

@ -365,6 +365,37 @@ namespace dawn_native {
AddCompressedFormat(wgpu::TextureFormat::EACRG11Unorm, 16, 4, 4, isETC2FormatSupported, 2);
AddCompressedFormat(wgpu::TextureFormat::EACRG11Snorm, 16, 4, 4, isETC2FormatSupported, 2);
// ASTC compressed formats
bool isASTCFormatSupported = device->IsExtensionEnabled(Extension::TextureCompressionASTC);
AddCompressedFormat(wgpu::TextureFormat::ASTC4x4Unorm, 16, 4, 4, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC4x4UnormSrgb, 16, 4, 4, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC5x4Unorm, 16, 5, 4, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC5x4UnormSrgb, 16, 5, 4, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC5x5Unorm, 16, 5, 5, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC5x5UnormSrgb, 16, 5, 5, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC6x5Unorm, 16, 6, 5, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC6x5UnormSrgb, 16, 6, 5, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC6x6Unorm, 16, 6, 6, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC6x6UnormSrgb, 16, 6, 6, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC8x5Unorm, 16, 8, 5, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC8x5UnormSrgb, 16, 8, 5, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC8x6Unorm, 16, 8, 6, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC8x6UnormSrgb, 16, 8, 6, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC8x8Unorm, 16, 8, 8, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC8x8UnormSrgb, 16, 8, 8, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC10x5Unorm, 16, 10, 5, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC10x5UnormSrgb, 16, 10, 5, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC10x6Unorm, 16, 10, 6, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC10x6UnormSrgb, 16, 10, 6, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC10x8Unorm, 16, 10, 8, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC10x8UnormSrgb, 16, 10, 8, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC10x10Unorm, 16, 10, 10, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC10x10UnormSrgb, 16, 10, 10, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC12x10Unorm, 16, 12, 10, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC12x10UnormSrgb, 16, 12, 10, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC12x12Unorm, 16, 12, 12, isASTCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ASTC12x12UnormSrgb, 16, 12, 12, isASTCFormatSupported, 4);
// multi-planar formats
const bool isMultiPlanarFormatSupported = device->IsExtensionEnabled(Extension::MultiPlanarFormats);
AddMultiAspectFormat(wgpu::TextureFormat::R8BG8Biplanar420Unorm, Aspect::Plane0 | Aspect::Plane1,

View File

@ -77,7 +77,7 @@ namespace dawn_native {
// The number of formats Dawn knows about. Asserts in BuildFormatTable ensure that this is the
// exact number of known format.
static constexpr size_t kKnownFormatCount = 65;
static constexpr size_t kKnownFormatCount = 93;
struct Format;
using FormatTable = std::array<Format, kKnownFormatCount>;

View File

@ -214,6 +214,35 @@ namespace dawn_native { namespace d3d12 {
case wgpu::TextureFormat::EACRG11Unorm:
case wgpu::TextureFormat::EACRG11Snorm:
case wgpu::TextureFormat::ASTC4x4Unorm:
case wgpu::TextureFormat::ASTC4x4UnormSrgb:
case wgpu::TextureFormat::ASTC5x4Unorm:
case wgpu::TextureFormat::ASTC5x4UnormSrgb:
case wgpu::TextureFormat::ASTC5x5Unorm:
case wgpu::TextureFormat::ASTC5x5UnormSrgb:
case wgpu::TextureFormat::ASTC6x5Unorm:
case wgpu::TextureFormat::ASTC6x5UnormSrgb:
case wgpu::TextureFormat::ASTC6x6Unorm:
case wgpu::TextureFormat::ASTC6x6UnormSrgb:
case wgpu::TextureFormat::ASTC8x5Unorm:
case wgpu::TextureFormat::ASTC8x5UnormSrgb:
case wgpu::TextureFormat::ASTC8x6Unorm:
case wgpu::TextureFormat::ASTC8x6UnormSrgb:
case wgpu::TextureFormat::ASTC8x8Unorm:
case wgpu::TextureFormat::ASTC8x8UnormSrgb:
case wgpu::TextureFormat::ASTC10x5Unorm:
case wgpu::TextureFormat::ASTC10x5UnormSrgb:
case wgpu::TextureFormat::ASTC10x6Unorm:
case wgpu::TextureFormat::ASTC10x6UnormSrgb:
case wgpu::TextureFormat::ASTC10x8Unorm:
case wgpu::TextureFormat::ASTC10x8UnormSrgb:
case wgpu::TextureFormat::ASTC10x10Unorm:
case wgpu::TextureFormat::ASTC10x10UnormSrgb:
case wgpu::TextureFormat::ASTC12x10Unorm:
case wgpu::TextureFormat::ASTC12x10UnormSrgb:
case wgpu::TextureFormat::ASTC12x12Unorm:
case wgpu::TextureFormat::ASTC12x12UnormSrgb:
case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
case wgpu::TextureFormat::Stencil8:
case wgpu::TextureFormat::Undefined:
@ -352,6 +381,35 @@ namespace dawn_native { namespace d3d12 {
case wgpu::TextureFormat::EACRG11Unorm:
case wgpu::TextureFormat::EACRG11Snorm:
case wgpu::TextureFormat::ASTC4x4Unorm:
case wgpu::TextureFormat::ASTC4x4UnormSrgb:
case wgpu::TextureFormat::ASTC5x4Unorm:
case wgpu::TextureFormat::ASTC5x4UnormSrgb:
case wgpu::TextureFormat::ASTC5x5Unorm:
case wgpu::TextureFormat::ASTC5x5UnormSrgb:
case wgpu::TextureFormat::ASTC6x5Unorm:
case wgpu::TextureFormat::ASTC6x5UnormSrgb:
case wgpu::TextureFormat::ASTC6x6Unorm:
case wgpu::TextureFormat::ASTC6x6UnormSrgb:
case wgpu::TextureFormat::ASTC8x5Unorm:
case wgpu::TextureFormat::ASTC8x5UnormSrgb:
case wgpu::TextureFormat::ASTC8x6Unorm:
case wgpu::TextureFormat::ASTC8x6UnormSrgb:
case wgpu::TextureFormat::ASTC8x8Unorm:
case wgpu::TextureFormat::ASTC8x8UnormSrgb:
case wgpu::TextureFormat::ASTC10x5Unorm:
case wgpu::TextureFormat::ASTC10x5UnormSrgb:
case wgpu::TextureFormat::ASTC10x6Unorm:
case wgpu::TextureFormat::ASTC10x6UnormSrgb:
case wgpu::TextureFormat::ASTC10x8Unorm:
case wgpu::TextureFormat::ASTC10x8UnormSrgb:
case wgpu::TextureFormat::ASTC10x10Unorm:
case wgpu::TextureFormat::ASTC10x10UnormSrgb:
case wgpu::TextureFormat::ASTC12x10Unorm:
case wgpu::TextureFormat::ASTC12x10UnormSrgb:
case wgpu::TextureFormat::ASTC12x12Unorm:
case wgpu::TextureFormat::ASTC12x12UnormSrgb:
case wgpu::TextureFormat::Stencil8:
case wgpu::TextureFormat::Undefined:
UNREACHABLE();

View File

@ -282,6 +282,35 @@ namespace dawn_native { namespace metal {
case wgpu::TextureFormat::EACRG11Unorm:
case wgpu::TextureFormat::EACRG11Snorm:
case wgpu::TextureFormat::ASTC4x4Unorm:
case wgpu::TextureFormat::ASTC4x4UnormSrgb:
case wgpu::TextureFormat::ASTC5x4Unorm:
case wgpu::TextureFormat::ASTC5x4UnormSrgb:
case wgpu::TextureFormat::ASTC5x5Unorm:
case wgpu::TextureFormat::ASTC5x5UnormSrgb:
case wgpu::TextureFormat::ASTC6x5Unorm:
case wgpu::TextureFormat::ASTC6x5UnormSrgb:
case wgpu::TextureFormat::ASTC6x6Unorm:
case wgpu::TextureFormat::ASTC6x6UnormSrgb:
case wgpu::TextureFormat::ASTC8x5Unorm:
case wgpu::TextureFormat::ASTC8x5UnormSrgb:
case wgpu::TextureFormat::ASTC8x6Unorm:
case wgpu::TextureFormat::ASTC8x6UnormSrgb:
case wgpu::TextureFormat::ASTC8x8Unorm:
case wgpu::TextureFormat::ASTC8x8UnormSrgb:
case wgpu::TextureFormat::ASTC10x5Unorm:
case wgpu::TextureFormat::ASTC10x5UnormSrgb:
case wgpu::TextureFormat::ASTC10x6Unorm:
case wgpu::TextureFormat::ASTC10x6UnormSrgb:
case wgpu::TextureFormat::ASTC10x8Unorm:
case wgpu::TextureFormat::ASTC10x8UnormSrgb:
case wgpu::TextureFormat::ASTC10x10Unorm:
case wgpu::TextureFormat::ASTC10x10UnormSrgb:
case wgpu::TextureFormat::ASTC12x10Unorm:
case wgpu::TextureFormat::ASTC12x10UnormSrgb:
case wgpu::TextureFormat::ASTC12x12Unorm:
case wgpu::TextureFormat::ASTC12x12UnormSrgb:
case wgpu::TextureFormat::Stencil8:
case wgpu::TextureFormat::Undefined:
UNREACHABLE();

View File

@ -359,6 +359,63 @@ namespace dawn_native { namespace vulkan {
case wgpu::TextureFormat::EACRG11Snorm:
return VK_FORMAT_EAC_R11G11_SNORM_BLOCK;
case wgpu::TextureFormat::ASTC4x4Unorm:
return VK_FORMAT_ASTC_4x4_UNORM_BLOCK;
case wgpu::TextureFormat::ASTC4x4UnormSrgb:
return VK_FORMAT_ASTC_4x4_SRGB_BLOCK;
case wgpu::TextureFormat::ASTC5x4Unorm:
return VK_FORMAT_ASTC_5x4_UNORM_BLOCK;
case wgpu::TextureFormat::ASTC5x4UnormSrgb:
return VK_FORMAT_ASTC_5x4_SRGB_BLOCK;
case wgpu::TextureFormat::ASTC5x5Unorm:
return VK_FORMAT_ASTC_5x5_UNORM_BLOCK;
case wgpu::TextureFormat::ASTC5x5UnormSrgb:
return VK_FORMAT_ASTC_5x5_SRGB_BLOCK;
case wgpu::TextureFormat::ASTC6x5Unorm:
return VK_FORMAT_ASTC_6x5_UNORM_BLOCK;
case wgpu::TextureFormat::ASTC6x5UnormSrgb:
return VK_FORMAT_ASTC_6x5_SRGB_BLOCK;
case wgpu::TextureFormat::ASTC6x6Unorm:
return VK_FORMAT_ASTC_6x6_UNORM_BLOCK;
case wgpu::TextureFormat::ASTC6x6UnormSrgb:
return VK_FORMAT_ASTC_6x6_SRGB_BLOCK;
case wgpu::TextureFormat::ASTC8x5Unorm:
return VK_FORMAT_ASTC_8x5_UNORM_BLOCK;
case wgpu::TextureFormat::ASTC8x5UnormSrgb:
return VK_FORMAT_ASTC_8x5_SRGB_BLOCK;
case wgpu::TextureFormat::ASTC8x6Unorm:
return VK_FORMAT_ASTC_8x6_UNORM_BLOCK;
case wgpu::TextureFormat::ASTC8x6UnormSrgb:
return VK_FORMAT_ASTC_8x6_SRGB_BLOCK;
case wgpu::TextureFormat::ASTC8x8Unorm:
return VK_FORMAT_ASTC_8x8_UNORM_BLOCK;
case wgpu::TextureFormat::ASTC8x8UnormSrgb:
return VK_FORMAT_ASTC_8x8_SRGB_BLOCK;
case wgpu::TextureFormat::ASTC10x5Unorm:
return VK_FORMAT_ASTC_10x5_UNORM_BLOCK;
case wgpu::TextureFormat::ASTC10x5UnormSrgb:
return VK_FORMAT_ASTC_10x5_SRGB_BLOCK;
case wgpu::TextureFormat::ASTC10x6Unorm:
return VK_FORMAT_ASTC_10x6_UNORM_BLOCK;
case wgpu::TextureFormat::ASTC10x6UnormSrgb:
return VK_FORMAT_ASTC_10x6_SRGB_BLOCK;
case wgpu::TextureFormat::ASTC10x8Unorm:
return VK_FORMAT_ASTC_10x8_UNORM_BLOCK;
case wgpu::TextureFormat::ASTC10x8UnormSrgb:
return VK_FORMAT_ASTC_10x8_SRGB_BLOCK;
case wgpu::TextureFormat::ASTC10x10Unorm:
return VK_FORMAT_ASTC_10x10_UNORM_BLOCK;
case wgpu::TextureFormat::ASTC10x10UnormSrgb:
return VK_FORMAT_ASTC_10x10_SRGB_BLOCK;
case wgpu::TextureFormat::ASTC12x10Unorm:
return VK_FORMAT_ASTC_12x10_UNORM_BLOCK;
case wgpu::TextureFormat::ASTC12x10UnormSrgb:
return VK_FORMAT_ASTC_12x10_SRGB_BLOCK;
case wgpu::TextureFormat::ASTC12x12Unorm:
return VK_FORMAT_ASTC_12x12_UNORM_BLOCK;
case wgpu::TextureFormat::ASTC12x12UnormSrgb:
return VK_FORMAT_ASTC_12x12_SRGB_BLOCK;
case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
case wgpu::TextureFormat::Stencil8:
case wgpu::TextureFormat::Undefined:

View File

@ -391,6 +391,53 @@ class CompressedTextureFormatTest : public DawnTestWithParams<CompressedTextureF
return {0x2, 0x90, 0xff, 0xff, 0xff, 0x6d, 0xb6, 0xdb,
0x2, 0x90, 0x6d, 0xb6, 0xdb, 0xff, 0xff, 0xff};
// The expected data is a texel block of the corresponding size where the left width / 2
// pixels are dark red with an alpha of 0x80 and the remaining (width - width / 2)
// pixels are dark green. We specify the same compressed data in both sRGB and non-sRGB
// tests, but the rendering result should be different because for sRGB formats, the
// red, green, and blue components are converted from an sRGB color space to a linear
// color space as part of filtering, and any alpha component is left unchanged.
case wgpu::TextureFormat::ASTC4x4Unorm:
case wgpu::TextureFormat::ASTC4x4UnormSrgb:
return {0x13, 0x80, 0xe9, 0x1, 0x0, 0xe8, 0x1, 0x0,
0x0, 0xff, 0x1, 0x0, 0x0, 0x3f, 0xf0, 0x3};
case wgpu::TextureFormat::ASTC5x4Unorm:
case wgpu::TextureFormat::ASTC5x4UnormSrgb:
case wgpu::TextureFormat::ASTC5x5Unorm:
case wgpu::TextureFormat::ASTC5x5UnormSrgb:
return {0x83, 0x80, 0xe9, 0x1, 0x0, 0xe8, 0x1, 0x0,
0x0, 0xff, 0x1, 0x0, 0x80, 0x14, 0x90, 0x2};
case wgpu::TextureFormat::ASTC6x5Unorm:
case wgpu::TextureFormat::ASTC6x5UnormSrgb:
case wgpu::TextureFormat::ASTC6x6Unorm:
case wgpu::TextureFormat::ASTC6x6UnormSrgb:
return {0x2, 0x81, 0xe9, 0x1, 0x0, 0xe8, 0x1, 0x0,
0x0, 0xff, 0x1, 0x0, 0x0, 0x3f, 0xf0, 0x3};
case wgpu::TextureFormat::ASTC8x5Unorm:
case wgpu::TextureFormat::ASTC8x5UnormSrgb:
case wgpu::TextureFormat::ASTC8x6Unorm:
case wgpu::TextureFormat::ASTC8x6UnormSrgb:
case wgpu::TextureFormat::ASTC8x8Unorm:
case wgpu::TextureFormat::ASTC8x8UnormSrgb:
return {0x6, 0x80, 0xe9, 0x1, 0x0, 0xe8, 0x1, 0x0,
0x0, 0xff, 0x1, 0x0, 0xff, 0x0, 0xff, 0x0};
case wgpu::TextureFormat::ASTC10x5Unorm:
case wgpu::TextureFormat::ASTC10x5UnormSrgb:
case wgpu::TextureFormat::ASTC10x6Unorm:
case wgpu::TextureFormat::ASTC10x6UnormSrgb:
case wgpu::TextureFormat::ASTC10x8Unorm:
case wgpu::TextureFormat::ASTC10x8UnormSrgb:
case wgpu::TextureFormat::ASTC10x10Unorm:
case wgpu::TextureFormat::ASTC10x10UnormSrgb:
return {0x6, 0x81, 0xe9, 0x1, 0x0, 0xe8, 0x1, 0x0,
0x0, 0xff, 0x1, 0xff, 0x3, 0xf0, 0x3f, 0x0};
case wgpu::TextureFormat::ASTC12x10Unorm:
case wgpu::TextureFormat::ASTC12x10UnormSrgb:
case wgpu::TextureFormat::ASTC12x12Unorm:
case wgpu::TextureFormat::ASTC12x12UnormSrgb:
return {0x4, 0x80, 0xe9, 0x1, 0x0, 0xe8, 0x1, 0x0,
0x0, 0xff, 0x1, 0x0, 0x0, 0x3f, 0xf0, 0x3};
default:
UNREACHABLE();
return {};
@ -401,6 +448,9 @@ class CompressedTextureFormatTest : public DawnTestWithParams<CompressedTextureF
// in RGBA8 formats. Since some compression methods may be lossy, we may use different colors
// to test different formats.
std::vector<RGBA8> GetExpectedData(const wgpu::Extent3D& testRegion) {
constexpr uint8_t kLeftAlpha = 0x88;
constexpr uint8_t kRightAlpha = 0xFF;
constexpr RGBA8 kBCDarkRed(198, 0, 0, 255);
constexpr RGBA8 kBCDarkGreen(0, 207, 0, 255);
constexpr RGBA8 kBCDarkRedSRGB(144, 0, 0, 255);
@ -411,8 +461,10 @@ class CompressedTextureFormatTest : public DawnTestWithParams<CompressedTextureF
constexpr RGBA8 kETC2DarkRedSRGB(154, 0, 0, 255);
constexpr RGBA8 kETC2DarkGreenSRGB(0, 154, 0, 255);
constexpr uint8_t kLeftAlpha = 0x88;
constexpr uint8_t kRightAlpha = 0xFF;
constexpr RGBA8 kASTCDarkRed(244, 0, 0, 128);
constexpr RGBA8 kASTCDarkGreen(0, 244, 0, 255);
constexpr RGBA8 kASTCDarkRedSRGB(231, 0, 0, 128);
constexpr RGBA8 kASTCDarkGreenSRGB(0, 231, 0, 255);
switch (GetParam().mTextureFormat) {
case wgpu::TextureFormat::BC1RGBAUnorm:
@ -475,6 +527,38 @@ class CompressedTextureFormatTest : public DawnTestWithParams<CompressedTextureF
case wgpu::TextureFormat::EACRG11Snorm:
return FillExpectedData(testRegion, RGBA8::kRed, RGBA8::kGreen);
case wgpu::TextureFormat::ASTC4x4Unorm:
case wgpu::TextureFormat::ASTC5x4Unorm:
case wgpu::TextureFormat::ASTC5x5Unorm:
case wgpu::TextureFormat::ASTC6x5Unorm:
case wgpu::TextureFormat::ASTC6x6Unorm:
case wgpu::TextureFormat::ASTC8x5Unorm:
case wgpu::TextureFormat::ASTC8x6Unorm:
case wgpu::TextureFormat::ASTC8x8Unorm:
case wgpu::TextureFormat::ASTC10x5Unorm:
case wgpu::TextureFormat::ASTC10x6Unorm:
case wgpu::TextureFormat::ASTC10x8Unorm:
case wgpu::TextureFormat::ASTC10x10Unorm:
case wgpu::TextureFormat::ASTC12x10Unorm:
case wgpu::TextureFormat::ASTC12x12Unorm:
return FillExpectedData(testRegion, kASTCDarkRed, kASTCDarkGreen);
case wgpu::TextureFormat::ASTC4x4UnormSrgb:
case wgpu::TextureFormat::ASTC5x4UnormSrgb:
case wgpu::TextureFormat::ASTC5x5UnormSrgb:
case wgpu::TextureFormat::ASTC6x5UnormSrgb:
case wgpu::TextureFormat::ASTC6x6UnormSrgb:
case wgpu::TextureFormat::ASTC8x5UnormSrgb:
case wgpu::TextureFormat::ASTC8x6UnormSrgb:
case wgpu::TextureFormat::ASTC8x8UnormSrgb:
case wgpu::TextureFormat::ASTC10x5UnormSrgb:
case wgpu::TextureFormat::ASTC10x6UnormSrgb:
case wgpu::TextureFormat::ASTC10x8UnormSrgb:
case wgpu::TextureFormat::ASTC10x10UnormSrgb:
case wgpu::TextureFormat::ASTC12x10UnormSrgb:
case wgpu::TextureFormat::ASTC12x12UnormSrgb:
return FillExpectedData(testRegion, kASTCDarkRedSRGB, kASTCDarkGreenSRGB);
default:
UNREACHABLE();
return {};
@ -497,6 +581,55 @@ class CompressedTextureFormatTest : public DawnTestWithParams<CompressedTextureF
return expectedData;
}
// Returns a texture size given the number of texel blocks that should be tiled. For example,
// if a texel block size is 5x4, then GetTextureSizeFromBlocks(2, 2) -> {10, 8, 1}.
wgpu::Extent3D GetTextureSizeWithNumBlocks(uint32_t numBlockWidth,
uint32_t numBlockHeight,
uint32_t depthOrArrayLayers = 1) const {
return {numBlockWidth * BlockWidthInTexels(), numBlockHeight * BlockHeightInTexels(),
depthOrArrayLayers};
}
CopyConfig GetDefaultFullConfig(uint32_t depthOrArrayLayers = 1) const {
ASSERT(IsFormatSupported());
CopyConfig config;
config.textureDescriptor.format = GetParam().mTextureFormat;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = GetTextureSizeWithNumBlocks(
kUnalignedBlockSize, kUnalignedBlockSize, depthOrArrayLayers);
config.textureDescriptor.mipLevelCount = kMipmapLevelCount;
config.viewMipmapLevel = kMipmapLevelCount - 1;
const wgpu::Extent3D virtualSize = GetVirtualSizeAtLevel(config);
ASSERT(virtualSize.width % BlockWidthInTexels() != 0u);
ASSERT(virtualSize.height % BlockHeightInTexels() != 0u);
return config;
}
CopyConfig GetDefaultSmallConfig(uint32_t depthOrArrayLayers = 1) const {
ASSERT(IsFormatSupported());
CopyConfig config;
config.textureDescriptor.format = GetParam().mTextureFormat;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = GetTextureSizeWithNumBlocks(2, 2, depthOrArrayLayers);
return config;
}
CopyConfig GetDefaultSubresourceConfig(uint32_t depthOrArrayLayers = 1) const {
ASSERT(IsFormatSupported());
CopyConfig config;
config.textureDescriptor.format = GetParam().mTextureFormat;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size =
GetPhysicalSizeAtLevel(GetDefaultFullConfig(depthOrArrayLayers));
config.viewMipmapLevel = config.textureDescriptor.mipLevelCount - 1;
return config;
}
// Note: Compressed formats are only valid with 2D (array) textures.
static wgpu::Extent3D GetVirtualSizeAtLevel(const CopyConfig& config) {
return {config.textureDescriptor.size.width >> config.viewMipmapLevel,
@ -504,7 +637,7 @@ class CompressedTextureFormatTest : public DawnTestWithParams<CompressedTextureF
config.textureDescriptor.size.depthOrArrayLayers};
}
wgpu::Extent3D GetPhysicalSizeAtLevel(const CopyConfig& config) {
wgpu::Extent3D GetPhysicalSizeAtLevel(const CopyConfig& config) const {
wgpu::Extent3D sizeAtLevel = GetVirtualSizeAtLevel(config);
sizeAtLevel.width = (sizeAtLevel.width + BlockWidthInTexels() - 1) / BlockWidthInTexels() *
BlockWidthInTexels();
@ -516,6 +649,13 @@ class CompressedTextureFormatTest : public DawnTestWithParams<CompressedTextureF
static constexpr wgpu::TextureUsage kDefaultFormatTextureUsage =
wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopyDst;
// We choose a prime that is greater than the current max texel dimension size as a multiplier
// to compute test texture sizes so that we can be certain that its level 2 mipmap (x4)
// cannot be a multiple of the dimension. This is useful for testing padding at the edges of
// the mipmaps.
static constexpr uint32_t kUnalignedBlockSize = 13;
static constexpr uint32_t kMipmapLevelCount = 3;
bool mIsFormatSupported = false;
};
@ -526,12 +666,9 @@ TEST_P(CompressedTextureFormatTest, Basic) {
DAWN_TEST_UNSUPPORTED_IF(!IsFormatSupported());
CopyConfig config;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = {8, 8, 1};
CopyConfig config = GetDefaultSmallConfig();
config.copyExtent3D = config.textureDescriptor.size;
config.textureDescriptor.format = GetParam().mTextureFormat;
TestCopyRegionIntoFormatTextures(config);
}
@ -542,16 +679,10 @@ TEST_P(CompressedTextureFormatTest, CopyIntoSubRegion) {
DAWN_TEST_UNSUPPORTED_IF(!IsFormatSupported());
CopyConfig config;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = {8, 8, 1};
CopyConfig config = GetDefaultSmallConfig();
config.copyOrigin3D = {BlockWidthInTexels(), BlockHeightInTexels(), 0};
config.copyExtent3D = {BlockWidthInTexels(), BlockHeightInTexels(), 1};
const wgpu::Origin3D kOrigin = {4, 4, 0};
const wgpu::Extent3D kExtent3D = {4, 4, 1};
config.copyOrigin3D = kOrigin;
config.copyExtent3D = kExtent3D;
config.textureDescriptor.format = GetParam().mTextureFormat;
TestCopyRegionIntoFormatTextures(config);
}
@ -565,16 +696,13 @@ TEST_P(CompressedTextureFormatTest, CopyIntoNonZeroArrayLayer) {
// This test uses glTextureView() which is not supported in OpenGL ES.
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
CopyConfig config;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = {8, 8, 1};
config.copyExtent3D = config.textureDescriptor.size;
constexpr uint32_t kArrayLayerCount = 3;
config.textureDescriptor.size.depthOrArrayLayers = kArrayLayerCount;
CopyConfig config = GetDefaultSmallConfig(kArrayLayerCount);
config.copyExtent3D = config.textureDescriptor.size;
config.copyExtent3D.depthOrArrayLayers = 1;
config.copyOrigin3D.z = kArrayLayerCount - 1;
config.textureDescriptor.format = GetParam().mTextureFormat;
TestCopyRegionIntoFormatTextures(config);
}
@ -588,30 +716,11 @@ TEST_P(CompressedTextureFormatTest, CopyBufferIntoNonZeroMipmapLevel) {
// This test uses glTextureView() which is not supported in OpenGL ES.
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
CopyConfig config;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = {60, 60, 1};
CopyConfig config = GetDefaultFullConfig();
// The virtual size of the texture at mipmap level == 2 is not a multiple of the texel
// dimensions so paddings are required in the copies.
config.copyExtent3D = GetPhysicalSizeAtLevel(config);
constexpr uint32_t kMipmapLevelCount = 3;
config.textureDescriptor.mipLevelCount = kMipmapLevelCount;
config.viewMipmapLevel = kMipmapLevelCount - 1;
// The actual size of the texture at mipmap level == 2 is not a multiple of 4, paddings are
// required in the copies.
const wgpu::Extent3D textureSizeLevel0 = config.textureDescriptor.size;
const uint32_t kActualWidthAtLevel = textureSizeLevel0.width >> config.viewMipmapLevel;
const uint32_t kActualHeightAtLevel = textureSizeLevel0.height >> config.viewMipmapLevel;
ASSERT(kActualWidthAtLevel % BlockWidthInTexels() != 0);
ASSERT(kActualHeightAtLevel % BlockHeightInTexels() != 0);
const uint32_t kCopyWidthAtLevel = (kActualWidthAtLevel + BlockWidthInTexels() - 1) /
BlockWidthInTexels() * BlockWidthInTexels();
const uint32_t kCopyHeightAtLevel = (kActualHeightAtLevel + BlockHeightInTexels() - 1) /
BlockHeightInTexels() * BlockHeightInTexels();
config.copyExtent3D = {kCopyWidthAtLevel, kCopyHeightAtLevel, 1};
config.textureDescriptor.format = GetParam().mTextureFormat;
TestCopyRegionIntoFormatTextures(config);
}
@ -629,30 +738,17 @@ TEST_P(CompressedTextureFormatTest, CopyWholeTextureSubResourceIntoNonZeroMipmap
// black instead of opaque red on Win10 FYI Release (NVIDIA GeForce GTX 1660).
DAWN_SUPPRESS_TEST_IF(IsWindows() && IsVulkan() && IsNvidia());
CopyConfig config;
config.textureDescriptor.size = {60, 60, 1};
constexpr uint32_t kMipmapLevelCount = 3;
config.textureDescriptor.mipLevelCount = kMipmapLevelCount;
config.viewMipmapLevel = kMipmapLevelCount - 1;
// The actual size of the texture at mipmap level == 2 is not a multiple of 4, paddings are
// required in the copies.
const wgpu::Extent3D kVirtualSize = GetVirtualSizeAtLevel(config);
const wgpu::Extent3D kPhysicalSize = GetPhysicalSizeAtLevel(config);
ASSERT_NE(0u, kVirtualSize.width % BlockWidthInTexels());
ASSERT_NE(0u, kVirtualSize.height % BlockHeightInTexels());
config.copyExtent3D = kPhysicalSize;
// Create textureSrc as the source texture and initialize it with pre-prepared compressed
// data.
config.textureDescriptor.format = GetParam().mTextureFormat;
CopyConfig config = GetDefaultFullConfig();
// Add the usage bit for both source and destination textures so that we don't need to
// create two copy configs.
config.textureDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst |
wgpu::TextureUsage::TextureBinding;
// The virtual size of the texture at mipmap level == 2 is not a multiple of the texel
// dimensions so paddings are required in the copies.
const wgpu::Extent3D kVirtualSize = GetVirtualSizeAtLevel(config);
config.copyExtent3D = GetPhysicalSizeAtLevel(config);
wgpu::Texture textureSrc = CreateTextureWithCompressedData(config);
// Create textureDst and copy from the content in textureSrc into it.
@ -678,42 +774,24 @@ TEST_P(CompressedTextureFormatTest, CopyIntoSubresourceWithPhysicalSizeNotEqualT
// subresource and does not fit in another one on OpenGL.
DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
CopyConfig srcConfig;
srcConfig.textureDescriptor.size = {60, 60, 1};
srcConfig.viewMipmapLevel = srcConfig.textureDescriptor.mipLevelCount - 1;
CopyConfig srcConfig = GetDefaultSubresourceConfig();
srcConfig.textureDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
const wgpu::Extent3D kSrcVirtualSize = GetVirtualSizeAtLevel(srcConfig);
CopyConfig dstConfig = GetDefaultFullConfig();
CopyConfig dstConfig;
dstConfig.textureDescriptor.size = {60, 60, 1};
constexpr uint32_t kMipmapLevelCount = 3;
dstConfig.textureDescriptor.mipLevelCount = kMipmapLevelCount;
dstConfig.viewMipmapLevel = kMipmapLevelCount - 1;
// The actual size of the texture at mipmap level == 2 is not a multiple of 4, paddings are
// required in the copies.
// The virtual size of the texture at mipmap level == 2 is not a multiple of the texel
// dimensions so paddings are required in the copies.
const wgpu::Extent3D kDstVirtualSize = GetVirtualSizeAtLevel(dstConfig);
ASSERT_NE(0u, kDstVirtualSize.width % BlockWidthInTexels());
ASSERT_NE(0u, kDstVirtualSize.height % BlockHeightInTexels());
const wgpu::Extent3D kDstPhysicalSize = GetPhysicalSizeAtLevel(dstConfig);
srcConfig.copyExtent3D = dstConfig.copyExtent3D = kDstPhysicalSize;
ASSERT_LT(srcConfig.copyOrigin3D.x + srcConfig.copyExtent3D.width, kSrcVirtualSize.width);
ASSERT_LT(srcConfig.copyOrigin3D.y + srcConfig.copyExtent3D.height, kSrcVirtualSize.height);
// Create textureSrc as the source texture and initialize it with pre-prepared compressed
// data.
const wgpu::TextureFormat format = GetParam().mTextureFormat;
srcConfig.textureDescriptor.format = format;
srcConfig.textureDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
wgpu::Texture textureSrc = CreateTextureWithCompressedData(srcConfig);
wgpu::ImageCopyTexture imageCopyTextureSrc = utils::CreateImageCopyTexture(
textureSrc, srcConfig.viewMipmapLevel, srcConfig.copyOrigin3D);
// Create textureDst and copy from the content in textureSrc into it.
dstConfig.textureDescriptor.format = format;
dstConfig.textureDescriptor.usage = kDefaultFormatTextureUsage;
wgpu::Texture textureDst = CreateTextureFromTexture(textureSrc, srcConfig, dstConfig);
// Verify if we can use texture as sampled textures correctly.
@ -736,33 +814,20 @@ TEST_P(CompressedTextureFormatTest, CopyFromSubresourceWithPhysicalSizeNotEqualT
// subresource and does not fit in another one on OpenGL.
DAWN_SUPPRESS_TEST_IF(IsOpenGL() || IsOpenGLES());
CopyConfig srcConfig;
srcConfig.textureDescriptor.size = {60, 60, 1};
constexpr uint32_t kMipmapLevelCount = 3;
srcConfig.textureDescriptor.mipLevelCount = kMipmapLevelCount;
srcConfig.viewMipmapLevel = srcConfig.textureDescriptor.mipLevelCount - 1;
CopyConfig srcConfig = GetDefaultFullConfig();
srcConfig.textureDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
// The actual size of the texture at mipmap level == 2 is not a multiple of 4, paddings are
// required in the copies.
CopyConfig dstConfig = GetDefaultSubresourceConfig();
// The virtual size of the texture at mipmap level == 2 is not a multiple of the texel
// dimensions so paddings are required in the copies.
const wgpu::Extent3D kSrcVirtualSize = GetVirtualSizeAtLevel(srcConfig);
ASSERT_NE(0u, kSrcVirtualSize.width % BlockWidthInTexels());
ASSERT_NE(0u, kSrcVirtualSize.height % BlockHeightInTexels());
CopyConfig dstConfig;
dstConfig.textureDescriptor.size = {16, 16, 1};
dstConfig.viewMipmapLevel = dstConfig.textureDescriptor.mipLevelCount - 1;
const wgpu::Extent3D kDstVirtualSize = GetVirtualSizeAtLevel(dstConfig);
srcConfig.copyExtent3D = dstConfig.copyExtent3D = kDstVirtualSize;
ASSERT_GT(srcConfig.copyOrigin3D.x + srcConfig.copyExtent3D.width, kSrcVirtualSize.width);
ASSERT_GT(srcConfig.copyOrigin3D.y + srcConfig.copyExtent3D.height, kSrcVirtualSize.height);
srcConfig.textureDescriptor.format = dstConfig.textureDescriptor.format =
GetParam().mTextureFormat;
srcConfig.textureDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
dstConfig.textureDescriptor.usage = kDefaultFormatTextureUsage;
// Create textureSrc as the source texture and initialize it with pre-prepared compressed
// data.
wgpu::Texture textureSrc = CreateTextureWithCompressedData(srcConfig);
@ -794,68 +859,52 @@ TEST_P(CompressedTextureFormatTest, MultipleCopiesWithPhysicalSizeNotEqualToVirt
std::array<CopyConfig, kTotalCopyCount> srcConfigs;
std::array<CopyConfig, kTotalCopyCount> dstConfigs;
constexpr uint32_t kSrcMipmapLevelCount0 = 3;
srcConfigs[0].textureDescriptor.size = {60, 60, 1};
srcConfigs[0].textureDescriptor.mipLevelCount = kSrcMipmapLevelCount0;
srcConfigs[0].viewMipmapLevel = srcConfigs[0].textureDescriptor.mipLevelCount - 1;
dstConfigs[0].textureDescriptor.size = {16, 16, 1};
dstConfigs[0].viewMipmapLevel = dstConfigs[0].textureDescriptor.mipLevelCount - 1;
srcConfigs[0] = GetDefaultFullConfig();
srcConfigs[0].textureDescriptor.usage =
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
dstConfigs[0] = GetDefaultSubresourceConfig();
srcConfigs[0].copyExtent3D = dstConfigs[0].copyExtent3D = GetVirtualSizeAtLevel(dstConfigs[0]);
const wgpu::Extent3D kSrcVirtualSize0 = GetVirtualSizeAtLevel(srcConfigs[0]);
ASSERT_NE(0u, kSrcVirtualSize0.width % BlockWidthInTexels());
ASSERT_NE(0u, kSrcVirtualSize0.height % BlockHeightInTexels());
constexpr uint32_t kDstMipmapLevelCount1 = 4;
srcConfigs[1].textureDescriptor.size = {8, 8, 1};
srcConfigs[1].viewMipmapLevel = srcConfigs[1].textureDescriptor.mipLevelCount - 1;
dstConfigs[1].textureDescriptor.size = {56, 56, 1};
dstConfigs[1].textureDescriptor.mipLevelCount = kDstMipmapLevelCount1;
dstConfigs[1].viewMipmapLevel = dstConfigs[1].textureDescriptor.mipLevelCount - 1;
srcConfigs[1] = GetDefaultSubresourceConfig();
srcConfigs[1].textureDescriptor.usage =
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
dstConfigs[1] = GetDefaultFullConfig();
srcConfigs[1].copyExtent3D = dstConfigs[1].copyExtent3D = GetVirtualSizeAtLevel(srcConfigs[1]);
std::array<wgpu::Extent3D, kTotalCopyCount> dstVirtualSizes;
for (uint32_t i = 0; i < kTotalCopyCount; ++i) {
dstVirtualSizes[i] = GetVirtualSizeAtLevel(dstConfigs[i]);
}
ASSERT_NE(0u, dstVirtualSizes[1].width % BlockWidthInTexels());
ASSERT_NE(0u, dstVirtualSizes[1].height % BlockHeightInTexels());
std::array<wgpu::Texture, kTotalCopyCount> srcTextures;
std::array<wgpu::Texture, kTotalCopyCount> dstTextures;
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
for (uint32_t i = 0; i < kTotalCopyCount; ++i) {
srcConfigs[i].textureDescriptor.format = dstConfigs[i].textureDescriptor.format =
GetParam().mTextureFormat;
srcConfigs[i].textureDescriptor.usage =
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
dstConfigs[i].textureDescriptor.usage = kDefaultFormatTextureUsage;
// Create srcTextures as the source textures and initialize them with pre-prepared
// compressed data.
srcTextures[i] = CreateTextureWithCompressedData(srcConfigs[i]);
dstTextures[i] = device.CreateTexture(&dstConfigs[i].textureDescriptor);
RecordTextureToTextureCopy(encoder, srcTextures[i], dstTextures[i], srcConfigs[i],
dstConfigs[i]);
}
wgpu::CommandBuffer commandBuffer = encoder.Finish();
queue.Submit(1, &commandBuffer);
wgpu::CommandBuffer commandBuffer = encoder.Finish();
queue.Submit(1, &commandBuffer);
wgpu::RenderPipeline renderPipeline = CreateRenderPipelineForTest();
wgpu::RenderPipeline renderPipeline = CreateRenderPipelineForTest();
for (uint32_t i = 0; i < kTotalCopyCount; ++i) {
// Verify if we can use dstTextures as sampled textures correctly.
wgpu::BindGroup bindGroup0 =
CreateBindGroupForTest(renderPipeline.GetBindGroupLayout(0), dstTextures[i],
dstConfigs[i].copyOrigin3D.z, dstConfigs[i].viewMipmapLevel);
for (uint32_t i = 0; i < kTotalCopyCount; ++i) {
// Verify if we can use dstTextures as sampled textures correctly.
wgpu::BindGroup bindGroup0 =
CreateBindGroupForTest(renderPipeline.GetBindGroupLayout(0), dstTextures[i],
dstConfigs[i].copyOrigin3D.z, dstConfigs[i].viewMipmapLevel);
std::vector<RGBA8> expectedData = GetExpectedData(dstVirtualSizes[i]);
VerifyCompressedTexturePixelValues(renderPipeline, bindGroup0, dstVirtualSizes[i],
dstConfigs[i].copyOrigin3D, dstVirtualSizes[i],
expectedData);
}
std::vector<RGBA8> expectedData = GetExpectedData(dstVirtualSizes[i]);
VerifyCompressedTexturePixelValues(renderPipeline, bindGroup0, dstVirtualSizes[i],
dstConfigs[i].copyOrigin3D, dstVirtualSizes[i],
expectedData);
}
}
// A regression test for a bug for the toggle UseTemporaryBufferInCompressedTextureToTextureCopy on
@ -870,27 +919,18 @@ TEST_P(CompressedTextureFormatTest, CopyWithMultipleLayerAndPhysicalSizeNotEqual
constexpr uint32_t kArrayLayerCount = 5;
CopyConfig srcConfig;
srcConfig.textureDescriptor.size = {60, 60, kArrayLayerCount};
constexpr uint32_t kMipmapLevelCount = 3;
srcConfig.textureDescriptor.mipLevelCount = kMipmapLevelCount;
srcConfig.viewMipmapLevel = srcConfig.textureDescriptor.mipLevelCount - 1;
CopyConfig srcConfig = GetDefaultFullConfig(kArrayLayerCount);
srcConfig.textureDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
// The actual size of the texture at mipmap level == 2 is not a multiple of 4, paddings are
// required in the copies.
CopyConfig dstConfig = GetDefaultSubresourceConfig(kArrayLayerCount);
// The virtual size of the texture at mipmap level == 2 is not a multiple of the texel
// dimensions so paddings are required in the copies.
const wgpu::Extent3D kSrcVirtualSize = GetVirtualSizeAtLevel(srcConfig);
ASSERT_NE(0u, kSrcVirtualSize.width % BlockWidthInTexels());
ASSERT_NE(0u, kSrcVirtualSize.height % BlockHeightInTexels());
CopyConfig dstConfig;
dstConfig.textureDescriptor.size = {16, 16, kArrayLayerCount};
dstConfig.viewMipmapLevel = dstConfig.textureDescriptor.mipLevelCount - 1;
const wgpu::Extent3D kDstVirtualSize = GetVirtualSizeAtLevel(dstConfig);
srcConfig.copyExtent3D = dstConfig.copyExtent3D = kDstVirtualSize;
srcConfig.rowsPerImage = srcConfig.copyExtent3D.height / BlockHeightInTexels();
ASSERT_GT(srcConfig.copyOrigin3D.x + srcConfig.copyExtent3D.width, kSrcVirtualSize.width);
ASSERT_GT(srcConfig.copyOrigin3D.y + srcConfig.copyExtent3D.height, kSrcVirtualSize.height);
@ -936,19 +976,13 @@ TEST_P(CompressedTextureFormatTest, BufferOffsetAndExtentFitRowPitch) {
DAWN_TEST_UNSUPPORTED_IF(!IsFormatSupported());
CopyConfig config;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = {8, 8, 1};
CopyConfig config = GetDefaultSmallConfig();
config.copyExtent3D = config.textureDescriptor.size;
const uint32_t blockCountPerRow = config.textureDescriptor.size.width / BlockWidthInTexels();
const wgpu::TextureFormat format = GetParam().mTextureFormat;
config.textureDescriptor.format = format;
const uint32_t blockCountPerRow = config.textureDescriptor.size.width / BlockWidthInTexels();
const uint32_t blockSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes;
config.bufferOffset = (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes;
TestCopyRegionIntoFormatTextures(config);
@ -964,22 +998,16 @@ TEST_P(CompressedTextureFormatTest, BufferOffsetExceedsSlicePitch) {
DAWN_TEST_UNSUPPORTED_IF(!IsFormatSupported());
CopyConfig config;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = {8, 8, 1};
CopyConfig config = GetDefaultSmallConfig();
config.copyExtent3D = config.textureDescriptor.size;
const wgpu::Extent3D textureSizeLevel0 = config.textureDescriptor.size;
const uint32_t blockCountPerRow = textureSizeLevel0.width / BlockWidthInTexels();
const uint32_t slicePitchInBytes =
config.bytesPerRowAlignment * (textureSizeLevel0.height / BlockHeightInTexels());
const wgpu::TextureFormat format = GetParam().mTextureFormat;
config.textureDescriptor.format = format;
const wgpu::Extent3D textureSizeLevel = config.textureDescriptor.size;
const uint32_t blockCountPerRow = textureSizeLevel.width / BlockWidthInTexels();
const uint32_t slicePitchInBytes =
config.bytesPerRowAlignment * (textureSizeLevel.height / BlockHeightInTexels());
const uint32_t blockSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes;
config.bufferOffset = (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes +
config.bytesPerRowAlignment + slicePitchInBytes;
@ -994,18 +1022,13 @@ TEST_P(CompressedTextureFormatTest, CopyWithBufferOffsetAndExtentExceedRowPitch)
DAWN_TEST_UNSUPPORTED_IF(!IsFormatSupported());
CopyConfig config;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = {8, 8, 1};
config.copyExtent3D = config.textureDescriptor.size;
const uint32_t blockCountPerRow = config.textureDescriptor.size.width / BlockWidthInTexels();
constexpr uint32_t kExceedRowBlockCount = 1;
const wgpu::TextureFormat format = GetParam().mTextureFormat;
config.textureDescriptor.format = format;
CopyConfig config = GetDefaultSmallConfig();
config.copyExtent3D = config.textureDescriptor.size;
const wgpu::TextureFormat format = GetParam().mTextureFormat;
const uint32_t blockCountPerRow = config.textureDescriptor.size.width / BlockWidthInTexels();
const uint32_t blockSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes;
config.bufferOffset =
@ -1020,20 +1043,15 @@ TEST_P(CompressedTextureFormatTest, CopyWithBufferOffsetAndExtentExceedRowPitch)
TEST_P(CompressedTextureFormatTest, RowPitchEqualToSlicePitch) {
DAWN_TEST_UNSUPPORTED_IF(!IsFormatSupported());
CopyConfig config;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = {8, BlockHeightInTexels(), 1};
CopyConfig config = GetDefaultSmallConfig();
config.textureDescriptor.size = GetTextureSizeWithNumBlocks(2, 1);
config.copyExtent3D = config.textureDescriptor.size;
const wgpu::TextureFormat format = GetParam().mTextureFormat;
const uint32_t blockCountPerRow = config.textureDescriptor.size.width / BlockWidthInTexels();
const uint32_t slicePitchInBytes = config.bytesPerRowAlignment;
const wgpu::TextureFormat format = GetParam().mTextureFormat;
config.textureDescriptor.format = format;
const uint32_t blockSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes;
config.bufferOffset =
(blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes + slicePitchInBytes;
@ -1049,13 +1067,10 @@ TEST_P(CompressedTextureFormatTest, LargeImageHeight) {
DAWN_TEST_UNSUPPORTED_IF(!IsFormatSupported());
CopyConfig config;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = {8, 8, 1};
CopyConfig config = GetDefaultSmallConfig();
config.copyExtent3D = config.textureDescriptor.size;
config.rowsPerImage = config.textureDescriptor.size.height * 2 / BlockHeightInTexels();
config.textureDescriptor.format = GetParam().mTextureFormat;
TestCopyRegionIntoFormatTextures(config);
}
@ -1070,32 +1085,14 @@ TEST_P(CompressedTextureFormatTest, LargeImageHeightAndClampedCopyExtent) {
// This test uses glTextureView() which is not supported in OpenGL ES.
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
CopyConfig config;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = {56, 56, 1};
CopyConfig config = GetDefaultFullConfig();
constexpr uint32_t kMipmapLevelCount = 3;
config.textureDescriptor.mipLevelCount = kMipmapLevelCount;
config.viewMipmapLevel = kMipmapLevelCount - 1;
// The virtual size of the texture at mipmap level == 2 is not a multiple of the texel
// dimensions so paddings are required in the copies.
const wgpu::Extent3D kPhysicalSize = GetPhysicalSizeAtLevel(config);
config.copyExtent3D = kPhysicalSize;
config.rowsPerImage = kPhysicalSize.height * 2 / BlockHeightInTexels();
// The actual size of the texture at mipmap level == 2 is not a multiple of 4, paddings are
// required in the copies.
const wgpu::Extent3D textureSizeLevel0 = config.textureDescriptor.size;
const uint32_t kActualWidthAtLevel = textureSizeLevel0.width >> config.viewMipmapLevel;
const uint32_t kActualHeightAtLevel = textureSizeLevel0.height >> config.viewMipmapLevel;
ASSERT(kActualWidthAtLevel % BlockWidthInTexels() != 0);
ASSERT(kActualHeightAtLevel % BlockHeightInTexels() != 0);
const uint32_t kCopyWidthAtLevel = (kActualWidthAtLevel + BlockWidthInTexels() - 1) /
BlockWidthInTexels() * BlockWidthInTexels();
const uint32_t kCopyHeightAtLevel = (kActualHeightAtLevel + BlockHeightInTexels() - 1) /
BlockHeightInTexels() * BlockHeightInTexels();
config.copyExtent3D = {kCopyWidthAtLevel, kCopyHeightAtLevel, 1};
config.rowsPerImage = kCopyHeightAtLevel * 2 / BlockHeightInTexels();
config.textureDescriptor.format = GetParam().mTextureFormat;
TestCopyRegionIntoFormatTextures(config);
}
@ -1112,15 +1109,11 @@ TEST_P(CompressedTextureFormatTest, CopyWhole2DArrayTexture) {
constexpr uint32_t kArrayLayerCount = 3;
CopyConfig config;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = {8, 8, kArrayLayerCount};
CopyConfig config = GetDefaultSmallConfig(kArrayLayerCount);
config.rowsPerImage = 8;
config.copyExtent3D = config.textureDescriptor.size;
config.copyExtent3D.depthOrArrayLayers = kArrayLayerCount;
config.textureDescriptor.format = GetParam().mTextureFormat;
TestCopyRegionIntoFormatTextures(config);
}
@ -1136,9 +1129,7 @@ TEST_P(CompressedTextureFormatTest, CopyMultiple2DArrayLayers) {
constexpr uint32_t kArrayLayerCount = 3;
CopyConfig config;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = {8, 8, kArrayLayerCount};
CopyConfig config = GetDefaultSmallConfig(kArrayLayerCount);
config.rowsPerImage = 8;
constexpr uint32_t kCopyBaseArrayLayer = 1;
@ -1147,7 +1138,6 @@ TEST_P(CompressedTextureFormatTest, CopyMultiple2DArrayLayers) {
config.copyExtent3D = config.textureDescriptor.size;
config.copyExtent3D.depthOrArrayLayers = kCopyLayerCount;
config.textureDescriptor.format = GetParam().mTextureFormat;
TestCopyRegionIntoFormatTextures(config);
}
@ -1258,15 +1248,25 @@ TEST_P(CompressedTextureWriteTextureTest, Basic) {
// TODO(crbug.com/dawn/976): Failing on Linux Intel OpenGL drivers.
DAWN_SUPPRESS_TEST_IF(IsIntel() && IsOpenGL() && IsLinux());
constexpr uint32_t kSizeWidthMultiplier = 5;
constexpr uint32_t kSizeHeightMultiplier = 6;
constexpr uint32_t kOriginWidthMultiplier = 1;
constexpr uint32_t kOriginHeightMultiplier = 2;
constexpr uint32_t kExtentWidthMultiplier = 3;
constexpr uint32_t kExtentHeightMultiplier = 4;
CopyConfig config;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = {20, 24, 1};
config.copyOrigin3D = {4, 8, 0};
config.copyExtent3D = {12, 16, 1};
config.textureDescriptor.size = {BlockWidthInTexels() * kSizeWidthMultiplier,
BlockHeightInTexels() * kSizeHeightMultiplier, 1};
config.copyOrigin3D = {BlockWidthInTexels() * kOriginWidthMultiplier,
BlockHeightInTexels() * kOriginHeightMultiplier, 0};
config.copyExtent3D = {BlockWidthInTexels() * kExtentWidthMultiplier,
BlockHeightInTexels() * kExtentHeightMultiplier, 1};
config.bytesPerRowAlignment = 511;
config.rowsPerImage = 5;
config.textureDescriptor.format = GetParam().mTextureFormat;
TestWriteRegionIntoFormatTextures(config);
}
@ -1278,15 +1278,26 @@ TEST_P(CompressedTextureWriteTextureTest, WriteMultiple2DArrayLayers) {
// TODO(crbug.com/dawn/593): This test uses glTextureView() which is not supported on OpenGLES.
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
// TODO(b/198674734): Width multiplier set to 7 because 5 results in square size for ASTC6x5.
constexpr uint32_t kSizeWidthMultiplier = 7;
constexpr uint32_t kSizeHeightMultiplier = 6;
constexpr uint32_t kOriginWidthMultiplier = 1;
constexpr uint32_t kOriginHeightMultiplier = 2;
constexpr uint32_t kExtentWidthMultiplier = 3;
constexpr uint32_t kExtentHeightMultiplier = 4;
CopyConfig config;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = {20, 24, 9};
config.copyOrigin3D = {4, 8, 3};
config.copyExtent3D = {12, 16, 6};
config.textureDescriptor.size = {BlockWidthInTexels() * kSizeWidthMultiplier,
BlockHeightInTexels() * kSizeHeightMultiplier, 9};
config.copyOrigin3D = {BlockWidthInTexels() * kOriginWidthMultiplier,
BlockHeightInTexels() * kOriginHeightMultiplier, 3};
config.copyExtent3D = {BlockWidthInTexels() * kExtentWidthMultiplier,
BlockHeightInTexels() * kExtentHeightMultiplier, 6};
config.bytesPerRowAlignment = 511;
config.rowsPerImage = 5;
config.textureDescriptor.format = GetParam().mTextureFormat;
TestWriteRegionIntoFormatTextures(config);
}
@ -1300,25 +1311,19 @@ TEST_P(CompressedTextureWriteTextureTest,
// TODO(crbug.com/dawn/593): This test uses glTextureView() which is not supported on OpenGLES.
DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES());
// Texture virtual size at mipLevel 2 will be {15, 15, 1} while the physical
// size will be {16, 16, 1}.
// Setting copyExtent.width or copyExtent.height to 16 fits in
// the texture physical size, but doesn't fit in the virtual size.
for (unsigned int w : {12, 16}) {
for (unsigned int h : {12, 16}) {
CopyConfig config;
config.textureDescriptor.usage = kDefaultFormatTextureUsage;
config.textureDescriptor.size = {60, 60, 1};
config.textureDescriptor.mipLevelCount = 4;
config.viewMipmapLevel = 2;
CopyConfig config = GetDefaultFullConfig();
config.copyOrigin3D = {0, 0, 0};
config.copyExtent3D = {w, h, 1};
config.bytesPerRowAlignment = 256;
config.textureDescriptor.format = GetParam().mTextureFormat;
TestWriteRegionIntoFormatTextures(config);
}
// The virtual size of the texture at mipmap level == 2 is not a multiple of the texel
// dimensions so paddings are required in the copies. We then test against the expected
// physical size and a valid size smaller than the physical size for verification.
const wgpu::Extent3D kPhysicalSize = GetPhysicalSizeAtLevel(config);
for (unsigned int w : {kPhysicalSize.width - BlockWidthInTexels(), kPhysicalSize.width}) {
for (unsigned int h :
{kPhysicalSize.height - BlockHeightInTexels(), kPhysicalSize.height}) {
config.copyExtent3D = {w, h, 1};
TestWriteRegionIntoFormatTextures(config);
}
}
}
DAWN_INSTANTIATE_TEST_P(CompressedTextureWriteTextureTest,

View File

@ -198,6 +198,33 @@ class CopyCommandTest : public ValidationTest {
}
};
// Test copies between buffer and multiple array layers of an uncompressed texture
TEST_F(CopyCommandTest, CopyToMultipleArrayLayers) {
wgpu::Texture destination =
CopyCommandTest::Create2DTexture(4, 2, 1, 5, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
// Copy to all array layers
TestBothTBCopiesExactBufferSize(256, 2, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 0},
{4, 2, 5});
// Copy to the highest array layer
TestBothTBCopiesExactBufferSize(256, 2, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 4},
{4, 2, 1});
// Copy to array layers in the middle
TestBothTBCopiesExactBufferSize(256, 2, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 1},
{4, 2, 3});
// Copy with a non-packed rowsPerImage
TestBothTBCopiesExactBufferSize(256, 3, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 0},
{4, 2, 5});
// Copy with bytesPerRow = 512
TestBothTBCopiesExactBufferSize(512, 2, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 1},
{4, 2, 3});
}
class CopyCommandTest_B2B : public CopyCommandTest {};
// TODO(cwallez@chromium.org): Test that copies are forbidden inside renderpasses
@ -2026,9 +2053,9 @@ class CopyCommandTest_CompressedTextureFormats : public CopyCommandTest {
}
wgpu::Texture Create2DTexture(wgpu::TextureFormat format,
uint32_t mipmapLevels = 1,
uint32_t width = kWidth,
uint32_t height = kHeight) {
uint32_t mipmapLevels,
uint32_t width,
uint32_t height) {
constexpr wgpu::TextureUsage kUsage = wgpu::TextureUsage::CopyDst |
wgpu::TextureUsage::CopySrc |
wgpu::TextureUsage::TextureBinding;
@ -2037,8 +2064,12 @@ class CopyCommandTest_CompressedTextureFormats : public CopyCommandTest {
kUsage, 1);
}
static constexpr uint32_t kWidth = 16;
static constexpr uint32_t kHeight = 16;
// By default, we use a 4x4 tiling of the format block size.
wgpu::Texture Create2DTexture(wgpu::TextureFormat format) {
uint32_t width = utils::GetTextureFormatBlockWidth(format) * 4;
uint32_t height = utils::GetTextureFormatBlockHeight(format) * 4;
return Create2DTexture(format, 1, width, height);
}
};
// Tests to verify that bufferOffset must be a multiple of the compressed texture blocks in bytes
@ -2049,19 +2080,21 @@ TEST_F(CopyCommandTest_CompressedTextureFormats, BufferOffset) {
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format);
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
// Valid usages of BufferOffset in B2T and T2B copies with compressed texture formats.
{
uint32_t validBufferOffset = utils::GetTexelBlockSizeInBytes(format);
TestBothTBCopies(utils::Expectation::Success, buffer, validBufferOffset, 256, 4,
texture, 0, {0, 0, 0}, {4, 4, 1});
texture, 0, {0, 0, 0}, {blockWidth, blockHeight, 1});
}
// Failures on invalid bufferOffset.
{
uint32_t kInvalidBufferOffset = utils::GetTexelBlockSizeInBytes(format) / 2;
TestBothTBCopies(utils::Expectation::Failure, buffer, kInvalidBufferOffset, 256, 4,
texture, 0, {0, 0, 0}, {4, 4, 1});
texture, 0, {0, 0, 0}, {blockWidth, blockHeight, 1});
}
}
}
@ -2073,36 +2106,40 @@ TEST_F(CopyCommandTest_CompressedTextureFormats, BytesPerRow) {
wgpu::Buffer buffer =
CreateBuffer(1024, wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst);
constexpr uint32_t kTestWidth = 160;
constexpr uint32_t kTestHeight = 160;
// Used to compute test width and height. We choose 320 because it isn't divisible by 256 and
// hence will need to be aligned.
constexpr uint32_t kInvalidBytesPerRow = 320;
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format, 1, kTestWidth, kTestHeight);
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
// Compute the test width and height such that the smallest BytesPerRow is always equal to
// 320. We choose 320 because it isn't divisible by 256 and hence needs to be aligned.
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
uint32_t blockByteSize = utils::GetTexelBlockSizeInBytes(format);
uint32_t testWidth = kInvalidBytesPerRow * blockWidth / blockByteSize;
uint32_t testHeight = kInvalidBytesPerRow * blockHeight / blockByteSize;
wgpu::Texture texture = Create2DTexture(format, 1, testWidth, testHeight);
// Failures on the BytesPerRow that is not large enough.
{
constexpr uint32_t kSmallBytesPerRow = 256;
TestBothTBCopies(utils::Expectation::Failure, buffer, 0, kSmallBytesPerRow, 4,
texture, 0, {0, 0, 0}, {kTestWidth, 4, 1});
}
// Test it is not valid to use a BytesPerRow that is not a multiple of 256.
{
uint32_t inValidBytesPerRow =
kTestWidth / 4 * utils::GetTexelBlockSizeInBytes(format);
ASSERT_NE(0u, inValidBytesPerRow % 256);
TestBothTBCopies(utils::Expectation::Failure, buffer, 0, inValidBytesPerRow, 4,
texture, 0, {0, 0, 0}, {kTestWidth, 4, 1});
}
// Test the smallest valid BytesPerRow should work.
{
uint32_t smallestValidBytesPerRow =
Align(kTestWidth / 4 * utils::GetTexelBlockSizeInBytes(format), 256);
TestBothTBCopies(utils::Expectation::Success, buffer, 0, smallestValidBytesPerRow,
4, texture, 0, {0, 0, 0}, {kTestWidth, 4, 1});
}
// Failures on the BytesPerRow that is not large enough.
{
constexpr uint32_t kSmallBytesPerRow = 256;
TestBothTBCopies(utils::Expectation::Failure, buffer, 0, kSmallBytesPerRow, 4, texture,
0, {0, 0, 0}, {testWidth, blockHeight, 1});
}
// Test it is not valid to use a BytesPerRow that is not a multiple of 256.
{
TestBothTBCopies(utils::Expectation::Failure, buffer, 0, kInvalidBytesPerRow, 4,
texture, 0, {0, 0, 0}, {testWidth, blockHeight, 1});
}
// Test the smallest valid BytesPerRow should work.
{
uint32_t smallestValidBytesPerRow = Align(kInvalidBytesPerRow, 256);
TestBothTBCopies(utils::Expectation::Success, buffer, 0, smallestValidBytesPerRow, 4,
texture, 0, {0, 0, 0}, {testWidth, blockHeight, 1});
}
}
}
// rowsPerImage must be >= heightInBlocks.
@ -2112,24 +2149,26 @@ TEST_F(CopyCommandTest_CompressedTextureFormats, RowsPerImage) {
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format);
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
// Valid usages of rowsPerImage in B2T and T2B copies with compressed texture formats.
{
constexpr uint32_t kValidRowsPerImage = 5;
TestBothTBCopies(utils::Expectation::Success, buffer, 0, 256, kValidRowsPerImage,
texture, 0, {0, 0, 0}, {4, 16, 1});
texture, 0, {0, 0, 0}, {blockWidth, blockHeight * 4, 1});
}
{
constexpr uint32_t kValidRowsPerImage = 4;
TestBothTBCopies(utils::Expectation::Success, buffer, 0, 256, kValidRowsPerImage,
texture, 0, {0, 0, 0}, {4, 16, 1});
texture, 0, {0, 0, 0}, {blockWidth, blockHeight * 4, 1});
}
// rowsPerImage is smaller than height.
{
constexpr uint32_t kInvalidRowsPerImage = 3;
TestBothTBCopies(utils::Expectation::Failure, buffer, 0, 256, kInvalidRowsPerImage,
texture, 0, {0, 0, 0}, {4, 20, 1});
texture, 0, {0, 0, 0}, {blockWidth, blockHeight * 5, 1});
}
}
}
@ -2144,35 +2183,37 @@ TEST_F(CopyCommandTest_CompressedTextureFormats, ImageOffset) {
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format);
wgpu::Texture texture2 = Create2DTexture(format);
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
constexpr wgpu::Origin3D kSmallestValidOrigin3D = {4, 4, 0};
wgpu::Origin3D smallestValidOrigin3D = {blockWidth, blockHeight, 0};
// Valid usages of ImageOffset in B2T, T2B and T2T copies with compressed texture formats.
{
TestBothTBCopies(utils::Expectation::Success, buffer, 0, 256, 4, texture, 0,
kSmallestValidOrigin3D, {4, 4, 1});
smallestValidOrigin3D, {blockWidth, blockHeight, 1});
TestBothT2TCopies(utils::Expectation::Success, texture, 0, {0, 0, 0}, texture2, 0,
kSmallestValidOrigin3D, {4, 4, 1});
smallestValidOrigin3D, {blockWidth, blockHeight, 1});
}
// Failures on invalid ImageOffset.x.
{
constexpr wgpu::Origin3D kInvalidOrigin3D = {kSmallestValidOrigin3D.x - 1,
kSmallestValidOrigin3D.y, 0};
wgpu::Origin3D invalidOrigin3D = {smallestValidOrigin3D.x - 1, smallestValidOrigin3D.y,
0};
TestBothTBCopies(utils::Expectation::Failure, buffer, 0, 256, 4, texture, 0,
kInvalidOrigin3D, {4, 4, 1});
TestBothT2TCopies(utils::Expectation::Failure, texture, 0, kInvalidOrigin3D, texture2,
0, {0, 0, 0}, {4, 4, 1});
invalidOrigin3D, {blockWidth, blockHeight, 1});
TestBothT2TCopies(utils::Expectation::Failure, texture, 0, invalidOrigin3D, texture2, 0,
{0, 0, 0}, {blockWidth, blockHeight, 1});
}
// Failures on invalid ImageOffset.y.
{
constexpr wgpu::Origin3D kInvalidOrigin3D = {kSmallestValidOrigin3D.x,
kSmallestValidOrigin3D.y - 1, 0};
wgpu::Origin3D invalidOrigin3D = {smallestValidOrigin3D.x, smallestValidOrigin3D.y - 1,
0};
TestBothTBCopies(utils::Expectation::Failure, buffer, 0, 256, 4, texture, 0,
kInvalidOrigin3D, {4, 4, 1});
TestBothT2TCopies(utils::Expectation::Failure, texture, 0, kInvalidOrigin3D, texture2,
0, {0, 0, 0}, {4, 4, 1});
invalidOrigin3D, {blockWidth, blockHeight, 1});
TestBothT2TCopies(utils::Expectation::Failure, texture, 0, invalidOrigin3D, texture2, 0,
{0, 0, 0}, {blockWidth, blockHeight, 1});
}
}
}
@ -2182,105 +2223,95 @@ TEST_F(CopyCommandTest_CompressedTextureFormats, ImageOffset) {
// texture-to-buffer or texture-to-texture copies with compressed texture formats.
TEST_F(CopyCommandTest_CompressedTextureFormats, ImageExtent) {
wgpu::Buffer buffer =
CreateBuffer(512, wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst);
CreateBuffer(1024, wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst);
constexpr uint32_t kMipmapLevels = 3;
constexpr uint32_t kTestWidth = 60;
constexpr uint32_t kTestHeight = 60;
// We choose a prime that is greater than the current max texel dimension size as a multiplier
// to compute the test texture size so that we can be certain that its level 2 mipmap (x4)
// cannot be a multiple of the dimension. This is useful for testing padding at the edges of
// the mipmaps.
constexpr uint32_t kBlockPerDim = 13;
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format, kMipmapLevels, kTestWidth, kTestHeight);
wgpu::Texture texture2 = Create2DTexture(format, kMipmapLevels, kTestWidth, kTestHeight);
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
uint32_t testWidth = blockWidth * kBlockPerDim;
uint32_t testHeight = blockHeight * kBlockPerDim;
wgpu::Texture texture = Create2DTexture(format, kMipmapLevels, testWidth, testHeight);
wgpu::Texture texture2 = Create2DTexture(format, kMipmapLevels, testWidth, testHeight);
constexpr wgpu::Extent3D kSmallestValidExtent3D = {4, 4, 1};
wgpu::Extent3D smallestValidExtent3D = {blockWidth, blockHeight, 1};
// Valid usages of ImageExtent in B2T, T2B and T2T copies with compressed texture formats.
{
TestBothTBCopies(utils::Expectation::Success, buffer, 0, 256, 8, texture, 0, {0, 0, 0},
kSmallestValidExtent3D);
TestBothTBCopies(utils::Expectation::Success, buffer, 0, 256, 4, texture, 0, {0, 0, 0},
smallestValidExtent3D);
TestBothT2TCopies(utils::Expectation::Success, texture, 0, {0, 0, 0}, texture2, 0,
{0, 0, 0}, kSmallestValidExtent3D);
{0, 0, 0}, smallestValidExtent3D);
}
// Valid usages of ImageExtent in B2T, T2B and T2T copies with compressed texture formats
// and non-zero mipmap levels.
{
constexpr uint32_t kTestMipmapLevel = 2;
constexpr wgpu::Origin3D kTestOrigin = {
(kTestWidth >> kTestMipmapLevel) - kSmallestValidExtent3D.width + 1,
(kTestHeight >> kTestMipmapLevel) - kSmallestValidExtent3D.height + 1, 0};
wgpu::Origin3D testOrigin = {
((testWidth >> kTestMipmapLevel) / blockWidth) * blockWidth,
((testHeight >> kTestMipmapLevel) / blockHeight) * blockHeight, 0};
TestBothTBCopies(utils::Expectation::Success, buffer, 0, 256, 4, texture,
kTestMipmapLevel, kTestOrigin, kSmallestValidExtent3D);
TestBothT2TCopies(utils::Expectation::Success, texture, kTestMipmapLevel, kTestOrigin,
texture2, 0, {0, 0, 0}, kSmallestValidExtent3D);
kTestMipmapLevel, testOrigin, smallestValidExtent3D);
TestBothT2TCopies(utils::Expectation::Success, texture, kTestMipmapLevel, testOrigin,
texture2, 0, {0, 0, 0}, smallestValidExtent3D);
}
// Failures on invalid ImageExtent.x.
{
constexpr wgpu::Extent3D kInValidExtent3D = {kSmallestValidExtent3D.width - 1,
kSmallestValidExtent3D.height, 1};
wgpu::Extent3D inValidExtent3D = {smallestValidExtent3D.width - 1,
smallestValidExtent3D.height, 1};
TestBothTBCopies(utils::Expectation::Failure, buffer, 0, 256, 4, texture, 0, {0, 0, 0},
kInValidExtent3D);
inValidExtent3D);
TestBothT2TCopies(utils::Expectation::Failure, texture, 0, {0, 0, 0}, texture2, 0,
{0, 0, 0}, kInValidExtent3D);
{0, 0, 0}, inValidExtent3D);
}
// Failures on invalid ImageExtent.y.
{
constexpr wgpu::Extent3D kInValidExtent3D = {kSmallestValidExtent3D.width,
kSmallestValidExtent3D.height - 1, 1};
wgpu::Extent3D inValidExtent3D = {smallestValidExtent3D.width,
smallestValidExtent3D.height - 1, 1};
TestBothTBCopies(utils::Expectation::Failure, buffer, 0, 256, 4, texture, 0, {0, 0, 0},
kInValidExtent3D);
inValidExtent3D);
TestBothT2TCopies(utils::Expectation::Failure, texture, 0, {0, 0, 0}, texture2, 0,
{0, 0, 0}, kInValidExtent3D);
{0, 0, 0}, inValidExtent3D);
}
}
}
// Test copies between buffer and multiple array layers of an uncompressed texture
TEST_F(CopyCommandTest, CopyToMultipleArrayLayers) {
wgpu::Texture destination =
CopyCommandTest::Create2DTexture(4, 2, 1, 5, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
// Copy to all array layers
TestBothTBCopiesExactBufferSize(256, 2, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 0},
{4, 2, 5});
// Copy to the highest array layer
TestBothTBCopiesExactBufferSize(256, 2, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 4},
{4, 2, 1});
// Copy to array layers in the middle
TestBothTBCopiesExactBufferSize(256, 2, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 1},
{4, 2, 3});
// Copy with a non-packed rowsPerImage
TestBothTBCopiesExactBufferSize(256, 3, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 0},
{4, 2, 5});
// Copy with bytesPerRow = 512
TestBothTBCopiesExactBufferSize(512, 2, destination, wgpu::TextureFormat::RGBA8Unorm, {0, 0, 1},
{4, 2, 3});
}
// Test copies between buffer and multiple array layers of a compressed texture
TEST_F(CopyCommandTest_CompressedTextureFormats, CopyToMultipleArrayLayers) {
constexpr uint32_t kWidthMultiplier = 3;
constexpr uint32_t kHeightMultiplier = 4;
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
uint32_t testWidth = kWidthMultiplier * blockWidth;
uint32_t testHeight = kHeightMultiplier * blockHeight;
wgpu::Texture texture = CopyCommandTest::Create2DTexture(
12, 16, 1, 20, format, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
testWidth, testHeight, 1, 20, format,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
// Copy to all array layers
TestBothTBCopiesExactBufferSize(256, 4, texture, format, {0, 0, 0}, {12, 16, 20});
TestBothTBCopiesExactBufferSize(256, 4, texture, format, {0, 0, 0},
{testWidth, testHeight, 20});
// Copy to the highest array layer
TestBothTBCopiesExactBufferSize(256, 4, texture, format, {0, 0, 19}, {12, 16, 1});
TestBothTBCopiesExactBufferSize(256, 4, texture, format, {0, 0, 19},
{testWidth, testHeight, 1});
// Copy to array layers in the middle
TestBothTBCopiesExactBufferSize(256, 4, texture, format, {0, 0, 1}, {12, 16, 18});
TestBothTBCopiesExactBufferSize(256, 4, texture, format, {0, 0, 1},
{testWidth, testHeight, 18});
// Copy touching the texture corners with a non-packed rowsPerImage
TestBothTBCopiesExactBufferSize(256, 6, texture, format, {4, 4, 4}, {8, 12, 16});
TestBothTBCopiesExactBufferSize(256, 6, texture, format, {blockWidth, blockHeight, 4},
{testWidth - blockWidth, testHeight - blockHeight, 16});
}
}

View File

@ -586,25 +586,29 @@ namespace {
textOrigin, size);
}
static constexpr uint32_t kWidth = 16;
static constexpr uint32_t kHeight = 16;
static constexpr uint32_t kWidth = 120;
static constexpr uint32_t kHeight = 120;
};
// Tests to verify that data offset may not be a multiple of the compressed texture block size
TEST_F(WriteTextureTest_CompressedTextureFormats, DataOffset) {
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format);
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
// Valid if aligned.
{
uint32_t kAlignedOffset = utils::GetTexelBlockSizeInBytes(format);
TestWriteTexture(1024, kAlignedOffset, 256, 4, texture, 0, {0, 0, 0}, {4, 16, 1});
TestWriteTexture(1024, kAlignedOffset, 256, 4, texture, 0, {0, 0, 0},
{blockWidth, blockHeight, 1});
}
// Still valid if not aligned.
{
uint32_t kUnalignedOffset = utils::GetTexelBlockSizeInBytes(format) - 1;
TestWriteTexture(1024, kUnalignedOffset, 256, 4, texture, 0, {0, 0, 0}, {4, 16, 1});
TestWriteTexture(1024, kUnalignedOffset, 256, 4, texture, 0, {0, 0, 0},
{blockWidth, blockHeight, 1});
}
}
}
@ -613,45 +617,41 @@ namespace {
// blockSizeInBytes and that it doesn't have to be a multiple of the compressed
// texture block width.
TEST_F(WriteTextureTest_CompressedTextureFormats, BytesPerRow) {
constexpr uint32_t kTestWidth = 160;
constexpr uint32_t kTestHeight = 160;
// Failures on the BytesPerRow that is not large enough.
{
constexpr uint32_t kSmallBytesPerRow = 256;
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format, 1, kTestWidth, kTestHeight);
ASSERT_DEVICE_ERROR(TestWriteTexture(1024, 0, kSmallBytesPerRow, 4, texture, 0,
{0, 0, 0}, {kTestWidth, 4, 1}));
}
}
// Test it is valid to use a BytesPerRow that is not a multiple of 256.
{
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format, 1, kTestWidth, kTestHeight);
uint32_t ValidBytesPerRow =
kTestWidth / 4 * utils::GetTexelBlockSizeInBytes(format);
ASSERT_NE(0u, ValidBytesPerRow % 256);
TestWriteTexture(1024, 0, ValidBytesPerRow, 4, texture, 0, {0, 0, 0},
{kTestWidth, 4, 1});
}
}
// Used to compute test width and height.
constexpr uint32_t kTestBytesPerRow = 320;
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format);
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
uint32_t blockByteSize = utils::GetTexelBlockSizeInBytes(format);
uint32_t testWidth = kTestBytesPerRow * blockWidth / blockByteSize;
uint32_t testHeight = kTestBytesPerRow * blockHeight / blockByteSize;
wgpu::Texture texture = Create2DTexture(format, 1, testWidth, testHeight);
// Failures on the BytesPerRow that is not large enough.
{
uint32_t kSmallBytesPerRow = kTestBytesPerRow - blockByteSize;
ASSERT_DEVICE_ERROR(TestWriteTexture(1024, 0, kSmallBytesPerRow, 4, texture, 0,
{0, 0, 0}, {testWidth, blockHeight, 1}));
}
// Test it is valid to use a BytesPerRow that is not a multiple of 256.
{
TestWriteTexture(1024, 0, kTestBytesPerRow, 4, texture, 0, {0, 0, 0},
{testWidth, blockHeight, 1});
}
// Valid usage of bytesPerRow in WriteTexture with compressed texture formats.
{
constexpr uint32_t kValidBytesPerRow = 20;
TestWriteTexture(512, 0, kValidBytesPerRow, 4, texture, 0, {0, 0, 0}, {4, 4, 1});
TestWriteTexture(512, 0, blockByteSize, 4, texture, 0, {0, 0, 0},
{blockWidth, blockHeight, 1});
}
// Valid bytesPerRow.
// Note that image width is not a multiple of blockWidth.
// Valid usage of bytesPerRow in WriteTexture with compressed texture formats. Note that
// BytesPerRow is not a multiple of the blockByteSize (but is greater than it).
{
constexpr uint32_t kValidBytesPerRow = 17;
TestWriteTexture(512, 0, kValidBytesPerRow, 4, texture, 0, {0, 0, 0}, {4, 4, 1});
TestWriteTexture(512, 0, blockByteSize + 1, 4, texture, 0, {0, 0, 0},
{blockWidth, blockHeight, 1});
}
}
}
@ -660,24 +660,26 @@ namespace {
TEST_F(WriteTextureTest_CompressedTextureFormats, RowsPerImage) {
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format);
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
// Valid usages of rowsPerImage in WriteTexture with compressed texture formats.
{
constexpr uint32_t kValidRowsPerImage = 5;
TestWriteTexture(1024, 0, 256, kValidRowsPerImage, texture, 0, {0, 0, 0},
{4, 16, 1});
{blockWidth, blockHeight * 4, 1});
}
{
constexpr uint32_t kValidRowsPerImage = 4;
TestWriteTexture(1024, 0, 256, kValidRowsPerImage, texture, 0, {0, 0, 0},
{4, 16, 1});
{blockWidth, blockHeight * 4, 1});
}
// Failure on invalid rowsPerImage.
// rowsPerImage is smaller than height.
{
constexpr uint32_t kInvalidRowsPerImage = 3;
ASSERT_DEVICE_ERROR(TestWriteTexture(1024, 0, 256, kInvalidRowsPerImage, texture, 0,
{0, 0, 0}, {4, 16, 1}));
{0, 0, 0}, {blockWidth, blockWidth * 4, 1}));
}
}
}
@ -688,26 +690,31 @@ namespace {
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format);
wgpu::Texture texture2 = Create2DTexture(format);
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
constexpr wgpu::Origin3D kSmallestValidOrigin3D = {4, 4, 0};
wgpu::Origin3D smallestValidOrigin3D = {blockWidth, blockHeight, 0};
// Valid usages of ImageOffset in WriteTexture with compressed texture formats.
{ TestWriteTexture(512, 0, 256, 4, texture, 0, kSmallestValidOrigin3D, {4, 4, 1}); }
{
TestWriteTexture(512, 0, 256, 4, texture, 0, smallestValidOrigin3D,
{blockWidth, blockHeight, 1});
}
// Failures on invalid ImageOffset.x.
{
constexpr wgpu::Origin3D kInvalidOrigin3D = {kSmallestValidOrigin3D.x - 1,
kSmallestValidOrigin3D.y, 0};
ASSERT_DEVICE_ERROR(
TestWriteTexture(512, 0, 256, 4, texture, 0, kInvalidOrigin3D, {4, 4, 1}));
wgpu::Origin3D invalidOrigin3D = {smallestValidOrigin3D.x - 1,
smallestValidOrigin3D.y, 0};
ASSERT_DEVICE_ERROR(TestWriteTexture(512, 0, 256, 4, texture, 0, invalidOrigin3D,
{blockWidth, blockHeight, 1}));
}
// Failures on invalid ImageOffset.y.
{
constexpr wgpu::Origin3D kInvalidOrigin3D = {kSmallestValidOrigin3D.x,
kSmallestValidOrigin3D.y - 1, 0};
ASSERT_DEVICE_ERROR(
TestWriteTexture(512, 0, 256, 4, texture, 0, kInvalidOrigin3D, {4, 4, 1}));
wgpu::Origin3D invalidOrigin3D = {smallestValidOrigin3D.x,
smallestValidOrigin3D.y - 1, 0};
ASSERT_DEVICE_ERROR(TestWriteTexture(512, 0, 256, 4, texture, 0, invalidOrigin3D,
{blockWidth, blockHeight, 1}));
}
}
}
@ -716,66 +723,83 @@ namespace {
// and ImageExtent.y must be a multiple of the compressed texture block height
TEST_F(WriteTextureTest_CompressedTextureFormats, ImageExtent) {
constexpr uint32_t kMipmapLevels = 3;
constexpr uint32_t kTestWidth = 60;
constexpr uint32_t kTestHeight = 60;
// We choose a prime that is greater than the current max texel dimension size as a
// multiplier to compute the test texture size so that we can be certain that its level 2
// mipmap (x4) cannot be a multiple of the dimension. This is useful for testing padding at
// the edges of the mipmaps.
constexpr uint32_t kBlockPerDim = 13;
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format, kMipmapLevels, kTestWidth, kTestHeight);
wgpu::Texture texture2 =
Create2DTexture(format, kMipmapLevels, kTestWidth, kTestHeight);
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
uint32_t testWidth = blockWidth * kBlockPerDim;
uint32_t testHeight = blockHeight * kBlockPerDim;
wgpu::Texture texture = Create2DTexture(format, kMipmapLevels, testWidth, testHeight);
wgpu::Texture texture2 = Create2DTexture(format, kMipmapLevels, testWidth, testHeight);
constexpr wgpu::Extent3D kSmallestValidExtent3D = {4, 4, 1};
wgpu::Extent3D smallestValidExtent3D = {blockWidth, blockHeight, 1};
// Valid usages of ImageExtent in WriteTexture with compressed texture formats.
{ TestWriteTexture(512, 0, 256, 8, texture, 0, {0, 0, 0}, kSmallestValidExtent3D); }
{ TestWriteTexture(512, 0, 256, 4, texture, 0, {0, 0, 0}, smallestValidExtent3D); }
// Valid usages of ImageExtent in WriteTexture with compressed texture formats
// and non-zero mipmap levels.
{
constexpr uint32_t kTestMipmapLevel = 2;
constexpr wgpu::Origin3D kTestOrigin = {
(kTestWidth >> kTestMipmapLevel) - kSmallestValidExtent3D.width + 1,
(kTestHeight >> kTestMipmapLevel) - kSmallestValidExtent3D.height + 1, 0};
wgpu::Origin3D testOrigin = {
((testWidth >> kTestMipmapLevel) / blockWidth) * blockWidth,
((testHeight >> kTestMipmapLevel) / blockHeight) * blockHeight, 0};
TestWriteTexture(512, 0, 256, 4, texture, kTestMipmapLevel, kTestOrigin,
kSmallestValidExtent3D);
TestWriteTexture(512, 0, 256, 4, texture, kTestMipmapLevel, testOrigin,
smallestValidExtent3D);
}
// Failures on invalid ImageExtent.x.
{
constexpr wgpu::Extent3D kInValidExtent3D = {kSmallestValidExtent3D.width - 1,
kSmallestValidExtent3D.height, 1};
wgpu::Extent3D inValidExtent3D = {smallestValidExtent3D.width - 1,
smallestValidExtent3D.height, 1};
ASSERT_DEVICE_ERROR(
TestWriteTexture(512, 0, 256, 4, texture, 0, {0, 0, 0}, kInValidExtent3D));
TestWriteTexture(512, 0, 256, 4, texture, 0, {0, 0, 0}, inValidExtent3D));
}
// Failures on invalid ImageExtent.y.
{
constexpr wgpu::Extent3D kInValidExtent3D = {kSmallestValidExtent3D.width,
kSmallestValidExtent3D.height - 1, 1};
wgpu::Extent3D inValidExtent3D = {smallestValidExtent3D.width,
smallestValidExtent3D.height - 1, 1};
ASSERT_DEVICE_ERROR(
TestWriteTexture(512, 0, 256, 4, texture, 0, {0, 0, 0}, kInValidExtent3D));
TestWriteTexture(512, 0, 256, 4, texture, 0, {0, 0, 0}, inValidExtent3D));
}
}
}
// Test writes to multiple array layers of a compressed texture
TEST_F(WriteTextureTest_CompressedTextureFormats, WriteToMultipleArrayLayers) {
constexpr uint32_t kWidthMultiplier = 3;
constexpr uint32_t kHeightMultiplier = 4;
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
uint32_t testWidth = kWidthMultiplier * blockWidth;
uint32_t testHeight = kHeightMultiplier * blockHeight;
wgpu::Texture texture = QueueWriteTextureValidationTest::Create2DTexture(
{12, 16, 20}, 1, format, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
{testWidth, testHeight, 20}, 1, format,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
// Write to all array layers
TestWriteTextureExactDataSize(256, 4, texture, format, {0, 0, 0}, {12, 16, 20});
TestWriteTextureExactDataSize(256, 4, texture, format, {0, 0, 0},
{testWidth, testHeight, 20});
// Write to the highest array layer
TestWriteTextureExactDataSize(256, 4, texture, format, {0, 0, 19}, {12, 16, 1});
TestWriteTextureExactDataSize(256, 4, texture, format, {0, 0, 19},
{testWidth, testHeight, 1});
// Write to array layers in the middle
TestWriteTextureExactDataSize(256, 4, texture, format, {0, 0, 1}, {12, 16, 18});
TestWriteTextureExactDataSize(256, 4, texture, format, {0, 0, 1},
{testWidth, testHeight, 18});
// Write touching the texture corners with a non-packed rowsPerImage
TestWriteTextureExactDataSize(256, 6, texture, format, {4, 4, 4}, {8, 12, 16});
TestWriteTextureExactDataSize(256, 6, texture, format, {blockWidth, blockHeight, 4},
{testWidth - blockWidth, testHeight - blockHeight, 16});
}
}

View File

@ -52,8 +52,10 @@ namespace {
wgpu::Queue queue;
private:
static constexpr uint32_t kWidth = 32;
static constexpr uint32_t kHeight = 32;
// Choose the LCM of all current compressed texture format texel dimensions as the
// dimensions of the default texture.
static constexpr uint32_t kWidth = 120;
static constexpr uint32_t kHeight = 120;
static constexpr uint32_t kDefaultDepth = 1;
static constexpr uint32_t kDefaultMipLevels = 1;
static constexpr uint32_t kDefaultSampleCount = 1;
@ -577,8 +579,16 @@ namespace {
TextureValidationTest::CreateDefaultTextureDescriptor();
descriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst |
wgpu::TextureUsage::TextureBinding;
descriptor.size.width = kWidth;
descriptor.size.height = kHeight;
return descriptor;
}
private:
// Choose the LCM of all current compressed texture format texel dimensions as the
// dimensions of the default texture.
static constexpr uint32_t kWidth = 120;
static constexpr uint32_t kHeight = 120;
};
// Test that only CopySrc, CopyDst and Sampled are accepted as usage in compressed formats.
@ -641,71 +651,51 @@ namespace {
}
}
// Test that it is invalid to use a number that is not a multiple of 4 (the compressed block
// width and height of all BC formats) as the width or height in BC formats.
TEST_F(CompressedTextureFormatsValidationTests, BCFormatsTextureSize) {
for (wgpu::TextureFormat format : utils::kBCFormats) {
// Test that it is invalid to use numbers for a texture's width/height that are not multiples
// of the compressed block sizes.
TEST_F(CompressedTextureFormatsValidationTests, TextureSize) {
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(format);
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(format);
// Test that the default size (120 x 120) is valid for all formats.
{
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
ASSERT_TRUE(descriptor.size.width % 4 == 0 && descriptor.size.height % 4 == 0);
ASSERT_TRUE(descriptor.size.width % blockWidth == 0 &&
descriptor.size.height % blockHeight == 0);
device.CreateTexture(&descriptor);
}
// Test that invalid width should cause an error. Note that if the block width of the
// compression type is even, we test that alignment to half the width is not sufficient.
{
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.size.width = 30;
descriptor.size.width =
blockWidth % 2 == 0 ? blockWidth - (blockWidth / 2) : blockWidth - 1;
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
}
// Test that invalid width should cause an error. Note that if the block height of the
// compression type is even, we test that alignment to half the height is not
// sufficient.
{
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.size.height = 30;
descriptor.size.height =
blockHeight % 2 == 0 ? blockHeight - (blockHeight / 2) : blockHeight - 1;
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
}
// Test a working dimension based on some constant multipliers to the dimensions.
{
constexpr uint32_t kWidthMultiplier = 3;
constexpr uint32_t kHeightMultiplier = 8;
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.size.width = 12;
descriptor.size.height = 32;
device.CreateTexture(&descriptor);
}
}
}
// Test that it is invalid to use a number that is not a multiple of 4 (the compressed block
// width and height of all ETC2 formats) as the width or height in ETC2 formats.
TEST_F(CompressedTextureFormatsValidationTests, ETC2FormatsTextureSize) {
for (wgpu::TextureFormat format : utils::kETC2Formats) {
{
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
ASSERT_TRUE(descriptor.size.width % 4 == 0 && descriptor.size.height % 4 == 0);
device.CreateTexture(&descriptor);
}
{
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.size.width = 30;
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
}
{
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.size.height = 30;
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
}
{
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.size.width = 12;
descriptor.size.height = 32;
descriptor.size.width = kWidthMultiplier * blockWidth;
descriptor.size.height = kHeightMultiplier * blockHeight;
device.CreateTexture(&descriptor);
}
}

View File

@ -83,7 +83,40 @@ namespace utils {
}
bool IsASTCTextureFormat(wgpu::TextureFormat textureFormat) {
return false;
switch (textureFormat) {
case wgpu::TextureFormat::ASTC4x4Unorm:
case wgpu::TextureFormat::ASTC4x4UnormSrgb:
case wgpu::TextureFormat::ASTC5x4Unorm:
case wgpu::TextureFormat::ASTC5x4UnormSrgb:
case wgpu::TextureFormat::ASTC5x5Unorm:
case wgpu::TextureFormat::ASTC5x5UnormSrgb:
case wgpu::TextureFormat::ASTC6x5Unorm:
case wgpu::TextureFormat::ASTC6x5UnormSrgb:
case wgpu::TextureFormat::ASTC6x6Unorm:
case wgpu::TextureFormat::ASTC6x6UnormSrgb:
case wgpu::TextureFormat::ASTC8x5Unorm:
case wgpu::TextureFormat::ASTC8x5UnormSrgb:
case wgpu::TextureFormat::ASTC8x6Unorm:
case wgpu::TextureFormat::ASTC8x6UnormSrgb:
case wgpu::TextureFormat::ASTC8x8Unorm:
case wgpu::TextureFormat::ASTC8x8UnormSrgb:
case wgpu::TextureFormat::ASTC10x5Unorm:
case wgpu::TextureFormat::ASTC10x5UnormSrgb:
case wgpu::TextureFormat::ASTC10x6Unorm:
case wgpu::TextureFormat::ASTC10x6UnormSrgb:
case wgpu::TextureFormat::ASTC10x8Unorm:
case wgpu::TextureFormat::ASTC10x8UnormSrgb:
case wgpu::TextureFormat::ASTC10x10Unorm:
case wgpu::TextureFormat::ASTC10x10UnormSrgb:
case wgpu::TextureFormat::ASTC12x10Unorm:
case wgpu::TextureFormat::ASTC12x10UnormSrgb:
case wgpu::TextureFormat::ASTC12x12Unorm:
case wgpu::TextureFormat::ASTC12x12UnormSrgb:
return true;
default:
return false;
}
}
uint32_t GetTexelBlockSizeInBytes(wgpu::TextureFormat textureFormat) {
@ -167,6 +200,36 @@ namespace utils {
case wgpu::TextureFormat::EACRG11Snorm:
return 16u;
case wgpu::TextureFormat::ASTC4x4Unorm:
case wgpu::TextureFormat::ASTC4x4UnormSrgb:
case wgpu::TextureFormat::ASTC5x4Unorm:
case wgpu::TextureFormat::ASTC5x4UnormSrgb:
case wgpu::TextureFormat::ASTC5x5Unorm:
case wgpu::TextureFormat::ASTC5x5UnormSrgb:
case wgpu::TextureFormat::ASTC6x5Unorm:
case wgpu::TextureFormat::ASTC6x5UnormSrgb:
case wgpu::TextureFormat::ASTC6x6Unorm:
case wgpu::TextureFormat::ASTC6x6UnormSrgb:
case wgpu::TextureFormat::ASTC8x5Unorm:
case wgpu::TextureFormat::ASTC8x5UnormSrgb:
case wgpu::TextureFormat::ASTC8x6Unorm:
case wgpu::TextureFormat::ASTC8x6UnormSrgb:
case wgpu::TextureFormat::ASTC8x8Unorm:
case wgpu::TextureFormat::ASTC8x8UnormSrgb:
case wgpu::TextureFormat::ASTC10x5Unorm:
case wgpu::TextureFormat::ASTC10x5UnormSrgb:
case wgpu::TextureFormat::ASTC10x6Unorm:
case wgpu::TextureFormat::ASTC10x6UnormSrgb:
case wgpu::TextureFormat::ASTC10x8Unorm:
case wgpu::TextureFormat::ASTC10x8UnormSrgb:
case wgpu::TextureFormat::ASTC10x10Unorm:
case wgpu::TextureFormat::ASTC10x10UnormSrgb:
case wgpu::TextureFormat::ASTC12x10Unorm:
case wgpu::TextureFormat::ASTC12x10UnormSrgb:
case wgpu::TextureFormat::ASTC12x12Unorm:
case wgpu::TextureFormat::ASTC12x12UnormSrgb:
return 16u;
case wgpu::TextureFormat::Depth24Plus:
case wgpu::TextureFormat::Depth24PlusStencil8:
@ -248,6 +311,41 @@ namespace utils {
case wgpu::TextureFormat::EACRG11Snorm:
return 4u;
case wgpu::TextureFormat::ASTC4x4Unorm:
case wgpu::TextureFormat::ASTC4x4UnormSrgb:
return 4u;
case wgpu::TextureFormat::ASTC5x4Unorm:
case wgpu::TextureFormat::ASTC5x4UnormSrgb:
case wgpu::TextureFormat::ASTC5x5Unorm:
case wgpu::TextureFormat::ASTC5x5UnormSrgb:
return 5u;
case wgpu::TextureFormat::ASTC6x5Unorm:
case wgpu::TextureFormat::ASTC6x5UnormSrgb:
case wgpu::TextureFormat::ASTC6x6Unorm:
case wgpu::TextureFormat::ASTC6x6UnormSrgb:
return 6u;
case wgpu::TextureFormat::ASTC8x5Unorm:
case wgpu::TextureFormat::ASTC8x5UnormSrgb:
case wgpu::TextureFormat::ASTC8x6Unorm:
case wgpu::TextureFormat::ASTC8x6UnormSrgb:
case wgpu::TextureFormat::ASTC8x8Unorm:
case wgpu::TextureFormat::ASTC8x8UnormSrgb:
return 8u;
case wgpu::TextureFormat::ASTC10x5Unorm:
case wgpu::TextureFormat::ASTC10x5UnormSrgb:
case wgpu::TextureFormat::ASTC10x6Unorm:
case wgpu::TextureFormat::ASTC10x6UnormSrgb:
case wgpu::TextureFormat::ASTC10x8Unorm:
case wgpu::TextureFormat::ASTC10x8UnormSrgb:
case wgpu::TextureFormat::ASTC10x10Unorm:
case wgpu::TextureFormat::ASTC10x10UnormSrgb:
return 10u;
case wgpu::TextureFormat::ASTC12x10Unorm:
case wgpu::TextureFormat::ASTC12x10UnormSrgb:
case wgpu::TextureFormat::ASTC12x12Unorm:
case wgpu::TextureFormat::ASTC12x12UnormSrgb:
return 12u;
// Block size of a multi-planar format depends on aspect.
case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
@ -326,6 +424,41 @@ namespace utils {
case wgpu::TextureFormat::EACRG11Snorm:
return 4u;
case wgpu::TextureFormat::ASTC4x4Unorm:
case wgpu::TextureFormat::ASTC4x4UnormSrgb:
case wgpu::TextureFormat::ASTC5x4Unorm:
case wgpu::TextureFormat::ASTC5x4UnormSrgb:
return 4u;
case wgpu::TextureFormat::ASTC5x5Unorm:
case wgpu::TextureFormat::ASTC5x5UnormSrgb:
case wgpu::TextureFormat::ASTC6x5Unorm:
case wgpu::TextureFormat::ASTC6x5UnormSrgb:
case wgpu::TextureFormat::ASTC8x5Unorm:
case wgpu::TextureFormat::ASTC8x5UnormSrgb:
case wgpu::TextureFormat::ASTC10x5Unorm:
case wgpu::TextureFormat::ASTC10x5UnormSrgb:
return 5u;
case wgpu::TextureFormat::ASTC6x6Unorm:
case wgpu::TextureFormat::ASTC6x6UnormSrgb:
case wgpu::TextureFormat::ASTC8x6Unorm:
case wgpu::TextureFormat::ASTC8x6UnormSrgb:
case wgpu::TextureFormat::ASTC10x6Unorm:
case wgpu::TextureFormat::ASTC10x6UnormSrgb:
return 6u;
case wgpu::TextureFormat::ASTC8x8Unorm:
case wgpu::TextureFormat::ASTC8x8UnormSrgb:
case wgpu::TextureFormat::ASTC10x8Unorm:
case wgpu::TextureFormat::ASTC10x8UnormSrgb:
return 8u;
case wgpu::TextureFormat::ASTC10x10Unorm:
case wgpu::TextureFormat::ASTC10x10UnormSrgb:
case wgpu::TextureFormat::ASTC12x10Unorm:
case wgpu::TextureFormat::ASTC12x10UnormSrgb:
return 10u;
case wgpu::TextureFormat::ASTC12x12Unorm:
case wgpu::TextureFormat::ASTC12x12UnormSrgb:
return 12u;
// Block size of a multi-planar format depends on aspect.
case wgpu::TextureFormat::R8BG8Biplanar420Unorm:

View File

@ -22,7 +22,7 @@
#include "common/Assert.h"
namespace utils {
static constexpr std::array<wgpu::TextureFormat, 63> kAllTextureFormats = {
static constexpr std::array<wgpu::TextureFormat, 91> kAllTextureFormats = {
wgpu::TextureFormat::R8Unorm,
wgpu::TextureFormat::R8Snorm,
wgpu::TextureFormat::R8Uint,
@ -85,7 +85,35 @@ namespace utils {
wgpu::TextureFormat::EACR11Unorm,
wgpu::TextureFormat::EACR11Snorm,
wgpu::TextureFormat::EACRG11Unorm,
wgpu::TextureFormat::EACRG11Snorm};
wgpu::TextureFormat::EACRG11Snorm,
wgpu::TextureFormat::ASTC4x4Unorm,
wgpu::TextureFormat::ASTC4x4UnormSrgb,
wgpu::TextureFormat::ASTC5x4Unorm,
wgpu::TextureFormat::ASTC5x4UnormSrgb,
wgpu::TextureFormat::ASTC5x5Unorm,
wgpu::TextureFormat::ASTC5x5UnormSrgb,
wgpu::TextureFormat::ASTC6x5Unorm,
wgpu::TextureFormat::ASTC6x5UnormSrgb,
wgpu::TextureFormat::ASTC6x6Unorm,
wgpu::TextureFormat::ASTC6x6UnormSrgb,
wgpu::TextureFormat::ASTC8x5Unorm,
wgpu::TextureFormat::ASTC8x5UnormSrgb,
wgpu::TextureFormat::ASTC8x6Unorm,
wgpu::TextureFormat::ASTC8x6UnormSrgb,
wgpu::TextureFormat::ASTC8x8Unorm,
wgpu::TextureFormat::ASTC8x8UnormSrgb,
wgpu::TextureFormat::ASTC10x5Unorm,
wgpu::TextureFormat::ASTC10x5UnormSrgb,
wgpu::TextureFormat::ASTC10x6Unorm,
wgpu::TextureFormat::ASTC10x6UnormSrgb,
wgpu::TextureFormat::ASTC10x8Unorm,
wgpu::TextureFormat::ASTC10x8UnormSrgb,
wgpu::TextureFormat::ASTC10x10Unorm,
wgpu::TextureFormat::ASTC10x10UnormSrgb,
wgpu::TextureFormat::ASTC12x10Unorm,
wgpu::TextureFormat::ASTC12x10UnormSrgb,
wgpu::TextureFormat::ASTC12x12Unorm,
wgpu::TextureFormat::ASTC12x12UnormSrgb};
static constexpr std::array<wgpu::TextureFormat, 14> kBCFormats = {
wgpu::TextureFormat::BC1RGBAUnorm, wgpu::TextureFormat::BC1RGBAUnormSrgb,
@ -103,10 +131,24 @@ namespace utils {
wgpu::TextureFormat::EACR11Unorm, wgpu::TextureFormat::EACR11Snorm,
wgpu::TextureFormat::EACRG11Unorm, wgpu::TextureFormat::EACRG11Snorm};
// TODO(crbug.com/dawn/955) Add formats once implemented.
static constexpr std::array<wgpu::TextureFormat, 0> kASTCFormats = {};
static constexpr std::array<wgpu::TextureFormat, 28> kASTCFormats = {
wgpu::TextureFormat::ASTC4x4Unorm, wgpu::TextureFormat::ASTC4x4UnormSrgb,
wgpu::TextureFormat::ASTC5x4Unorm, wgpu::TextureFormat::ASTC5x4UnormSrgb,
wgpu::TextureFormat::ASTC5x5Unorm, wgpu::TextureFormat::ASTC5x5UnormSrgb,
wgpu::TextureFormat::ASTC6x5Unorm, wgpu::TextureFormat::ASTC6x5UnormSrgb,
wgpu::TextureFormat::ASTC6x6Unorm, wgpu::TextureFormat::ASTC6x6UnormSrgb,
wgpu::TextureFormat::ASTC8x5Unorm, wgpu::TextureFormat::ASTC8x5UnormSrgb,
wgpu::TextureFormat::ASTC8x6Unorm, wgpu::TextureFormat::ASTC8x6UnormSrgb,
wgpu::TextureFormat::ASTC8x8Unorm, wgpu::TextureFormat::ASTC8x8UnormSrgb,
wgpu::TextureFormat::ASTC10x5Unorm, wgpu::TextureFormat::ASTC10x5UnormSrgb,
wgpu::TextureFormat::ASTC10x6Unorm, wgpu::TextureFormat::ASTC10x6UnormSrgb,
wgpu::TextureFormat::ASTC10x8Unorm, wgpu::TextureFormat::ASTC10x8UnormSrgb,
wgpu::TextureFormat::ASTC10x10Unorm, wgpu::TextureFormat::ASTC10x10UnormSrgb,
wgpu::TextureFormat::ASTC12x10Unorm, wgpu::TextureFormat::ASTC12x10UnormSrgb,
wgpu::TextureFormat::ASTC12x12Unorm, wgpu::TextureFormat::ASTC12x12UnormSrgb,
};
static constexpr std::array<wgpu::TextureFormat, 24> kCompressedFormats = {
static constexpr std::array<wgpu::TextureFormat, 52> kCompressedFormats = {
wgpu::TextureFormat::BC1RGBAUnorm, wgpu::TextureFormat::BC1RGBAUnormSrgb,
wgpu::TextureFormat::BC2RGBAUnorm, wgpu::TextureFormat::BC2RGBAUnormSrgb,
wgpu::TextureFormat::BC3RGBAUnorm, wgpu::TextureFormat::BC3RGBAUnormSrgb,
@ -118,7 +160,21 @@ namespace utils {
wgpu::TextureFormat::ETC2RGB8A1Unorm, wgpu::TextureFormat::ETC2RGB8A1UnormSrgb,
wgpu::TextureFormat::ETC2RGBA8Unorm, wgpu::TextureFormat::ETC2RGBA8UnormSrgb,
wgpu::TextureFormat::EACR11Unorm, wgpu::TextureFormat::EACR11Snorm,
wgpu::TextureFormat::EACRG11Unorm, wgpu::TextureFormat::EACRG11Snorm};
wgpu::TextureFormat::EACRG11Unorm, wgpu::TextureFormat::EACRG11Snorm,
wgpu::TextureFormat::ASTC4x4Unorm, wgpu::TextureFormat::ASTC4x4UnormSrgb,
wgpu::TextureFormat::ASTC5x4Unorm, wgpu::TextureFormat::ASTC5x4UnormSrgb,
wgpu::TextureFormat::ASTC5x5Unorm, wgpu::TextureFormat::ASTC5x5UnormSrgb,
wgpu::TextureFormat::ASTC6x5Unorm, wgpu::TextureFormat::ASTC6x5UnormSrgb,
wgpu::TextureFormat::ASTC6x6Unorm, wgpu::TextureFormat::ASTC6x6UnormSrgb,
wgpu::TextureFormat::ASTC8x5Unorm, wgpu::TextureFormat::ASTC8x5UnormSrgb,
wgpu::TextureFormat::ASTC8x6Unorm, wgpu::TextureFormat::ASTC8x6UnormSrgb,
wgpu::TextureFormat::ASTC8x8Unorm, wgpu::TextureFormat::ASTC8x8UnormSrgb,
wgpu::TextureFormat::ASTC10x5Unorm, wgpu::TextureFormat::ASTC10x5UnormSrgb,
wgpu::TextureFormat::ASTC10x6Unorm, wgpu::TextureFormat::ASTC10x6UnormSrgb,
wgpu::TextureFormat::ASTC10x8Unorm, wgpu::TextureFormat::ASTC10x8UnormSrgb,
wgpu::TextureFormat::ASTC10x10Unorm, wgpu::TextureFormat::ASTC10x10UnormSrgb,
wgpu::TextureFormat::ASTC12x10Unorm, wgpu::TextureFormat::ASTC12x10UnormSrgb,
wgpu::TextureFormat::ASTC12x12Unorm, wgpu::TextureFormat::ASTC12x12UnormSrgb};
static_assert(kCompressedFormats.size() ==
kBCFormats.size() + kETC2Formats.size() + kASTCFormats.size(),
"Number of compressed format must equal number of BC, ETC2, and ASTC formats.");