Adds ETC2/EAC texture compression formats and Vulkan support for them

The end to end texture tests with the binary information for the textures are generated with a combination of the open source etc2comp tool and manual crafting of the data based on the specification in the Kronos Data Format Specifications (https://www.khronos.org/registry/DataFormat/specs/1.1/dataformat.1.1.pdf) for the compressed formats.

Also: Refactors end2end compressed texture tests and some utilities so that we can use parameterized tests for easier new format additions.

Bug: dawn:955
Change-Id: I91686f26a693a85cb076ef0eca3029111a64c50f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/62740
Commit-Queue: Loko Kung <lokokung@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Loko Kung 2021-08-31 00:15:45 +00:00 committed by Dawn LUCI CQ
parent 6bb3f6f216
commit c7226a7624
13 changed files with 857 additions and 546 deletions

View File

@ -1978,7 +1978,18 @@
{"value": 52, "name": "BC6H RGB float"},
{"value": 53, "name": "BC7 RGBA unorm"},
{"value": 54, "name": "BC7 RGBA unorm srgb"},
{"value": 55, "name": "R8 BG8 Biplanar 420 unorm"}
{"value": 55, "name": "R8 BG8 Biplanar 420 unorm"},
{"value": 56, "name": "ETC2 RGB8 unorm"},
{"value": 57, "name": "ETC2 RGB8 unorm srgb"},
{"value": 58, "name": "ETC2 RGB8A1 unorm"},
{"value": 59, "name": "ETC2 RGB8A1 unorm srgb"},
{"value": 60, "name": "ETC2 RGBA8 unorm"},
{"value": 61, "name": "ETC2 RGBA8 unorm srgb"},
{"value": 62, "name": "EAC R11 unorm"},
{"value": 63, "name": "EAC R11 snorm"},
{"value": 64, "name": "EAC RG11 unorm"},
{"value": 65, "name": "EAC RG11 snorm"}
]
},
"texture usage": {

View File

@ -352,6 +352,19 @@ namespace dawn_native {
AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnorm, 16, 4, 4, isBCFormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4);
// ETC2/EAC compressed formats
bool isETC2FormatSupported = device->IsExtensionEnabled(Extension::TextureCompressionETC2);
AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8Unorm, 8, 4, 4, isETC2FormatSupported, 3);
AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8UnormSrgb, 8, 4, 4, isETC2FormatSupported, 3);
AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8A1Unorm, 8, 4, 4, isETC2FormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8A1UnormSrgb, 8, 4, 4, isETC2FormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ETC2RGBA8Unorm, 16, 4, 4, isETC2FormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::ETC2RGBA8UnormSrgb, 16, 4, 4, isETC2FormatSupported, 4);
AddCompressedFormat(wgpu::TextureFormat::EACR11Unorm, 8, 4, 4, isETC2FormatSupported, 1);
AddCompressedFormat(wgpu::TextureFormat::EACR11Snorm, 8, 4, 4, isETC2FormatSupported, 1);
AddCompressedFormat(wgpu::TextureFormat::EACRG11Unorm, 16, 4, 4, isETC2FormatSupported, 2);
AddCompressedFormat(wgpu::TextureFormat::EACRG11Snorm, 16, 4, 4, isETC2FormatSupported, 2);
// 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 = 55;
static constexpr size_t kKnownFormatCount = 65;
struct Format;
using FormatTable = std::array<Format, kKnownFormatCount>;

View File

@ -203,6 +203,17 @@ namespace dawn_native { namespace d3d12 {
case wgpu::TextureFormat::BC7RGBAUnormSrgb:
return DXGI_FORMAT_BC7_TYPELESS;
case wgpu::TextureFormat::ETC2RGB8Unorm:
case wgpu::TextureFormat::ETC2RGB8UnormSrgb:
case wgpu::TextureFormat::ETC2RGB8A1Unorm:
case wgpu::TextureFormat::ETC2RGB8A1UnormSrgb:
case wgpu::TextureFormat::ETC2RGBA8Unorm:
case wgpu::TextureFormat::ETC2RGBA8UnormSrgb:
case wgpu::TextureFormat::EACR11Unorm:
case wgpu::TextureFormat::EACR11Snorm:
case wgpu::TextureFormat::EACRG11Unorm:
case wgpu::TextureFormat::EACRG11Snorm:
case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
case wgpu::TextureFormat::Stencil8:
case wgpu::TextureFormat::Undefined:
@ -330,6 +341,17 @@ namespace dawn_native { namespace d3d12 {
case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
return DXGI_FORMAT_NV12;
case wgpu::TextureFormat::ETC2RGB8Unorm:
case wgpu::TextureFormat::ETC2RGB8UnormSrgb:
case wgpu::TextureFormat::ETC2RGB8A1Unorm:
case wgpu::TextureFormat::ETC2RGB8A1UnormSrgb:
case wgpu::TextureFormat::ETC2RGBA8Unorm:
case wgpu::TextureFormat::ETC2RGBA8UnormSrgb:
case wgpu::TextureFormat::EACR11Unorm:
case wgpu::TextureFormat::EACR11Snorm:
case wgpu::TextureFormat::EACRG11Unorm:
case wgpu::TextureFormat::EACRG11Snorm:
case wgpu::TextureFormat::Stencil8:
case wgpu::TextureFormat::Undefined:
UNREACHABLE();

View File

@ -252,9 +252,38 @@ namespace dawn_native { namespace metal {
return MTLPixelFormatBC7_RGBAUnorm;
case wgpu::TextureFormat::BC7RGBAUnormSrgb:
return MTLPixelFormatBC7_RGBAUnorm_sRGB;
#else
case wgpu::TextureFormat::BC1RGBAUnorm:
case wgpu::TextureFormat::BC1RGBAUnormSrgb:
case wgpu::TextureFormat::BC2RGBAUnorm:
case wgpu::TextureFormat::BC2RGBAUnormSrgb:
case wgpu::TextureFormat::BC3RGBAUnorm:
case wgpu::TextureFormat::BC3RGBAUnormSrgb:
case wgpu::TextureFormat::BC4RSnorm:
case wgpu::TextureFormat::BC4RUnorm:
case wgpu::TextureFormat::BC5RGSnorm:
case wgpu::TextureFormat::BC5RGUnorm:
case wgpu::TextureFormat::BC6HRGBFloat:
case wgpu::TextureFormat::BC6HRGBUfloat:
case wgpu::TextureFormat::BC7RGBAUnorm:
case wgpu::TextureFormat::BC7RGBAUnormSrgb:
#endif
default:
case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
case wgpu::TextureFormat::ETC2RGB8Unorm:
case wgpu::TextureFormat::ETC2RGB8UnormSrgb:
case wgpu::TextureFormat::ETC2RGB8A1Unorm:
case wgpu::TextureFormat::ETC2RGB8A1UnormSrgb:
case wgpu::TextureFormat::ETC2RGBA8Unorm:
case wgpu::TextureFormat::ETC2RGBA8UnormSrgb:
case wgpu::TextureFormat::EACR11Unorm:
case wgpu::TextureFormat::EACR11Snorm:
case wgpu::TextureFormat::EACRG11Unorm:
case wgpu::TextureFormat::EACRG11Snorm:
case wgpu::TextureFormat::Stencil8:
case wgpu::TextureFormat::Undefined:
UNREACHABLE();
}
}

View File

@ -337,6 +337,28 @@ namespace dawn_native { namespace vulkan {
return VK_FORMAT_BC7_UNORM_BLOCK;
case wgpu::TextureFormat::BC7RGBAUnormSrgb:
return VK_FORMAT_BC7_SRGB_BLOCK;
case wgpu::TextureFormat::ETC2RGB8Unorm:
return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
case wgpu::TextureFormat::ETC2RGB8UnormSrgb:
return VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK;
case wgpu::TextureFormat::ETC2RGB8A1Unorm:
return VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK;
case wgpu::TextureFormat::ETC2RGB8A1UnormSrgb:
return VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK;
case wgpu::TextureFormat::ETC2RGBA8Unorm:
return VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK;
case wgpu::TextureFormat::ETC2RGBA8UnormSrgb:
return VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK;
case wgpu::TextureFormat::EACR11Unorm:
return VK_FORMAT_EAC_R11_UNORM_BLOCK;
case wgpu::TextureFormat::EACR11Snorm:
return VK_FORMAT_EAC_R11_SNORM_BLOCK;
case wgpu::TextureFormat::EACRG11Unorm:
return VK_FORMAT_EAC_R11G11_UNORM_BLOCK;
case wgpu::TextureFormat::EACRG11Snorm:
return VK_FORMAT_EAC_R11G11_SNORM_BLOCK;
case wgpu::TextureFormat::R8BG8Biplanar420Unorm:
case wgpu::TextureFormat::Stencil8:
case wgpu::TextureFormat::Undefined:

View File

@ -130,5 +130,11 @@ auto MakeParamGenerator(std::vector<BackendTestConfig>&& first,
::detail::GetAvailableAdapterTestParamsForBackends(first.data(), first.size()),
std::forward<std::initializer_list<Params>&&>(params)...);
}
template <typename Param, typename... Params>
auto MakeParamGenerator(std::vector<BackendTestConfig>&& first, std::vector<Params>&&... params) {
return ParamGenerator<Param, AdapterTestParam, Params...>(
::detail::GetAvailableAdapterTestParamsForBackends(first.data(), first.size()),
std::forward<std::vector<Params>&&>(params)...);
}
#endif // TESTS_PARAMGENERATOR_H_

File diff suppressed because it is too large Load Diff

View File

@ -2020,7 +2020,8 @@ class CopyCommandTest_CompressedTextureFormats : public CopyCommandTest {
protected:
WGPUDevice CreateTestDevice() override {
dawn_native::DeviceDescriptor descriptor;
descriptor.requiredExtensions = {"texture_compression_bc"};
descriptor.requiredExtensions = {"texture_compression_bc", "texture-compression-etc2",
"texture-compression-astc"};
return adapter.CreateDevice(&descriptor);
}
@ -2046,19 +2047,19 @@ TEST_F(CopyCommandTest_CompressedTextureFormats, BufferOffset) {
wgpu::Buffer buffer =
CreateBuffer(512, wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst);
for (wgpu::TextureFormat bcFormat : utils::kBCFormats) {
wgpu::Texture texture = Create2DTexture(bcFormat);
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format);
// Valid usages of BufferOffset in B2T and T2B copies with compressed texture formats.
{
uint32_t validBufferOffset = utils::GetTexelBlockSizeInBytes(bcFormat);
uint32_t validBufferOffset = utils::GetTexelBlockSizeInBytes(format);
TestBothTBCopies(utils::Expectation::Success, buffer, validBufferOffset, 256, 4,
texture, 0, {0, 0, 0}, {4, 4, 1});
}
// Failures on invalid bufferOffset.
{
uint32_t kInvalidBufferOffset = utils::GetTexelBlockSizeInBytes(bcFormat) / 2;
uint32_t kInvalidBufferOffset = utils::GetTexelBlockSizeInBytes(format) / 2;
TestBothTBCopies(utils::Expectation::Failure, buffer, kInvalidBufferOffset, 256, 4,
texture, 0, {0, 0, 0}, {4, 4, 1});
}
@ -2072,43 +2073,36 @@ 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;
// Failures on the BytesPerRow that is not large enough.
{
constexpr uint32_t kSmallBytesPerRow = 256;
for (wgpu::TextureFormat bcFormat : utils::kBCFormats) {
wgpu::Texture texture = Create2DTexture(bcFormat, 1, kTestWidth, kTestHeight);
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format, 1, kTestWidth, kTestHeight);
// 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.
{
for (wgpu::TextureFormat bcFormat : utils::kBCFormats) {
wgpu::Texture texture = Create2DTexture(bcFormat, 1, kTestWidth, kTestHeight);
// Test it is not valid to use a BytesPerRow that is not a multiple of 256.
{
uint32_t inValidBytesPerRow =
kTestWidth / 4 * utils::GetTexelBlockSizeInBytes(bcFormat);
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.
{
for (wgpu::TextureFormat bcFormat : utils::kBCFormats) {
wgpu::Texture texture = Create2DTexture(bcFormat, 1, kTestWidth, kTestHeight);
// Test the smallest valid BytesPerRow should work.
{
uint32_t smallestValidBytesPerRow =
Align(kTestWidth / 4 * utils::GetTexelBlockSizeInBytes(bcFormat), 256);
Align(kTestWidth / 4 * utils::GetTexelBlockSizeInBytes(format), 256);
TestBothTBCopies(utils::Expectation::Success, buffer, 0, smallestValidBytesPerRow,
4, texture, 0, {0, 0, 0}, {kTestWidth, 4, 1});
}
}
}
}
// rowsPerImage must be >= heightInBlocks.
@ -2116,8 +2110,8 @@ TEST_F(CopyCommandTest_CompressedTextureFormats, RowsPerImage) {
wgpu::Buffer buffer =
CreateBuffer(1024, wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst);
for (wgpu::TextureFormat bcFormat : utils::kBCFormats) {
wgpu::Texture texture = Create2DTexture(bcFormat);
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format);
// Valid usages of rowsPerImage in B2T and T2B copies with compressed texture formats.
{
@ -2147,9 +2141,9 @@ TEST_F(CopyCommandTest_CompressedTextureFormats, ImageOffset) {
wgpu::Buffer buffer =
CreateBuffer(512, wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst);
for (wgpu::TextureFormat bcFormat : utils::kBCFormats) {
wgpu::Texture texture = Create2DTexture(bcFormat);
wgpu::Texture texture2 = Create2DTexture(bcFormat);
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format);
wgpu::Texture texture2 = Create2DTexture(format);
constexpr wgpu::Origin3D kSmallestValidOrigin3D = {4, 4, 0};
@ -2194,9 +2188,9 @@ TEST_F(CopyCommandTest_CompressedTextureFormats, ImageExtent) {
constexpr uint32_t kTestWidth = 60;
constexpr uint32_t kTestHeight = 60;
for (wgpu::TextureFormat bcFormat : utils::kBCFormats) {
wgpu::Texture texture = Create2DTexture(bcFormat, kMipmapLevels, kTestWidth, kTestHeight);
wgpu::Texture texture2 = Create2DTexture(bcFormat, kMipmapLevels, kTestWidth, kTestHeight);
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format, kMipmapLevels, kTestWidth, kTestHeight);
wgpu::Texture texture2 = Create2DTexture(format, kMipmapLevels, kTestWidth, kTestHeight);
constexpr wgpu::Extent3D kSmallestValidExtent3D = {4, 4, 1};
@ -2273,20 +2267,20 @@ TEST_F(CopyCommandTest, CopyToMultipleArrayLayers) {
// Test copies between buffer and multiple array layers of a compressed texture
TEST_F(CopyCommandTest_CompressedTextureFormats, CopyToMultipleArrayLayers) {
for (wgpu::TextureFormat bcFormat : utils::kBCFormats) {
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = CopyCommandTest::Create2DTexture(
12, 16, 1, 20, bcFormat, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
12, 16, 1, 20, format, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
// Copy to all array layers
TestBothTBCopiesExactBufferSize(256, 4, texture, bcFormat, {0, 0, 0}, {12, 16, 20});
TestBothTBCopiesExactBufferSize(256, 4, texture, format, {0, 0, 0}, {12, 16, 20});
// Copy to the highest array layer
TestBothTBCopiesExactBufferSize(256, 4, texture, bcFormat, {0, 0, 19}, {12, 16, 1});
TestBothTBCopiesExactBufferSize(256, 4, texture, format, {0, 0, 19}, {12, 16, 1});
// Copy to array layers in the middle
TestBothTBCopiesExactBufferSize(256, 4, texture, bcFormat, {0, 0, 1}, {12, 16, 18});
TestBothTBCopiesExactBufferSize(256, 4, texture, format, {0, 0, 1}, {12, 16, 18});
// Copy touching the texture corners with a non-packed rowsPerImage
TestBothTBCopiesExactBufferSize(256, 6, texture, bcFormat, {4, 4, 4}, {8, 12, 16});
TestBothTBCopiesExactBufferSize(256, 6, texture, format, {4, 4, 4}, {8, 12, 16});
}
}

View File

@ -558,7 +558,8 @@ namespace {
protected:
WGPUDevice CreateTestDevice() override {
dawn_native::DeviceDescriptor descriptor;
descriptor.requiredExtensions = {"texture_compression_bc"};
descriptor.requiredExtensions = {"texture_compression_bc", "texture-compression-etc2",
"texture-compression-astc"};
return adapter.CreateDevice(&descriptor);
}
@ -591,18 +592,18 @@ namespace {
// 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 bcFormat : utils::kBCFormats) {
wgpu::Texture texture = Create2DTexture(bcFormat);
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format);
// Valid if aligned.
{
uint32_t kAlignedOffset = utils::GetTexelBlockSizeInBytes(bcFormat);
uint32_t kAlignedOffset = utils::GetTexelBlockSizeInBytes(format);
TestWriteTexture(1024, kAlignedOffset, 256, 4, texture, 0, {0, 0, 0}, {4, 16, 1});
}
// Still valid if not aligned.
{
uint32_t kUnalignedOffset = utils::GetTexelBlockSizeInBytes(bcFormat) - 1;
uint32_t kUnalignedOffset = utils::GetTexelBlockSizeInBytes(format) - 1;
TestWriteTexture(1024, kUnalignedOffset, 256, 4, texture, 0, {0, 0, 0}, {4, 16, 1});
}
}
@ -618,8 +619,8 @@ namespace {
// Failures on the BytesPerRow that is not large enough.
{
constexpr uint32_t kSmallBytesPerRow = 256;
for (wgpu::TextureFormat bcFormat : utils::kBCFormats) {
wgpu::Texture texture = Create2DTexture(bcFormat, 1, kTestWidth, kTestHeight);
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}));
}
@ -627,18 +628,18 @@ namespace {
// Test it is valid to use a BytesPerRow that is not a multiple of 256.
{
for (wgpu::TextureFormat bcFormat : utils::kBCFormats) {
wgpu::Texture texture = Create2DTexture(bcFormat, 1, kTestWidth, kTestHeight);
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format, 1, kTestWidth, kTestHeight);
uint32_t ValidBytesPerRow =
kTestWidth / 4 * utils::GetTexelBlockSizeInBytes(bcFormat);
kTestWidth / 4 * utils::GetTexelBlockSizeInBytes(format);
ASSERT_NE(0u, ValidBytesPerRow % 256);
TestWriteTexture(1024, 0, ValidBytesPerRow, 4, texture, 0, {0, 0, 0},
{kTestWidth, 4, 1});
}
}
for (wgpu::TextureFormat bcFormat : utils::kBCFormats) {
wgpu::Texture texture = Create2DTexture(bcFormat);
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format);
// Valid usage of bytesPerRow in WriteTexture with compressed texture formats.
{
@ -657,8 +658,8 @@ namespace {
// rowsPerImage must be >= heightInBlocks.
TEST_F(WriteTextureTest_CompressedTextureFormats, RowsPerImage) {
for (wgpu::TextureFormat bcFormat : utils::kBCFormats) {
wgpu::Texture texture = Create2DTexture(bcFormat);
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format);
// Valid usages of rowsPerImage in WriteTexture with compressed texture formats.
{
@ -684,9 +685,9 @@ namespace {
// Tests to verify that ImageOffset.x must be a multiple of the compressed texture block width
// and ImageOffset.y must be a multiple of the compressed texture block height
TEST_F(WriteTextureTest_CompressedTextureFormats, ImageOffset) {
for (wgpu::TextureFormat bcFormat : utils::kBCFormats) {
wgpu::Texture texture = Create2DTexture(bcFormat);
wgpu::Texture texture2 = Create2DTexture(bcFormat);
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format);
wgpu::Texture texture2 = Create2DTexture(format);
constexpr wgpu::Origin3D kSmallestValidOrigin3D = {4, 4, 0};
@ -718,11 +719,10 @@ namespace {
constexpr uint32_t kTestWidth = 60;
constexpr uint32_t kTestHeight = 60;
for (wgpu::TextureFormat bcFormat : utils::kBCFormats) {
wgpu::Texture texture =
Create2DTexture(bcFormat, kMipmapLevels, kTestWidth, kTestHeight);
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = Create2DTexture(format, kMipmapLevels, kTestWidth, kTestHeight);
wgpu::Texture texture2 =
Create2DTexture(bcFormat, kMipmapLevels, kTestWidth, kTestHeight);
Create2DTexture(format, kMipmapLevels, kTestWidth, kTestHeight);
constexpr wgpu::Extent3D kSmallestValidExtent3D = {4, 4, 1};
@ -761,22 +761,21 @@ namespace {
// Test writes to multiple array layers of a compressed texture
TEST_F(WriteTextureTest_CompressedTextureFormats, WriteToMultipleArrayLayers) {
for (wgpu::TextureFormat bcFormat : utils::kBCFormats) {
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::Texture texture = QueueWriteTextureValidationTest::Create2DTexture(
{12, 16, 20}, 1, bcFormat,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
{12, 16, 20}, 1, format, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc);
// Write to all array layers
TestWriteTextureExactDataSize(256, 4, texture, bcFormat, {0, 0, 0}, {12, 16, 20});
TestWriteTextureExactDataSize(256, 4, texture, format, {0, 0, 0}, {12, 16, 20});
// Write to the highest array layer
TestWriteTextureExactDataSize(256, 4, texture, bcFormat, {0, 0, 19}, {12, 16, 1});
TestWriteTextureExactDataSize(256, 4, texture, format, {0, 0, 19}, {12, 16, 1});
// Write to array layers in the middle
TestWriteTextureExactDataSize(256, 4, texture, bcFormat, {0, 0, 1}, {12, 16, 18});
TestWriteTextureExactDataSize(256, 4, texture, format, {0, 0, 1}, {12, 16, 18});
// Write touching the texture corners with a non-packed rowsPerImage
TestWriteTextureExactDataSize(256, 6, texture, bcFormat, {4, 4, 4}, {8, 12, 16});
TestWriteTextureExactDataSize(256, 6, texture, format, {4, 4, 4}, {8, 12, 16});
}
}

View File

@ -581,9 +581,69 @@ namespace {
}
};
// Test that only CopySrc, CopyDst and Sampled are accepted as usage in compressed formats.
TEST_F(CompressedTextureFormatsValidationTests, TextureUsage) {
wgpu::TextureUsage invalidUsages[] = {
wgpu::TextureUsage::RenderAttachment,
wgpu::TextureUsage::StorageBinding,
wgpu::TextureUsage::Present,
};
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
for (wgpu::TextureUsage usage : invalidUsages) {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.usage = usage;
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
}
}
}
// Test that using various MipLevelCount is allowed for compressed formats.
TEST_F(CompressedTextureFormatsValidationTests, MipLevelCount) {
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
for (uint32_t mipLevels : {1, 3, 6}) {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.mipLevelCount = mipLevels;
device.CreateTexture(&descriptor);
}
}
}
// Test that it is invalid to specify SampleCount>1 in compressed formats.
TEST_F(CompressedTextureFormatsValidationTests, SampleCount) {
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.sampleCount = 4;
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
}
}
// Test that it is allowed to create a 2D texture with depth>1 in compressed formats.
TEST_F(CompressedTextureFormatsValidationTests, 2DArrayTexture) {
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.size.depthOrArrayLayers = 6;
device.CreateTexture(&descriptor);
}
}
// Test that it is not allowed to create a 3D texture in compressed formats.
TEST_F(CompressedTextureFormatsValidationTests, 3DTexture) {
for (wgpu::TextureFormat format : utils::kCompressedFormats) {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.size.depthOrArrayLayers = 4;
descriptor.dimension = wgpu::TextureDimension::e3D;
ASSERT_DEVICE_ERROR(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 BC formats) as the width or height in BC formats.
TEST_F(CompressedTextureFormatsValidationTests, TextureSize) {
TEST_F(CompressedTextureFormatsValidationTests, BCFormatsTextureSize) {
for (wgpu::TextureFormat format : utils::kBCFormats) {
{
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
@ -595,14 +655,14 @@ namespace {
{
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.size.width = 31;
descriptor.size.width = 30;
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
}
{
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.size.height = 31;
descriptor.size.height = 30;
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
}
@ -616,79 +676,39 @@ namespace {
}
}
// Test that only CopySrc, CopyDst and Sampled are accepted as usage in compressed formats.
TEST_F(CompressedTextureFormatsValidationTests, TextureUsage) {
wgpu::TextureUsage invalidUsages[] = {
wgpu::TextureUsage::RenderAttachment,
wgpu::TextureUsage::StorageBinding,
wgpu::TextureUsage::Present,
};
for (wgpu::TextureFormat format : utils::kBCFormats) {
for (wgpu::TextureUsage usage : invalidUsages) {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.usage = usage;
ASSERT_DEVICE_ERROR(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) {
for (wgpu::TextureUsage usage : invalidUsages) {
{
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.usage = usage;
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
ASSERT_TRUE(descriptor.size.width % 4 == 0 && descriptor.size.height % 4 == 0);
device.CreateTexture(&descriptor);
}
}
for (wgpu::TextureFormat format : utils::kASTCFormats) {
for (wgpu::TextureUsage usage : invalidUsages) {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.usage = usage;
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
}
}
}
TEST_F(CompressedTextureFormatsValidationTests, MipLevelCount) {
for (wgpu::TextureFormat format : utils::kBCFormats) {
for (uint32_t mipLevels : {1, 3, 6}) {
{
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.mipLevelCount = mipLevels;
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;
device.CreateTexture(&descriptor);
}
}
}
// Test that it is invalid to specify SampleCount>1 in BC formats.
TEST_F(CompressedTextureFormatsValidationTests, SampleCount) {
for (wgpu::TextureFormat format : utils::kBCFormats) {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.sampleCount = 4;
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
}
}
// Test that it is allowed to create a 2D texture with depth>1 in BC formats.
TEST_F(CompressedTextureFormatsValidationTests, 2DArrayTexture) {
for (wgpu::TextureFormat format : utils::kBCFormats) {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.size.depthOrArrayLayers = 6;
device.CreateTexture(&descriptor);
}
}
// Test that it is not allowed to create a 3D texture in BC formats.
TEST_F(CompressedTextureFormatsValidationTests, 3DTexture) {
for (wgpu::TextureFormat format : utils::kBCFormats) {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();
descriptor.format = format;
descriptor.size.depthOrArrayLayers = 4;
descriptor.dimension = wgpu::TextureDimension::e3D;
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
}
}
} // namespace

View File

@ -40,6 +40,52 @@ namespace utils {
}
}
bool IsBCTextureFormat(wgpu::TextureFormat textureFormat) {
switch (textureFormat) {
case wgpu::TextureFormat::BC1RGBAUnorm:
case wgpu::TextureFormat::BC1RGBAUnormSrgb:
case wgpu::TextureFormat::BC4RUnorm:
case wgpu::TextureFormat::BC4RSnorm:
case wgpu::TextureFormat::BC2RGBAUnorm:
case wgpu::TextureFormat::BC2RGBAUnormSrgb:
case wgpu::TextureFormat::BC3RGBAUnorm:
case wgpu::TextureFormat::BC3RGBAUnormSrgb:
case wgpu::TextureFormat::BC5RGUnorm:
case wgpu::TextureFormat::BC5RGSnorm:
case wgpu::TextureFormat::BC6HRGBUfloat:
case wgpu::TextureFormat::BC6HRGBFloat:
case wgpu::TextureFormat::BC7RGBAUnorm:
case wgpu::TextureFormat::BC7RGBAUnormSrgb:
return true;
default:
return false;
}
}
bool IsETC2TextureFormat(wgpu::TextureFormat textureFormat) {
switch (textureFormat) {
case wgpu::TextureFormat::ETC2RGB8Unorm:
case wgpu::TextureFormat::ETC2RGB8UnormSrgb:
case wgpu::TextureFormat::ETC2RGB8A1Unorm:
case wgpu::TextureFormat::ETC2RGB8A1UnormSrgb:
case wgpu::TextureFormat::EACR11Unorm:
case wgpu::TextureFormat::EACR11Snorm:
case wgpu::TextureFormat::ETC2RGBA8Unorm:
case wgpu::TextureFormat::ETC2RGBA8UnormSrgb:
case wgpu::TextureFormat::EACRG11Unorm:
case wgpu::TextureFormat::EACRG11Snorm:
return true;
default:
return false;
}
}
bool IsASTCTextureFormat(wgpu::TextureFormat textureFormat) {
return false;
}
uint32_t GetTexelBlockSizeInBytes(wgpu::TextureFormat textureFormat) {
switch (textureFormat) {
case wgpu::TextureFormat::R8Unorm:
@ -107,6 +153,20 @@ namespace utils {
case wgpu::TextureFormat::BC7RGBAUnormSrgb:
return 16u;
case wgpu::TextureFormat::ETC2RGB8Unorm:
case wgpu::TextureFormat::ETC2RGB8UnormSrgb:
case wgpu::TextureFormat::ETC2RGB8A1Unorm:
case wgpu::TextureFormat::ETC2RGB8A1UnormSrgb:
case wgpu::TextureFormat::EACR11Unorm:
case wgpu::TextureFormat::EACR11Snorm:
return 8u;
case wgpu::TextureFormat::ETC2RGBA8Unorm:
case wgpu::TextureFormat::ETC2RGBA8UnormSrgb:
case wgpu::TextureFormat::EACRG11Unorm:
case wgpu::TextureFormat::EACRG11Snorm:
return 16u;
case wgpu::TextureFormat::Depth24Plus:
case wgpu::TextureFormat::Depth24PlusStencil8:
@ -176,6 +236,16 @@ namespace utils {
case wgpu::TextureFormat::BC6HRGBFloat:
case wgpu::TextureFormat::BC7RGBAUnorm:
case wgpu::TextureFormat::BC7RGBAUnormSrgb:
case wgpu::TextureFormat::ETC2RGB8Unorm:
case wgpu::TextureFormat::ETC2RGB8UnormSrgb:
case wgpu::TextureFormat::ETC2RGB8A1Unorm:
case wgpu::TextureFormat::ETC2RGB8A1UnormSrgb:
case wgpu::TextureFormat::ETC2RGBA8Unorm:
case wgpu::TextureFormat::ETC2RGBA8UnormSrgb:
case wgpu::TextureFormat::EACR11Unorm:
case wgpu::TextureFormat::EACR11Snorm:
case wgpu::TextureFormat::EACRG11Unorm:
case wgpu::TextureFormat::EACRG11Snorm:
return 4u;
// Block size of a multi-planar format depends on aspect.
@ -244,6 +314,16 @@ namespace utils {
case wgpu::TextureFormat::BC6HRGBFloat:
case wgpu::TextureFormat::BC7RGBAUnorm:
case wgpu::TextureFormat::BC7RGBAUnormSrgb:
case wgpu::TextureFormat::ETC2RGB8Unorm:
case wgpu::TextureFormat::ETC2RGB8UnormSrgb:
case wgpu::TextureFormat::ETC2RGB8A1Unorm:
case wgpu::TextureFormat::ETC2RGB8A1UnormSrgb:
case wgpu::TextureFormat::ETC2RGBA8Unorm:
case wgpu::TextureFormat::ETC2RGBA8UnormSrgb:
case wgpu::TextureFormat::EACR11Unorm:
case wgpu::TextureFormat::EACR11Snorm:
case wgpu::TextureFormat::EACRG11Unorm:
case wgpu::TextureFormat::EACRG11Snorm:
return 4u;
// Block size of a multi-planar format depends on aspect.

View File

@ -22,7 +22,7 @@
#include "common/Assert.h"
namespace utils {
static constexpr std::array<wgpu::TextureFormat, 53> kAllTextureFormats = {
static constexpr std::array<wgpu::TextureFormat, 63> kAllTextureFormats = {
wgpu::TextureFormat::R8Unorm,
wgpu::TextureFormat::R8Snorm,
wgpu::TextureFormat::R8Uint,
@ -76,7 +76,16 @@ namespace utils {
wgpu::TextureFormat::BC6HRGBFloat,
wgpu::TextureFormat::BC7RGBAUnorm,
wgpu::TextureFormat::BC7RGBAUnormSrgb,
};
wgpu::TextureFormat::ETC2RGB8Unorm,
wgpu::TextureFormat::ETC2RGB8UnormSrgb,
wgpu::TextureFormat::ETC2RGB8A1Unorm,
wgpu::TextureFormat::ETC2RGB8A1UnormSrgb,
wgpu::TextureFormat::ETC2RGBA8Unorm,
wgpu::TextureFormat::ETC2RGBA8UnormSrgb,
wgpu::TextureFormat::EACR11Unorm,
wgpu::TextureFormat::EACR11Snorm,
wgpu::TextureFormat::EACRG11Unorm,
wgpu::TextureFormat::EACRG11Snorm};
static constexpr std::array<wgpu::TextureFormat, 14> kBCFormats = {
wgpu::TextureFormat::BC1RGBAUnorm, wgpu::TextureFormat::BC1RGBAUnormSrgb,
@ -87,12 +96,39 @@ namespace utils {
wgpu::TextureFormat::BC6HRGBUfloat, wgpu::TextureFormat::BC6HRGBFloat,
wgpu::TextureFormat::BC7RGBAUnorm, wgpu::TextureFormat::BC7RGBAUnormSrgb};
static constexpr std::array<wgpu::TextureFormat, 10> kETC2Formats = {
wgpu::TextureFormat::ETC2RGB8Unorm, wgpu::TextureFormat::ETC2RGB8UnormSrgb,
wgpu::TextureFormat::ETC2RGB8A1Unorm, wgpu::TextureFormat::ETC2RGB8A1UnormSrgb,
wgpu::TextureFormat::ETC2RGBA8Unorm, wgpu::TextureFormat::ETC2RGBA8UnormSrgb,
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> kETC2Formats = {};
static constexpr std::array<wgpu::TextureFormat, 0> kASTCFormats = {};
static constexpr std::array<wgpu::TextureFormat, 24> kCompressedFormats = {
wgpu::TextureFormat::BC1RGBAUnorm, wgpu::TextureFormat::BC1RGBAUnormSrgb,
wgpu::TextureFormat::BC2RGBAUnorm, wgpu::TextureFormat::BC2RGBAUnormSrgb,
wgpu::TextureFormat::BC3RGBAUnorm, wgpu::TextureFormat::BC3RGBAUnormSrgb,
wgpu::TextureFormat::BC4RUnorm, wgpu::TextureFormat::BC4RSnorm,
wgpu::TextureFormat::BC5RGUnorm, wgpu::TextureFormat::BC5RGSnorm,
wgpu::TextureFormat::BC6HRGBUfloat, wgpu::TextureFormat::BC6HRGBFloat,
wgpu::TextureFormat::BC7RGBAUnorm, wgpu::TextureFormat::BC7RGBAUnormSrgb,
wgpu::TextureFormat::ETC2RGB8Unorm, wgpu::TextureFormat::ETC2RGB8UnormSrgb,
wgpu::TextureFormat::ETC2RGB8A1Unorm, wgpu::TextureFormat::ETC2RGB8A1UnormSrgb,
wgpu::TextureFormat::ETC2RGBA8Unorm, wgpu::TextureFormat::ETC2RGBA8UnormSrgb,
wgpu::TextureFormat::EACR11Unorm, wgpu::TextureFormat::EACR11Snorm,
wgpu::TextureFormat::EACRG11Unorm, wgpu::TextureFormat::EACRG11Snorm};
static_assert(kCompressedFormats.size() ==
kBCFormats.size() + kETC2Formats.size() + kASTCFormats.size(),
"Number of compressed format must equal number of BC, ETC2, and ASTC formats.");
bool TextureFormatSupportsStorageTexture(wgpu::TextureFormat format);
bool IsBCTextureFormat(wgpu::TextureFormat textureFormat);
bool IsETC2TextureFormat(wgpu::TextureFormat textureFormat);
bool IsASTCTextureFormat(wgpu::TextureFormat textureFormat);
uint32_t GetTexelBlockSizeInBytes(wgpu::TextureFormat textureFormat);
uint32_t GetTextureFormatBlockWidth(wgpu::TextureFormat textureFormat);
uint32_t GetTextureFormatBlockHeight(wgpu::TextureFormat textureFormat);