Add checks to TextureUsage::Storage
This patch adds validations to the texture usage "Storage" when
creating a texture.
1. "Storage" usage cannot be used when SampleCount > 1
2. "Storage" usage can only be used with some texture formats. The
list of the formats can be found through the following link:
https://github.com/gpuweb/gpuweb/issues/513
BUG=dawn:267
TEST=dawn_unittests
Change-Id: Ifc7296d966ac0c600433948a63c3dd6a436c8d8b
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/15040
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
diff --git a/src/dawn_native/Format.cpp b/src/dawn_native/Format.cpp
index c553784..d4c0e16 100644
--- a/src/dawn_native/Format.cpp
+++ b/src/dawn_native/Format.cpp
@@ -118,12 +118,14 @@
};
auto AddColorFormat = [&AddFormat](wgpu::TextureFormat format, bool renderable,
- uint32_t byteSize, Type type) {
+ bool supportsStorageUsage, uint32_t byteSize,
+ Type type) {
Format internalFormat;
internalFormat.format = format;
internalFormat.isRenderable = renderable;
internalFormat.isCompressed = false;
internalFormat.isSupported = true;
+ internalFormat.supportsStorageUsage = supportsStorageUsage;
internalFormat.aspect = Aspect::Color;
internalFormat.type = type;
internalFormat.blockByteSize = byteSize;
@@ -139,6 +141,7 @@
internalFormat.isRenderable = true;
internalFormat.isCompressed = false;
internalFormat.isSupported = true;
+ internalFormat.supportsStorageUsage = false;
internalFormat.aspect = aspect;
internalFormat.type = Type::Other;
internalFormat.blockByteSize = byteSize;
@@ -154,6 +157,7 @@
internalFormat.isRenderable = false;
internalFormat.isCompressed = true;
internalFormat.isSupported = isSupported;
+ internalFormat.supportsStorageUsage = false;
internalFormat.aspect = Aspect::Color;
internalFormat.type = Type::Float;
internalFormat.blockByteSize = byteSize;
@@ -165,50 +169,50 @@
// clang-format off
// 1 byte color formats
- AddColorFormat(wgpu::TextureFormat::R8Unorm, true, 1, Type::Float);
- AddColorFormat(wgpu::TextureFormat::R8Snorm, false, 1, Type::Float);
- AddColorFormat(wgpu::TextureFormat::R8Uint, true, 1, Type::Uint);
- AddColorFormat(wgpu::TextureFormat::R8Sint, true, 1, Type::Sint);
+ AddColorFormat(wgpu::TextureFormat::R8Unorm, true, false, 1, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::R8Snorm, false, false, 1, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::R8Uint, true, false, 1, Type::Uint);
+ AddColorFormat(wgpu::TextureFormat::R8Sint, true, false, 1, Type::Sint);
// 2 bytes color formats
- AddColorFormat(wgpu::TextureFormat::R16Uint, true, 2, Type::Uint);
- AddColorFormat(wgpu::TextureFormat::R16Sint, true, 2, Type::Sint);
- AddColorFormat(wgpu::TextureFormat::R16Float, true, 2, Type::Float);
- AddColorFormat(wgpu::TextureFormat::RG8Unorm, true, 2, Type::Float);
- AddColorFormat(wgpu::TextureFormat::RG8Snorm, false, 2, Type::Float);
- AddColorFormat(wgpu::TextureFormat::RG8Uint, true, 2, Type::Uint);
- AddColorFormat(wgpu::TextureFormat::RG8Sint, true, 2, Type::Sint);
+ AddColorFormat(wgpu::TextureFormat::R16Uint, true, false, 2, Type::Uint);
+ AddColorFormat(wgpu::TextureFormat::R16Sint, true, false, 2, Type::Sint);
+ AddColorFormat(wgpu::TextureFormat::R16Float, true, false, 2, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::RG8Unorm, true, false, 2, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::RG8Snorm, false, false, 2, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::RG8Uint, true, false, 2, Type::Uint);
+ AddColorFormat(wgpu::TextureFormat::RG8Sint, true, false, 2, Type::Sint);
// 4 bytes color formats
- AddColorFormat(wgpu::TextureFormat::R32Uint, true, 4, Type::Uint);
- AddColorFormat(wgpu::TextureFormat::R32Sint, true, 4, Type::Sint);
- AddColorFormat(wgpu::TextureFormat::R32Float, true, 4, Type::Float);
- AddColorFormat(wgpu::TextureFormat::RG16Uint, true, 4, Type::Uint);
- AddColorFormat(wgpu::TextureFormat::RG16Sint, true, 4, Type::Sint);
- AddColorFormat(wgpu::TextureFormat::RG16Float, true, 4, Type::Float);
- AddColorFormat(wgpu::TextureFormat::RGBA8Unorm, true, 4, Type::Float);
- AddColorFormat(wgpu::TextureFormat::RGBA8UnormSrgb, true, 4, Type::Float);
- AddColorFormat(wgpu::TextureFormat::RGBA8Snorm, false, 4, Type::Float);
- AddColorFormat(wgpu::TextureFormat::RGBA8Uint, true, 4, Type::Uint);
- AddColorFormat(wgpu::TextureFormat::RGBA8Sint, true, 4, Type::Sint);
- AddColorFormat(wgpu::TextureFormat::BGRA8Unorm, true, 4, Type::Float);
- AddColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, true, 4, Type::Float);
- AddColorFormat(wgpu::TextureFormat::RGB10A2Unorm, true, 4, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::R32Uint, true, true, 4, Type::Uint);
+ AddColorFormat(wgpu::TextureFormat::R32Sint, true, true, 4, Type::Sint);
+ AddColorFormat(wgpu::TextureFormat::R32Float, true, true, 4, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::RG16Uint, true, false, 4, Type::Uint);
+ AddColorFormat(wgpu::TextureFormat::RG16Sint, true, false, 4, Type::Sint);
+ AddColorFormat(wgpu::TextureFormat::RG16Float, true, false, 4, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::RGBA8Unorm, true, true, 4, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::RGBA8UnormSrgb, true, false, 4, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::RGBA8Snorm, false, true, 4, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::RGBA8Uint, true, true, 4, Type::Uint);
+ AddColorFormat(wgpu::TextureFormat::RGBA8Sint, true, true, 4, Type::Sint);
+ AddColorFormat(wgpu::TextureFormat::BGRA8Unorm, true, false, 4, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, true, false, 4, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::RGB10A2Unorm, true, false, 4, Type::Float);
- AddColorFormat(wgpu::TextureFormat::RG11B10Float, false, 4, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::RG11B10Float, false, false, 4, Type::Float);
// 8 bytes color formats
- AddColorFormat(wgpu::TextureFormat::RG32Uint, true, 8, Type::Uint);
- AddColorFormat(wgpu::TextureFormat::RG32Sint, true, 8, Type::Sint);
- AddColorFormat(wgpu::TextureFormat::RG32Float, true, 8, Type::Float);
- AddColorFormat(wgpu::TextureFormat::RGBA16Uint, true, 8, Type::Uint);
- AddColorFormat(wgpu::TextureFormat::RGBA16Sint, true, 8, Type::Sint);
- AddColorFormat(wgpu::TextureFormat::RGBA16Float, true, 8, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::RG32Uint, true, true, 8, Type::Uint);
+ AddColorFormat(wgpu::TextureFormat::RG32Sint, true, true, 8, Type::Sint);
+ AddColorFormat(wgpu::TextureFormat::RG32Float, true, true, 8, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::RGBA16Uint, true, true, 8, Type::Uint);
+ AddColorFormat(wgpu::TextureFormat::RGBA16Sint, true, true, 8, Type::Sint);
+ AddColorFormat(wgpu::TextureFormat::RGBA16Float, true, true, 8, Type::Float);
// 16 bytes color formats
- AddColorFormat(wgpu::TextureFormat::RGBA32Uint, true, 16, Type::Uint);
- AddColorFormat(wgpu::TextureFormat::RGBA32Sint, true, 16, Type::Sint);
- AddColorFormat(wgpu::TextureFormat::RGBA32Float, true, 16, Type::Float);
+ AddColorFormat(wgpu::TextureFormat::RGBA32Uint, true, true, 16, Type::Uint);
+ AddColorFormat(wgpu::TextureFormat::RGBA32Sint, true, true, 16, Type::Sint);
+ AddColorFormat(wgpu::TextureFormat::RGBA32Float, true, true, 16, Type::Float);
// Depth stencil formats
AddDepthStencilFormat(wgpu::TextureFormat::Depth32Float, Aspect::Depth, 4);
diff --git a/src/dawn_native/Format.h b/src/dawn_native/Format.h
index f1e4fbb..3d2c48a 100644
--- a/src/dawn_native/Format.h
+++ b/src/dawn_native/Format.h
@@ -50,6 +50,7 @@
bool isCompressed;
// A format can be known but not supported because it is part of a disabled extension.
bool isSupported;
+ bool supportsStorageUsage;
Aspect aspect;
Type type;
diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp
index e1b70b2..7b264c1 100644
--- a/src/dawn_native/Texture.cpp
+++ b/src/dawn_native/Texture.cpp
@@ -108,6 +108,11 @@
return DAWN_VALIDATION_ERROR(
"The sample counts of the textures in BC formats must be 1.");
}
+
+ if (descriptor->usage & wgpu::TextureUsage::Storage) {
+ return DAWN_VALIDATION_ERROR(
+ "The sample counts of the storage textures must be 1.");
+ }
}
return {};
@@ -184,8 +189,9 @@
"Non-renderable format used with OutputAttachment usage");
}
- if (descriptor->usage & wgpu::TextureUsage::Storage) {
- return DAWN_VALIDATION_ERROR("storage textures aren't supported (yet)");
+ if (!format->supportsStorageUsage &&
+ (descriptor->usage & wgpu::TextureUsage::Storage)) {
+ return DAWN_VALIDATION_ERROR("Format cannot be used in storage textures");
}
return {};
diff --git a/src/tests/unittests/validation/TextureValidationTests.cpp b/src/tests/unittests/validation/TextureValidationTests.cpp
index 5e9cafa..4a996fc 100644
--- a/src/tests/unittests/validation/TextureValidationTests.cpp
+++ b/src/tests/unittests/validation/TextureValidationTests.cpp
@@ -93,6 +93,15 @@
ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
}
+
+ // It is an error to set TextureUsage::Storage when sampleCount > 1.
+ {
+ wgpu::TextureDescriptor descriptor = defaultDescriptor;
+ descriptor.sampleCount = 4;
+ descriptor.usage |= wgpu::TextureUsage::Storage;
+
+ ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
+ }
}
// Test the validation of the mip level count
@@ -329,6 +338,47 @@
}
}
+// Test it is an error to create a Storage texture with any format that doesn't support
+// TextureUsage::Storage texture usages.
+TEST_F(TextureValidationTest, TextureFormatNotSupportTextureUsageStorage) {
+ wgpu::TextureDescriptor descriptor;
+ descriptor.size = {1, 1, 1};
+ descriptor.usage = wgpu::TextureUsage::Storage;
+
+ wgpu::TextureFormat kSupportedFormatsWithStorageUsage[] = {
+ wgpu::TextureFormat::R32Uint, wgpu::TextureFormat::R32Sint,
+ wgpu::TextureFormat::R32Uint, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureFormat::RGBA8Snorm, wgpu::TextureFormat::RGBA8Uint,
+ wgpu::TextureFormat::RGBA8Sint, wgpu::TextureFormat::RG32Uint,
+ wgpu::TextureFormat::RG32Sint, wgpu::TextureFormat::RG32Float,
+ wgpu::TextureFormat::RGBA16Uint, wgpu::TextureFormat::RGBA16Sint,
+ wgpu::TextureFormat::RGBA16Float, wgpu::TextureFormat::RGBA32Uint,
+ wgpu::TextureFormat::RGBA32Sint, wgpu::TextureFormat::RGBA32Float};
+ for (wgpu::TextureFormat format : kSupportedFormatsWithStorageUsage) {
+ descriptor.format = format;
+ device.CreateTexture(&descriptor);
+ }
+
+ wgpu::TextureFormat kUnsupportedFormatsWithStorageUsage[] = {
+ wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::R8Snorm,
+ wgpu::TextureFormat::R8Uint, wgpu::TextureFormat::R8Sint,
+ wgpu::TextureFormat::R16Uint, wgpu::TextureFormat::R16Sint,
+ wgpu::TextureFormat::R16Float, wgpu::TextureFormat::RG8Unorm,
+ wgpu::TextureFormat::RG8Snorm, wgpu::TextureFormat::RG8Uint,
+ wgpu::TextureFormat::RG8Sint, wgpu::TextureFormat::RG16Uint,
+ wgpu::TextureFormat::RG16Sint, wgpu::TextureFormat::RG16Float,
+ wgpu::TextureFormat::RGBA8UnormSrgb, wgpu::TextureFormat::BGRA8Unorm,
+ wgpu::TextureFormat::BGRA8UnormSrgb, wgpu::TextureFormat::RGB10A2Unorm,
+ wgpu::TextureFormat::RG11B10Float,
+
+ wgpu::TextureFormat::Depth24Plus, wgpu::TextureFormat::Depth24PlusStencil8,
+ wgpu::TextureFormat::Depth32Float};
+ for (wgpu::TextureFormat format : kUnsupportedFormatsWithStorageUsage) {
+ descriptor.format = format;
+ ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor));
+ }
+}
+
// Test it is an error to create a texture with format "Undefined".
TEST_F(TextureValidationTest, TextureFormatUndefined) {
wgpu::TextureDescriptor descriptor = CreateDefaultTextureDescriptor();