Test all formats used as readonly storage texture in StorageTextureTests

This patch changes all the tests related to read-only storage textures
in dawn_end2end_tests StorageTextureTests to make them test all the
texture formats that support being used as storage textures in WebGPU.

BUG=dawn:267
TEST=dawn_end2end_tests

Change-Id: I4d6ddbee638a787a2dcfc626bd4963a9b9043772
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/22640
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
Jiawei Shao 2020-06-05 01:02:57 +00:00 committed by Commit Bot service account
parent 783cd5a79c
commit 0a6a9d8692
5 changed files with 584 additions and 215 deletions

View File

@ -18,6 +18,7 @@
#include "common/Constants.h" #include "common/Constants.h"
#include "common/Math.h" #include "common/Math.h"
#include "utils/ComboRenderPipelineDescriptor.h" #include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/TextureFormatUtils.h"
#include "utils/WGPUHelpers.h" #include "utils/WGPUHelpers.h"
// The helper struct to configure the copies between buffers and textures. // The helper struct to configure the copies between buffers and textures.
@ -66,7 +67,7 @@ class CompressedTextureBCFormatTest : public DawnTest {
} else { } else {
bufferRowPitchInBytes = bufferRowPitchInBytes =
copyWidthInBlockAtLevel * copyWidthInBlockAtLevel *
CompressedFormatBlockSizeInBytes(copyConfig.textureDescriptor.format); utils::GetTexelBlockSizeInBytes(copyConfig.textureDescriptor.format);
} }
uint32_t uploadBufferSize = uint32_t uploadBufferSize =
copyConfig.bufferOffset + bufferRowPitchInBytes * copyHeightInBlockAtLevel; copyConfig.bufferOffset + bufferRowPitchInBytes * copyHeightInBlockAtLevel;
@ -259,31 +260,6 @@ class CompressedTextureBCFormatTest : public DawnTest {
return dstTexture; return dstTexture;
} }
// Return the BC block size in bytes.
static uint32_t CompressedFormatBlockSizeInBytes(wgpu::TextureFormat format) {
switch (format) {
case wgpu::TextureFormat::BC1RGBAUnorm:
case wgpu::TextureFormat::BC1RGBAUnormSrgb:
case wgpu::TextureFormat::BC4RSnorm:
case wgpu::TextureFormat::BC4RUnorm:
return 8;
case wgpu::TextureFormat::BC2RGBAUnorm:
case wgpu::TextureFormat::BC2RGBAUnormSrgb:
case wgpu::TextureFormat::BC3RGBAUnorm:
case wgpu::TextureFormat::BC3RGBAUnormSrgb:
case wgpu::TextureFormat::BC5RGSnorm:
case wgpu::TextureFormat::BC5RGUnorm:
case wgpu::TextureFormat::BC6HRGBSfloat:
case wgpu::TextureFormat::BC6HRGBUfloat:
case wgpu::TextureFormat::BC7RGBAUnorm:
case wgpu::TextureFormat::BC7RGBAUnormSrgb:
return 16;
default:
UNREACHABLE();
return 0;
}
}
// Return the pre-prepared one-block BC texture data. // Return the pre-prepared one-block BC texture data.
static std::vector<uint8_t> GetOneBlockBCFormatTextureData(wgpu::TextureFormat bcFormat) { static std::vector<uint8_t> GetOneBlockBCFormatTextureData(wgpu::TextureFormat bcFormat) {
switch (bcFormat) { switch (bcFormat) {
@ -841,7 +817,7 @@ TEST_P(CompressedTextureBCFormatTest, BufferOffsetAndExtentFitRowPitch) {
for (wgpu::TextureFormat format : kBCFormats) { for (wgpu::TextureFormat format : kBCFormats) {
config.textureDescriptor.format = format; config.textureDescriptor.format = format;
const uint32_t blockSizeInBytes = CompressedFormatBlockSizeInBytes(format); const uint32_t blockSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes; const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes;
config.bufferOffset = (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes; config.bufferOffset = (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes;
@ -877,7 +853,7 @@ TEST_P(CompressedTextureBCFormatTest, BufferOffsetExceedsSlicePitch) {
for (wgpu::TextureFormat format : kBCFormats) { for (wgpu::TextureFormat format : kBCFormats) {
config.textureDescriptor.format = format; config.textureDescriptor.format = format;
const uint32_t blockSizeInBytes = CompressedFormatBlockSizeInBytes(format); const uint32_t blockSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes; const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes;
config.bufferOffset = (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes + config.bufferOffset = (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes +
@ -911,7 +887,7 @@ TEST_P(CompressedTextureBCFormatTest, CopyWithBufferOffsetAndExtentExceedRowPitc
for (wgpu::TextureFormat format : kBCFormats) { for (wgpu::TextureFormat format : kBCFormats) {
config.textureDescriptor.format = format; config.textureDescriptor.format = format;
const uint32_t blockSizeInBytes = CompressedFormatBlockSizeInBytes(format); const uint32_t blockSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes; const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes;
config.bufferOffset = config.bufferOffset =
(blockCountPerRowPitch - blockCountPerRow + kExceedRowBlockCount) * blockSizeInBytes; (blockCountPerRowPitch - blockCountPerRow + kExceedRowBlockCount) * blockSizeInBytes;
@ -941,7 +917,7 @@ TEST_P(CompressedTextureBCFormatTest, RowPitchEqualToSlicePitch) {
for (wgpu::TextureFormat format : kBCFormats) { for (wgpu::TextureFormat format : kBCFormats) {
config.textureDescriptor.format = format; config.textureDescriptor.format = format;
const uint32_t blockSizeInBytes = CompressedFormatBlockSizeInBytes(format); const uint32_t blockSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes; const uint32_t blockCountPerRowPitch = config.bytesPerRowAlignment / blockSizeInBytes;
config.bufferOffset = config.bufferOffset =

View File

@ -16,17 +16,309 @@
#include "common/Assert.h" #include "common/Assert.h"
#include "common/Constants.h" #include "common/Constants.h"
#include "common/Math.h"
#include "utils/ComboRenderPipelineDescriptor.h" #include "utils/ComboRenderPipelineDescriptor.h"
#include "utils/TextureFormatUtils.h"
#include "utils/WGPUHelpers.h" #include "utils/WGPUHelpers.h"
class StorageTextureTests : public DawnTest { class StorageTextureTests : public DawnTest {
public: public:
// TODO(jiawei.shao@intel.com): support all formats that can be used in storage textures. static void FillExpectedData(void* pixelValuePtr,
static std::vector<uint32_t> GetExpectedData(uint32_t arrayLayerCount = 1) { wgpu::TextureFormat format,
constexpr size_t kDataCountPerLayer = kWidth * kHeight; uint32_t x,
std::vector<uint32_t> outputData(kDataCountPerLayer * arrayLayerCount); uint32_t y,
for (uint32_t i = 0; i < outputData.size(); ++i) { uint32_t arrayLayer) {
outputData[i] = i + 1u; const uint32_t pixelValue = 1 + x + kWidth * (y + kHeight * arrayLayer);
ASSERT(pixelValue <= 255u / 4);
switch (format) {
// 32-bit unsigned integer formats
case wgpu::TextureFormat::R32Uint: {
uint32_t* valuePtr = static_cast<uint32_t*>(pixelValuePtr);
*valuePtr = pixelValue;
break;
}
case wgpu::TextureFormat::RG32Uint: {
uint32_t* valuePtr = static_cast<uint32_t*>(pixelValuePtr);
valuePtr[0] = pixelValue;
valuePtr[1] = pixelValue * 2;
break;
}
case wgpu::TextureFormat::RGBA32Uint: {
uint32_t* valuePtr = static_cast<uint32_t*>(pixelValuePtr);
valuePtr[0] = pixelValue;
valuePtr[1] = pixelValue * 2;
valuePtr[2] = pixelValue * 3;
valuePtr[3] = pixelValue * 4;
break;
}
// 32-bit signed integer formats
case wgpu::TextureFormat::R32Sint: {
int32_t* valuePtr = static_cast<int32_t*>(pixelValuePtr);
*valuePtr = static_cast<int32_t>(pixelValue);
break;
}
case wgpu::TextureFormat::RG32Sint: {
int32_t* valuePtr = static_cast<int32_t*>(pixelValuePtr);
valuePtr[0] = static_cast<int32_t>(pixelValue);
valuePtr[1] = -static_cast<int32_t>(pixelValue);
break;
}
case wgpu::TextureFormat::RGBA32Sint: {
int32_t* valuePtr = static_cast<int32_t*>(pixelValuePtr);
valuePtr[0] = static_cast<int32_t>(pixelValue);
valuePtr[1] = -static_cast<int32_t>(pixelValue);
valuePtr[2] = static_cast<int32_t>(pixelValue * 2);
valuePtr[3] = -static_cast<int32_t>(pixelValue * 2);
break;
}
// 32-bit float formats
case wgpu::TextureFormat::R32Float: {
float_t* valuePtr = static_cast<float_t*>(pixelValuePtr);
*valuePtr = static_cast<float_t>(pixelValue * 1.1f);
break;
}
case wgpu::TextureFormat::RG32Float: {
float_t* valuePtr = static_cast<float_t*>(pixelValuePtr);
valuePtr[0] = static_cast<float_t>(pixelValue * 1.1f);
valuePtr[1] = -static_cast<float_t>(pixelValue * 2.2f);
break;
}
case wgpu::TextureFormat::RGBA32Float: {
float_t* valuePtr = static_cast<float_t*>(pixelValuePtr);
valuePtr[0] = static_cast<float_t>(pixelValue * 1.1f);
valuePtr[1] = -static_cast<float_t>(pixelValue * 1.1f);
valuePtr[2] = static_cast<float_t>(pixelValue * 2.2f);
valuePtr[3] = -static_cast<float_t>(pixelValue * 2.2f);
break;
}
// 16-bit (unsigned integer, signed integer and float) 4-component formats
case wgpu::TextureFormat::RGBA16Uint: {
uint16_t* valuePtr = static_cast<uint16_t*>(pixelValuePtr);
valuePtr[0] = static_cast<uint16_t>(pixelValue);
valuePtr[1] = static_cast<uint16_t>(pixelValue * 2);
valuePtr[2] = static_cast<uint16_t>(pixelValue * 3);
valuePtr[3] = static_cast<uint16_t>(pixelValue * 4);
break;
}
case wgpu::TextureFormat::RGBA16Sint: {
int16_t* valuePtr = static_cast<int16_t*>(pixelValuePtr);
valuePtr[0] = static_cast<int16_t>(pixelValue);
valuePtr[1] = -static_cast<int16_t>(pixelValue);
valuePtr[2] = static_cast<int16_t>(pixelValue * 2);
valuePtr[3] = -static_cast<int16_t>(pixelValue * 2);
break;
}
case wgpu::TextureFormat::RGBA16Float: {
uint16_t* valuePtr = static_cast<uint16_t*>(pixelValuePtr);
valuePtr[0] = Float32ToFloat16(static_cast<float_t>(pixelValue));
valuePtr[1] = Float32ToFloat16(-static_cast<float_t>(pixelValue));
valuePtr[2] = Float32ToFloat16(static_cast<float_t>(pixelValue * 2));
valuePtr[3] = Float32ToFloat16(-static_cast<float_t>(pixelValue * 2));
break;
}
// 8-bit (normalized/non-normalized signed/unsigned integer) 4-component formats
case wgpu::TextureFormat::RGBA8Unorm:
case wgpu::TextureFormat::RGBA8Uint: {
RGBA8* valuePtr = static_cast<RGBA8*>(pixelValuePtr);
*valuePtr = RGBA8(pixelValue, pixelValue * 2, pixelValue * 3, pixelValue * 4);
break;
}
case wgpu::TextureFormat::RGBA8Snorm:
case wgpu::TextureFormat::RGBA8Sint: {
int8_t* valuePtr = static_cast<int8_t*>(pixelValuePtr);
valuePtr[0] = static_cast<int8_t>(pixelValue);
valuePtr[1] = -static_cast<int8_t>(pixelValue);
valuePtr[2] = static_cast<int8_t>(pixelValue) * 2;
valuePtr[3] = -static_cast<int8_t>(pixelValue) * 2;
break;
}
default:
UNREACHABLE();
break;
}
}
std::string GetGLSLImageDeclaration(wgpu::TextureFormat format,
std::string accessQualifier,
bool is2DArray) {
std::ostringstream ostream;
ostream << "layout(set = 0, binding = 0, " << utils::GetGLSLImageFormatQualifier(format)
<< ") uniform " << accessQualifier << " "
<< utils::GetColorTextureComponentTypePrefix(format) << "image2D";
if (is2DArray) {
ostream << "Array";
}
ostream << " storageImage;";
return ostream.str();
}
const char* GetExpectedPixelValue(wgpu::TextureFormat format) {
switch (format) {
// non-normalized unsigned integer formats
case wgpu::TextureFormat::R32Uint:
return "uvec4(value, 0, 0, 1u)";
case wgpu::TextureFormat::RG32Uint:
return "uvec4(value, value * 2, 0, 1);";
case wgpu::TextureFormat::RGBA8Uint:
case wgpu::TextureFormat::RGBA16Uint:
case wgpu::TextureFormat::RGBA32Uint:
return "uvec4(value, value * 2, value * 3, value * 4);";
// non-normalized signed integer formats
case wgpu::TextureFormat::R32Sint:
return "ivec4(value, 0, 0, 1)";
case wgpu::TextureFormat::RG32Sint:
return "ivec4(value, -value, 0, 1);";
case wgpu::TextureFormat::RGBA8Sint:
case wgpu::TextureFormat::RGBA16Sint:
case wgpu::TextureFormat::RGBA32Sint:
return "ivec4(value, -value, value * 2, -value * 2);";
// float formats
case wgpu::TextureFormat::R32Float:
return "vec4(value * 1.1f, 0, 0, 1);";
case wgpu::TextureFormat::RG32Float:
return "vec4(value * 1.1f, -(value * 2.2f), 0, 1);";
case wgpu::TextureFormat::RGBA16Float:
return "vec4(value, -float(value), float(value * 2), -float(value * 2));";
case wgpu::TextureFormat::RGBA32Float:
return "vec4(value * 1.1f, -(value * 1.1f), value * 2.2f, -(value * 2.2f));";
// normalized signed/unsigned integer formats
case wgpu::TextureFormat::RGBA8Unorm:
return "vec4(value / 255.0, value / 255.0 * 2, value / 255.0 * 3, value / 255.0 * "
"4);";
case wgpu::TextureFormat::RGBA8Snorm:
return "vec4(value / 127.0, -(value / 127.0), (value * 2 / 127.0), -(value * 2 / "
"127.0));";
default:
UNREACHABLE();
break;
}
}
const char* GetGLSLComparisonFunction(wgpu::TextureFormat format) {
switch (format) {
// non-normalized unsigned integer formats
case wgpu::TextureFormat::R32Uint:
case wgpu::TextureFormat::RG32Uint:
case wgpu::TextureFormat::RGBA8Uint:
case wgpu::TextureFormat::RGBA16Uint:
case wgpu::TextureFormat::RGBA32Uint:
return R"(bool IsEqualTo(uvec4 pixel, uvec4 expected) {
return pixel == expected;
})";
// non-normalized signed integer formats
case wgpu::TextureFormat::R32Sint:
case wgpu::TextureFormat::RG32Sint:
case wgpu::TextureFormat::RGBA8Sint:
case wgpu::TextureFormat::RGBA16Sint:
case wgpu::TextureFormat::RGBA32Sint:
return R"(bool IsEqualTo(ivec4 pixel, ivec4 expected) {
return pixel == expected;
})";
// float formats
case wgpu::TextureFormat::R32Float:
case wgpu::TextureFormat::RG32Float:
case wgpu::TextureFormat::RGBA16Float:
case wgpu::TextureFormat::RGBA32Float:
return R"(bool IsEqualTo(vec4 pixel, vec4 expected) {
return pixel == expected;
})";
// normalized signed/unsigned integer formats
case wgpu::TextureFormat::RGBA8Unorm:
case wgpu::TextureFormat::RGBA8Snorm:
// On Windows Intel drivers the tests will fail if tolerance <= 0.00000001f.
return R"(bool IsEqualTo(vec4 pixel, vec4 expected) {
const float tolerance = 0.0000001f;
return all(lessThan(abs(pixel - expected), vec4(tolerance)));
})";
default:
UNREACHABLE();
break;
}
return "";
}
std::string CommonReadOnlyTestCode(wgpu::TextureFormat format, bool is2DArray = false) {
std::ostringstream ostream;
const char* prefix = utils::GetColorTextureComponentTypePrefix(format);
ostream << GetGLSLImageDeclaration(format, "readonly", is2DArray) << "\n"
<< GetGLSLComparisonFunction(format) << "bool doTest() {\n";
if (is2DArray) {
ostream << R"(ivec3 size = imageSize(storageImage);
const uint layerCount = size.z;)";
} else {
ostream << R"(ivec2 size = imageSize(storageImage);
const uint layerCount = 1;)";
}
ostream << R"(for (uint layer = 0; layer < layerCount; ++layer) {
for (uint y = 0; y < size.y; ++y) {
for (uint x = 0; x < size.x; ++x) {
uint value = 1 + x + size.x * (y + size.y * layer);
)"
<< prefix << "vec4 expected = " << GetExpectedPixelValue(format) << ";\n"
<< prefix << R"(vec4 pixel = imageLoad(storageImage, )";
if (is2DArray) {
ostream << "ivec3(x, y, layer));";
} else {
ostream << "ivec2(x, y));";
}
ostream << R"(
if (!IsEqualTo(pixel, expected)) {
return false;
}
}
}
}
return true;
})";
return ostream.str();
}
static std::vector<uint8_t> GetExpectedData(wgpu::TextureFormat format,
uint32_t arrayLayerCount = 1) {
const uint32_t texelSizeInBytes = utils::GetTexelBlockSizeInBytes(format);
std::vector<uint8_t> outputData(texelSizeInBytes * kWidth * kHeight * arrayLayerCount);
for (uint32_t i = 0; i < outputData.size() / texelSizeInBytes; ++i) {
uint8_t* pixelValuePtr = &outputData[i * texelSizeInBytes];
const uint32_t x = i % kWidth;
const uint32_t y = (i % (kWidth * kHeight)) / kWidth;
const uint32_t arrayLayer = i / (kWidth * kHeight);
FillExpectedData(pixelValuePtr, format, x, y, arrayLayer);
} }
return outputData; return outputData;
@ -55,24 +347,27 @@ class StorageTextureTests : public DawnTest {
return device.CreateBuffer(&descriptor); return device.CreateBuffer(&descriptor);
} }
// TODO(jiawei.shao@intel.com): support all formats that can be used in storage textures. wgpu::Texture CreateTextureWithTestData(const std::vector<uint8_t>& initialTextureData,
wgpu::Texture CreateTextureWithTestData(const std::vector<uint32_t>& initialTextureData, wgpu::TextureFormat format) {
uint32_t texelSize) { uint32_t texelSize = utils::GetTexelBlockSizeInBytes(format);
ASSERT(kWidth * texelSize <= kTextureBytesPerRowAlignment); ASSERT(kWidth * texelSize <= kTextureBytesPerRowAlignment);
const uint32_t bytesPerTextureRow = texelSize * kWidth;
const uint32_t arrayLayerCount = const uint32_t arrayLayerCount =
static_cast<uint32_t>(initialTextureData.size() / (kWidth * kHeight)); static_cast<uint32_t>(initialTextureData.size() / texelSize / (kWidth * kHeight));
const size_t uploadBufferSize = const size_t uploadBufferSize =
kTextureBytesPerRowAlignment * (kHeight * arrayLayerCount - 1) + kWidth * texelSize; kTextureBytesPerRowAlignment * (kHeight * arrayLayerCount - 1) +
kWidth * bytesPerTextureRow;
std::vector<uint32_t> uploadBufferData(uploadBufferSize / texelSize); std::vector<uint8_t> uploadBufferData(uploadBufferSize);
const size_t texelCountPerRow = kTextureBytesPerRowAlignment / texelSize;
for (uint32_t layer = 0; layer < arrayLayerCount; ++layer) { for (uint32_t layer = 0; layer < arrayLayerCount; ++layer) {
const size_t initialDataOffset = kWidth * kHeight * layer; const size_t initialDataOffset = bytesPerTextureRow * kHeight * layer;
for (size_t y = 0; y < kHeight; ++y) { for (size_t y = 0; y < kHeight; ++y) {
for (size_t x = 0; x < kWidth; ++x) { for (size_t x = 0; x < bytesPerTextureRow; ++x) {
uint32_t data = initialTextureData[initialDataOffset + kWidth * y + x]; uint8_t data =
size_t indexInUploadBuffer = (kHeight * layer + y) * texelCountPerRow + x; initialTextureData[initialDataOffset + bytesPerTextureRow * y + x];
size_t indexInUploadBuffer =
(kHeight * layer + y) * kTextureBytesPerRowAlignment + x;
uploadBufferData[indexInUploadBuffer] = data; uploadBufferData[indexInUploadBuffer] = data;
} }
} }
@ -81,9 +376,9 @@ class StorageTextureTests : public DawnTest {
utils::CreateBufferFromData(device, uploadBufferData.data(), uploadBufferSize, utils::CreateBufferFromData(device, uploadBufferData.data(), uploadBufferSize,
wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst); wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst);
wgpu::Texture outputTexture = CreateTexture( wgpu::Texture outputTexture =
wgpu::TextureFormat::R32Uint, wgpu::TextureUsage::Storage | wgpu::TextureUsage::CopyDst, CreateTexture(format, wgpu::TextureUsage::Storage | wgpu::TextureUsage::CopyDst, kWidth,
kWidth, kHeight, arrayLayerCount); kHeight, arrayLayerCount);
const wgpu::Extent3D copyExtent = {kWidth, kHeight, 1}; const wgpu::Extent3D copyExtent = {kWidth, kHeight, 1};
@ -235,10 +530,10 @@ class StorageTextureTests : public DawnTest {
void CheckOutputStorageTexture(wgpu::Texture writeonlyStorageTexture, void CheckOutputStorageTexture(wgpu::Texture writeonlyStorageTexture,
uint32_t texelSize, uint32_t texelSize,
const std::vector<uint32_t>& expectedData) { const std::vector<uint8_t>& expectedData) {
// Copy the content from the write-only storage texture to the result buffer. // Copy the content from the write-only storage texture to the result buffer.
const uint32_t arrayLayerCount = const uint32_t arrayLayerCount =
static_cast<uint32_t>(expectedData.size() / (kWidth * kHeight)); static_cast<uint32_t>(expectedData.size() / texelSize / (kWidth * kHeight));
wgpu::Buffer resultBuffer = CreateEmptyBufferForTextureCopy(texelSize, arrayLayerCount); wgpu::Buffer resultBuffer = CreateEmptyBufferForTextureCopy(texelSize, arrayLayerCount);
const wgpu::Extent3D copyExtent = {kWidth, kHeight, 1}; const wgpu::Extent3D copyExtent = {kWidth, kHeight, 1};
@ -266,9 +561,10 @@ class StorageTextureTests : public DawnTest {
for (size_t y = 0; y < kHeight; ++y) { for (size_t y = 0; y < kHeight; ++y) {
const size_t resultBufferOffset = const size_t resultBufferOffset =
kTextureBytesPerRowAlignment * (kHeight * layer + y); kTextureBytesPerRowAlignment * (kHeight * layer + y);
const size_t expectedDataOffset = kWidth * (kHeight * layer + y); const size_t expectedDataOffset = texelSize * kWidth * (kHeight * layer + y);
EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data() + expectedDataOffset, resultBuffer, EXPECT_BUFFER_U32_RANGE_EQ(
resultBufferOffset, kWidth); reinterpret_cast<const uint32_t*>(expectedData.data() + expectedDataOffset),
resultBuffer, resultBufferOffset, kWidth);
} }
} }
} }
@ -284,20 +580,6 @@ class StorageTextureTests : public DawnTest {
gl_PointSize = 1.0f; gl_PointSize = 1.0f;
})"; })";
const char* kCommonReadOnlyTestCode_uimage2D = R"(
bool doTest() {
for (uint y = 0; y < 4; ++y) {
for (uint x = 0; x < 4; ++x) {
uvec4 expected = uvec4(1u + x + y * 4u, 0, 0, 1u);
uvec4 pixel = imageLoad(srcImage, ivec2(x, y));
if (pixel != expected) {
return false;
}
}
}
return true;
})";
const char* kCommonWriteOnlyTestCode_uimage2D = R"( const char* kCommonWriteOnlyTestCode_uimage2D = R"(
#version 450 #version 450
layout(set = 0, binding = 0, r32ui) uniform writeonly uimage2D dstImage; layout(set = 0, binding = 0, r32ui) uniform writeonly uimage2D dstImage;
@ -348,22 +630,26 @@ TEST_P(StorageTextureTests, ReadonlyStorageTextureInComputeShader) {
// bug in spvc parser is fixed. // bug in spvc parser is fixed.
DAWN_SKIP_TEST_IF(IsD3D12() && IsSpvcParserBeingUsed()); DAWN_SKIP_TEST_IF(IsD3D12() && IsSpvcParserBeingUsed());
// Prepare the read-only storage texture and fill it with the expected data. for (wgpu::TextureFormat format : utils::kAllTextureFormats) {
// TODO(jiawei.shao@intel.com): test more texture formats. if (!utils::TextureFormatSupportsStorageTexture(format)) {
constexpr uint32_t kTexelSizeR32Uint = 4u; continue;
const std::vector<uint32_t> kInitialTextureData = GetExpectedData(); }
wgpu::Texture readonlyStorageTexture =
CreateTextureWithTestData(kInitialTextureData, kTexelSizeR32Uint);
// Create a compute shader that reads the pixels from the read-only storage texture and writes 1 // Prepare the read-only storage texture and fill it with the expected data.
// to DstBuffer if they all have to expected value. const std::vector<uint8_t> kInitialTextureData = GetExpectedData(format);
const std::string kComputeShader = std::string(R"( wgpu::Texture readonlyStorageTexture =
CreateTextureWithTestData(kInitialTextureData, format);
// Create a compute shader that reads the pixels from the read-only storage texture and
// writes 1 to DstBuffer if they all have to expected value.
std::ostringstream csStream;
csStream << R"(
#version 450 #version 450
layout (set = 0, binding = 0, r32ui) uniform readonly uimage2D srcImage;
layout(set = 0, binding = 1, std430) buffer DstBuffer { layout(set = 0, binding = 1, std430) buffer DstBuffer {
uint result; uint result;
} dstBuffer;)") + kCommonReadOnlyTestCode_uimage2D + } dstBuffer;
R"( )" << CommonReadOnlyTestCode(format)
<< R"(
void main() { void main() {
if (doTest()) { if (doTest()) {
dstBuffer.result = 1; dstBuffer.result = 1;
@ -372,7 +658,8 @@ TEST_P(StorageTextureTests, ReadonlyStorageTextureInComputeShader) {
} }
})"; })";
CheckResultInStorageBuffer(readonlyStorageTexture, kComputeShader); CheckResultInStorageBuffer(readonlyStorageTexture, csStream.str());
}
} }
// Test that read-only storage textures are supported in vertex shader. // Test that read-only storage textures are supported in vertex shader.
@ -383,20 +670,24 @@ TEST_P(StorageTextureTests, ReadonlyStorageTextureInVertexShader) {
// bug in spvc parser is fixed. // bug in spvc parser is fixed.
DAWN_SKIP_TEST_IF(IsSpvcParserBeingUsed()); DAWN_SKIP_TEST_IF(IsSpvcParserBeingUsed());
// Prepare the read-only storage texture and fill it with the expected data. for (wgpu::TextureFormat format : utils::kAllTextureFormats) {
// TODO(jiawei.shao@intel.com): test more texture formats if (!utils::TextureFormatSupportsStorageTexture(format)) {
constexpr uint32_t kTexelSizeR32Uint = 4u; continue;
const std::vector<uint32_t> kInitialTextureData = GetExpectedData(); }
wgpu::Texture readonlyStorageTexture =
CreateTextureWithTestData(kInitialTextureData, kTexelSizeR32Uint);
// Create a rendering pipeline that reads the pixels from the read-only storage texture and uses // Prepare the read-only storage texture and fill it with the expected data.
// green as the output color, otherwise uses red instead. const std::vector<uint8_t> kInitialTextureData = GetExpectedData(format);
const std::string kVertexShader = std::string(R"( wgpu::Texture readonlyStorageTexture =
CreateTextureWithTestData(kInitialTextureData, format);
// Create a rendering pipeline that reads the pixels from the read-only storage texture and
// uses green as the output color, otherwise uses red instead.
std::ostringstream vsStream;
vsStream << R"(
#version 450 #version 450
layout(set = 0, binding = 0, r32ui) uniform readonly uimage2D srcImage; layout(location = 0) out vec4 o_color;
layout(location = 0) out vec4 o_color;)") + )" << CommonReadOnlyTestCode(format)
kCommonReadOnlyTestCode_uimage2D + R"( << R"(
void main() { void main() {
gl_Position = vec4(0.f, 0.f, 0.f, 1.f); gl_Position = vec4(0.f, 0.f, 0.f, 1.f);
if (doTest()) { if (doTest()) {
@ -413,7 +704,8 @@ TEST_P(StorageTextureTests, ReadonlyStorageTextureInVertexShader) {
void main() { void main() {
fragColor = o_color; fragColor = o_color;
})"; })";
CheckDrawsGreen(kVertexShader.c_str(), kFragmentShader, readonlyStorageTexture); CheckDrawsGreen(vsStream.str().c_str(), kFragmentShader, readonlyStorageTexture);
}
} }
// Test that read-only storage textures are supported in fragment shader. // Test that read-only storage textures are supported in fragment shader.
@ -424,21 +716,25 @@ TEST_P(StorageTextureTests, ReadonlyStorageTextureInFragmentShader) {
// bug in spvc parser is fixed. // bug in spvc parser is fixed.
DAWN_SKIP_TEST_IF(IsSpvcParserBeingUsed()); DAWN_SKIP_TEST_IF(IsSpvcParserBeingUsed());
// Prepare the read-only storage texture and fill it with the expected data. for (wgpu::TextureFormat format : utils::kAllTextureFormats) {
// TODO(jiawei.shao@intel.com): test more texture formats if (!utils::TextureFormatSupportsStorageTexture(format)) {
constexpr uint32_t kTexelSizeR32Uint = 4u; continue;
const std::vector<uint32_t> kInitialTextureData = GetExpectedData(); }
wgpu::Texture readonlyStorageTexture =
CreateTextureWithTestData(kInitialTextureData, kTexelSizeR32Uint);
// Create a rendering pipeline that reads the pixels from the read-only storage texture and uses // Prepare the read-only storage texture and fill it with the expected data.
// green as the output color if the pixel value is expected, otherwise uses red instead. const std::vector<uint8_t> kInitialTextureData = GetExpectedData(format);
const char* kVertexShader = kSimpleVertexShader; wgpu::Texture readonlyStorageTexture =
const std::string kFragmentShader = std::string(R"( CreateTextureWithTestData(kInitialTextureData, format);
// Create a rendering pipeline that reads the pixels from the read-only storage texture and
// uses green as the output color if the pixel value is expected, otherwise uses red
// instead.
std::ostringstream fsStream;
fsStream << R"(
#version 450 #version 450
layout(set = 0, binding = 0, r32ui) uniform readonly uimage2D srcImage; layout(location = 0) out vec4 o_color;
layout(location = 0) out vec4 o_color;)") + )" << CommonReadOnlyTestCode(format)
kCommonReadOnlyTestCode_uimage2D + R"( << R"(
void main() { void main() {
if (doTest()) { if (doTest()) {
o_color = vec4(0.f, 1.f, 0.f, 1.f); o_color = vec4(0.f, 1.f, 0.f, 1.f);
@ -446,7 +742,8 @@ TEST_P(StorageTextureTests, ReadonlyStorageTextureInFragmentShader) {
o_color = vec4(1.f, 0.f, 0.f, 1.f); o_color = vec4(1.f, 0.f, 0.f, 1.f);
} }
})"; })";
CheckDrawsGreen(kVertexShader, kFragmentShader.c_str(), readonlyStorageTexture); CheckDrawsGreen(kSimpleVertexShader, fsStream.str().c_str(), readonlyStorageTexture);
}
} }
// Test that write-only storage textures are supported in compute shader. // Test that write-only storage textures are supported in compute shader.
@ -465,7 +762,8 @@ TEST_P(StorageTextureTests, WriteonlyStorageTextureInComputeShader) {
WriteIntoStorageTextureInComputePass(writeonlyStorageTexture, WriteIntoStorageTextureInComputePass(writeonlyStorageTexture,
kCommonWriteOnlyTestCode_uimage2D); kCommonWriteOnlyTestCode_uimage2D);
CheckOutputStorageTexture(writeonlyStorageTexture, kTexelSizeR32Uint, GetExpectedData()); CheckOutputStorageTexture(writeonlyStorageTexture, kTexelSizeR32Uint,
GetExpectedData(wgpu::TextureFormat::R32Uint));
} }
// Test that write-only storage textures are supported in fragment shader. // Test that write-only storage textures are supported in fragment shader.
@ -484,7 +782,8 @@ TEST_P(StorageTextureTests, WriteonlyStorageTextureInFragmentShader) {
WriteIntoStorageTextureInRenderPass(writeonlyStorageTexture, kSimpleVertexShader, WriteIntoStorageTextureInRenderPass(writeonlyStorageTexture, kSimpleVertexShader,
kCommonWriteOnlyTestCode_uimage2D); kCommonWriteOnlyTestCode_uimage2D);
CheckOutputStorageTexture(writeonlyStorageTexture, kTexelSizeR32Uint, GetExpectedData()); CheckOutputStorageTexture(writeonlyStorageTexture, kTexelSizeR32Uint,
GetExpectedData(wgpu::TextureFormat::R32Uint));
} }
// Verify 2D array read-only storage texture works correctly. // Verify 2D array read-only storage texture works correctly.
@ -497,34 +796,23 @@ TEST_P(StorageTextureTests, Readonly2DArrayStorageTexture) {
constexpr uint32_t kArrayLayerCount = 3u; constexpr uint32_t kArrayLayerCount = 3u;
constexpr uint32_t kTexelSizeR32Uint = 4u; constexpr wgpu::TextureFormat kTextureFormat = wgpu::TextureFormat::R32Uint;
const std::vector<uint32_t> initialTextureData = GetExpectedData(kArrayLayerCount);
const std::vector<uint8_t> initialTextureData =
GetExpectedData(kTextureFormat, kArrayLayerCount);
wgpu::Texture readonlyStorageTexture = wgpu::Texture readonlyStorageTexture =
CreateTextureWithTestData(initialTextureData, kTexelSizeR32Uint); CreateTextureWithTestData(initialTextureData, kTextureFormat);
// Create a compute shader that reads the pixels from the read-only storage texture and writes 1 // Create a compute shader that reads the pixels from the read-only storage texture and writes 1
// to DstBuffer if they all have to expected value. // to DstBuffer if they all have to expected value.
const char* kComputeShader = R"( std::ostringstream csStream;
csStream << R"(
#version 450 #version 450
layout (set = 0, binding = 0, r32ui) uniform readonly uimage2DArray srcImage;
layout (set = 0, binding = 1, std430) buffer DstBuffer { layout (set = 0, binding = 1, std430) buffer DstBuffer {
uint result; uint result;
} dstBuffer; } dstBuffer;
bool doTest() { )" << CommonReadOnlyTestCode(kTextureFormat, true)
ivec3 size = imageSize(srcImage); << R"(
for (uint layer = 0; layer < size.z; ++layer) {
for (uint y = 0; y < size.y; ++y) {
for (uint x = 0; x < size.x; ++x) {
uint expected = 1u + x + size.x * (y + size.y * layer);
uvec4 pixel = imageLoad(srcImage, ivec3(x, y, layer));
if (pixel != uvec4(expected, 0, 0, 1u)) {
return false;
}
}
}
}
return true;
}
void main() { void main() {
if (doTest()) { if (doTest()) {
dstBuffer.result = 1; dstBuffer.result = 1;
@ -533,7 +821,7 @@ TEST_P(StorageTextureTests, Readonly2DArrayStorageTexture) {
} }
})"; })";
CheckResultInStorageBuffer(readonlyStorageTexture, kComputeShader); CheckResultInStorageBuffer(readonlyStorageTexture, csStream.str());
} }
// Verify 2D array write-only storage texture works correctly. // Verify 2D array write-only storage texture works correctly.
@ -570,7 +858,7 @@ TEST_P(StorageTextureTests, Writeonly2DArrayStorageTexture) {
constexpr uint32_t kTexelSizeR32Uint = 4u; constexpr uint32_t kTexelSizeR32Uint = 4u;
CheckOutputStorageTexture(writeonlyStorageTexture, kTexelSizeR32Uint, CheckOutputStorageTexture(writeonlyStorageTexture, kTexelSizeR32Uint,
GetExpectedData(kArrayLayerCount)); GetExpectedData(wgpu::TextureFormat::R32Uint, kArrayLayerCount));
} }
DAWN_INSTANTIATE_TEST(StorageTextureTests, DAWN_INSTANTIATE_TEST(StorageTextureTests,
@ -581,10 +869,16 @@ DAWN_INSTANTIATE_TEST(StorageTextureTests,
class StorageTextureZeroInitTests : public StorageTextureTests { class StorageTextureZeroInitTests : public StorageTextureTests {
public: public:
static std::vector<uint32_t> GetExpectedData() { static std::vector<uint8_t> GetExpectedData() {
constexpr size_t kDataCount = kWidth * kHeight; constexpr wgpu::TextureFormat kTextureFormat = wgpu::TextureFormat::R32Uint;
std::vector<uint32_t> outputData(kDataCount, 0);
outputData[0] = 1u; const uint32_t texelSizeInBytes = utils::GetTexelBlockSizeInBytes(kTextureFormat);
const size_t kDataCount = texelSizeInBytes * kWidth * kHeight;
std::vector<uint8_t> outputData(kDataCount, 0);
uint32_t* outputDataPtr = reinterpret_cast<uint32_t*>(&outputData[0]);
*outputDataPtr = 1u;
return outputData; return outputData;
} }

View File

@ -20,78 +20,6 @@
class StorageTextureValidationTests : public ValidationTest { class StorageTextureValidationTests : public ValidationTest {
protected: protected:
static const char* GetGLSLImageFormatQualifier(wgpu::TextureFormat textureFormat) {
switch (textureFormat) {
case wgpu::TextureFormat::R8Unorm:
return "r8";
case wgpu::TextureFormat::R8Snorm:
return "r8_snorm";
case wgpu::TextureFormat::R8Uint:
return "r8ui";
case wgpu::TextureFormat::R8Sint:
return "r8i";
case wgpu::TextureFormat::R16Uint:
return "r16ui";
case wgpu::TextureFormat::R16Sint:
return "r16i";
case wgpu::TextureFormat::R16Float:
return "r16f";
case wgpu::TextureFormat::RG8Unorm:
return "rg8";
case wgpu::TextureFormat::RG8Snorm:
return "rg8_snorm";
case wgpu::TextureFormat::RG8Uint:
return "rg8ui";
case wgpu::TextureFormat::RG8Sint:
return "rg8i";
case wgpu::TextureFormat::R32Float:
return "r32f";
case wgpu::TextureFormat::R32Uint:
return "r32ui";
case wgpu::TextureFormat::R32Sint:
return "r32i";
case wgpu::TextureFormat::RG16Uint:
return "rg16ui";
case wgpu::TextureFormat::RG16Sint:
return "rg16i";
case wgpu::TextureFormat::RG16Float:
return "rg16f";
case wgpu::TextureFormat::RGBA8Unorm:
return "rgba8";
case wgpu::TextureFormat::RGBA8Snorm:
return "rgba8_snorm";
case wgpu::TextureFormat::RGBA8Uint:
return "rgba8ui";
case wgpu::TextureFormat::RGBA8Sint:
return "rgba8i";
case wgpu::TextureFormat::RGB10A2Unorm:
return "rgb10_a2";
case wgpu::TextureFormat::RG11B10Float:
return "r11f_g11f_b10f";
case wgpu::TextureFormat::RG32Float:
return "rg32f";
case wgpu::TextureFormat::RG32Uint:
return "rg32ui";
case wgpu::TextureFormat::RG32Sint:
return "rg32i";
case wgpu::TextureFormat::RGBA16Uint:
return "rgba16ui";
case wgpu::TextureFormat::RGBA16Sint:
return "rgba16i";
case wgpu::TextureFormat::RGBA16Float:
return "rgba16f";
case wgpu::TextureFormat::RGBA32Float:
return "rgba32f";
case wgpu::TextureFormat::RGBA32Uint:
return "rgba32ui";
case wgpu::TextureFormat::RGBA32Sint:
return "rgba32i";
default:
UNREACHABLE();
return "";
}
}
static const char* GetGLSLFloatImageTypeDeclaration(wgpu::TextureViewDimension dimension) { static const char* GetGLSLFloatImageTypeDeclaration(wgpu::TextureViewDimension dimension) {
switch (dimension) { switch (dimension) {
case wgpu::TextureViewDimension::e1D: case wgpu::TextureViewDimension::e1D:
@ -117,7 +45,7 @@ class StorageTextureValidationTests : public ValidationTest {
wgpu::BindingType storageTextureBindingType, wgpu::BindingType storageTextureBindingType,
wgpu::TextureFormat textureFormat, wgpu::TextureFormat textureFormat,
wgpu::TextureViewDimension textureViewDimension = wgpu::TextureViewDimension::e2D) { wgpu::TextureViewDimension textureViewDimension = wgpu::TextureViewDimension::e2D) {
const char* glslImageFormatQualifier = GetGLSLImageFormatQualifier(textureFormat); const char* glslImageFormatQualifier = utils::GetGLSLImageFormatQualifier(textureFormat);
const char* textureComponentTypePrefix = const char* textureComponentTypePrefix =
utils::GetColorTextureComponentTypePrefix(textureFormat); utils::GetColorTextureComponentTypePrefix(textureFormat);
return CreateComputeShaderWithStorageTexture( return CreateComputeShaderWithStorageTexture(

View File

@ -86,4 +86,172 @@ namespace utils {
return false; return false;
} }
} }
uint32_t GetTexelBlockSizeInBytes(wgpu::TextureFormat textureFormat) {
switch (textureFormat) {
case wgpu::TextureFormat::R8Unorm:
case wgpu::TextureFormat::R8Snorm:
case wgpu::TextureFormat::R8Uint:
case wgpu::TextureFormat::R8Sint:
return 1u;
case wgpu::TextureFormat::R16Uint:
case wgpu::TextureFormat::R16Sint:
case wgpu::TextureFormat::R16Float:
case wgpu::TextureFormat::RG8Unorm:
case wgpu::TextureFormat::RG8Snorm:
case wgpu::TextureFormat::RG8Uint:
case wgpu::TextureFormat::RG8Sint:
return 2u;
case wgpu::TextureFormat::R32Float:
case wgpu::TextureFormat::R32Uint:
case wgpu::TextureFormat::R32Sint:
case wgpu::TextureFormat::RG16Uint:
case wgpu::TextureFormat::RG16Sint:
case wgpu::TextureFormat::RG16Float:
case wgpu::TextureFormat::RGBA8Unorm:
case wgpu::TextureFormat::RGBA8UnormSrgb:
case wgpu::TextureFormat::RGBA8Snorm:
case wgpu::TextureFormat::RGBA8Uint:
case wgpu::TextureFormat::RGBA8Sint:
case wgpu::TextureFormat::BGRA8Unorm:
case wgpu::TextureFormat::BGRA8UnormSrgb:
case wgpu::TextureFormat::RGB10A2Unorm:
case wgpu::TextureFormat::RG11B10Float:
return 4u;
case wgpu::TextureFormat::RG32Float:
case wgpu::TextureFormat::RG32Uint:
case wgpu::TextureFormat::RG32Sint:
case wgpu::TextureFormat::RGBA16Uint:
case wgpu::TextureFormat::RGBA16Sint:
case wgpu::TextureFormat::RGBA16Float:
return 8u;
case wgpu::TextureFormat::RGBA32Float:
case wgpu::TextureFormat::RGBA32Uint:
case wgpu::TextureFormat::RGBA32Sint:
return 16u;
case wgpu::TextureFormat::BC1RGBAUnorm:
case wgpu::TextureFormat::BC1RGBAUnormSrgb:
case wgpu::TextureFormat::BC4RUnorm:
case wgpu::TextureFormat::BC4RSnorm:
return 8u;
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::BC6HRGBSfloat:
case wgpu::TextureFormat::BC7RGBAUnorm:
case wgpu::TextureFormat::BC7RGBAUnormSrgb:
return 16u;
case wgpu::TextureFormat::Depth32Float:
case wgpu::TextureFormat::Depth24Plus:
case wgpu::TextureFormat::Depth24PlusStencil8:
case wgpu::TextureFormat::Undefined:
default:
UNREACHABLE();
return 0u;
}
}
const char* GetGLSLImageFormatQualifier(wgpu::TextureFormat textureFormat) {
switch (textureFormat) {
case wgpu::TextureFormat::R8Unorm:
return "r8";
case wgpu::TextureFormat::R8Snorm:
return "r8_snorm";
case wgpu::TextureFormat::R8Uint:
return "r8ui";
case wgpu::TextureFormat::R8Sint:
return "r8i";
case wgpu::TextureFormat::R16Uint:
return "r16ui";
case wgpu::TextureFormat::R16Sint:
return "r16i";
case wgpu::TextureFormat::R16Float:
return "r16f";
case wgpu::TextureFormat::RG8Unorm:
return "rg8";
case wgpu::TextureFormat::RG8Snorm:
return "rg8_snorm";
case wgpu::TextureFormat::RG8Uint:
return "rg8ui";
case wgpu::TextureFormat::RG8Sint:
return "rg8i";
case wgpu::TextureFormat::R32Float:
return "r32f";
case wgpu::TextureFormat::R32Uint:
return "r32ui";
case wgpu::TextureFormat::R32Sint:
return "r32i";
case wgpu::TextureFormat::RG16Uint:
return "rg16ui";
case wgpu::TextureFormat::RG16Sint:
return "rg16i";
case wgpu::TextureFormat::RG16Float:
return "rg16f";
case wgpu::TextureFormat::RGBA8Unorm:
return "rgba8";
case wgpu::TextureFormat::RGBA8Snorm:
return "rgba8_snorm";
case wgpu::TextureFormat::RGBA8Uint:
return "rgba8ui";
case wgpu::TextureFormat::RGBA8Sint:
return "rgba8i";
case wgpu::TextureFormat::RGB10A2Unorm:
return "rgb10_a2";
case wgpu::TextureFormat::RG11B10Float:
return "r11f_g11f_b10f";
case wgpu::TextureFormat::RG32Float:
return "rg32f";
case wgpu::TextureFormat::RG32Uint:
return "rg32ui";
case wgpu::TextureFormat::RG32Sint:
return "rg32i";
case wgpu::TextureFormat::RGBA16Uint:
return "rgba16ui";
case wgpu::TextureFormat::RGBA16Sint:
return "rgba16i";
case wgpu::TextureFormat::RGBA16Float:
return "rgba16f";
case wgpu::TextureFormat::RGBA32Float:
return "rgba32f";
case wgpu::TextureFormat::RGBA32Uint:
return "rgba32ui";
case wgpu::TextureFormat::RGBA32Sint:
return "rgba32i";
case wgpu::TextureFormat::RGBA8UnormSrgb:
case wgpu::TextureFormat::BGRA8Unorm:
case wgpu::TextureFormat::BGRA8UnormSrgb:
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::BC6HRGBSfloat:
case wgpu::TextureFormat::BC7RGBAUnorm:
case wgpu::TextureFormat::BC7RGBAUnormSrgb:
case wgpu::TextureFormat::Depth32Float:
case wgpu::TextureFormat::Depth24Plus:
case wgpu::TextureFormat::Depth24PlusStencil8:
case wgpu::TextureFormat::Undefined:
UNREACHABLE();
return "";
}
}
} // namespace utils } // namespace utils

View File

@ -53,6 +53,9 @@ namespace utils {
const char* GetColorTextureComponentTypePrefix(wgpu::TextureFormat textureFormat); const char* GetColorTextureComponentTypePrefix(wgpu::TextureFormat textureFormat);
bool TextureFormatSupportsStorageTexture(wgpu::TextureFormat format); bool TextureFormatSupportsStorageTexture(wgpu::TextureFormat format);
uint32_t GetTexelBlockSizeInBytes(wgpu::TextureFormat textureFormat);
const char* GetGLSLImageFormatQualifier(wgpu::TextureFormat textureFormat);
} // namespace utils } // namespace utils
#endif #endif