diff --git a/src/dawn_native/Format.cpp b/src/dawn_native/Format.cpp index c5537848a5..d4c0e16146 100644 --- a/src/dawn_native/Format.cpp +++ b/src/dawn_native/Format.cpp @@ -118,12 +118,14 @@ namespace dawn_native { }; 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 @@ namespace dawn_native { 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 @@ namespace dawn_native { 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 @@ namespace dawn_native { // 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 f1e4fbb487..3d2c48a9ad 100644 --- a/src/dawn_native/Format.h +++ b/src/dawn_native/Format.h @@ -50,6 +50,7 @@ namespace dawn_native { 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 e1b70b2c3c..7b264c1ec1 100644 --- a/src/dawn_native/Texture.cpp +++ b/src/dawn_native/Texture.cpp @@ -108,6 +108,11 @@ namespace dawn_native { 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 @@ namespace dawn_native { "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 5e9cafa25e..4a996fc4fc 100644 --- a/src/tests/unittests/validation/TextureValidationTests.cpp +++ b/src/tests/unittests/validation/TextureValidationTests.cpp @@ -93,6 +93,15 @@ TEST_F(TextureValidationTest, SampleCount) { 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_F(TextureValidationTest, NonRenderableAndOutputAttachment) { } } +// 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();