diff --git a/src/back/glsl/mod.rs b/src/back/glsl/mod.rs index 5a7d4d12a2..81df401d0d 100644 --- a/src/back/glsl/mod.rs +++ b/src/back/glsl/mod.rs @@ -3849,6 +3849,12 @@ const fn glsl_storage_format(format: crate::StorageFormat) -> &'static str { Sf::Rgba32Uint => "rgba32ui", Sf::Rgba32Sint => "rgba32i", Sf::Rgba32Float => "rgba32f", + Sf::R16Unorm => "r16", + Sf::R16Snorm => "r16_snorm", + Sf::Rg16Unorm => "rg16", + Sf::Rg16Snorm => "rg16_snorm", + Sf::Rgba16Unorm => "rgba16", + Sf::Rgba16Snorm => "rgba16_snorm", } } diff --git a/src/back/hlsl/conv.rs b/src/back/hlsl/conv.rs index 886b250b30..819ddb4d43 100644 --- a/src/back/hlsl/conv.rs +++ b/src/back/hlsl/conv.rs @@ -115,14 +115,14 @@ impl crate::StorageFormat { pub(super) const fn to_hlsl_str(self) -> &'static str { match self { Self::R16Float => "float", - Self::R8Unorm => "unorm float", - Self::R8Snorm => "snorm float", + Self::R8Unorm | Self::R16Unorm => "unorm float", + Self::R8Snorm | Self::R16Snorm => "snorm float", Self::R8Uint | Self::R16Uint => "uint", Self::R8Sint | Self::R16Sint => "int", Self::Rg16Float => "float2", - Self::Rg8Unorm => "unorm float2", - Self::Rg8Snorm => "snorm float2", + Self::Rg8Unorm | Self::Rg16Unorm => "unorm float2", + Self::Rg8Snorm | Self::Rg16Snorm => "snorm float2", Self::Rg8Sint | Self::Rg16Sint => "int2", Self::Rg8Uint | Self::Rg16Uint => "uint2", @@ -130,8 +130,8 @@ impl crate::StorageFormat { Self::Rg11b10Float => "float3", Self::Rgba16Float | Self::R32Float | Self::Rg32Float | Self::Rgba32Float => "float4", - Self::Rgba8Unorm | Self::Rgb10a2Unorm => "unorm float4", - Self::Rgba8Snorm => "snorm float4", + Self::Rgba8Unorm | Self::Rgba16Unorm | Self::Rgb10a2Unorm => "unorm float4", + Self::Rgba8Snorm | Self::Rgba16Snorm => "snorm float4", Self::Rgba8Uint | Self::Rgba16Uint diff --git a/src/back/spv/instructions.rs b/src/back/spv/instructions.rs index 9ec1deb0b2..c213790188 100644 --- a/src/back/spv/instructions.rs +++ b/src/back/spv/instructions.rs @@ -979,6 +979,12 @@ impl From for spirv::ImageFormat { Sf::Rgba32Uint => Self::Rgba32ui, Sf::Rgba32Sint => Self::Rgba32i, Sf::Rgba32Float => Self::Rgba32f, + Sf::R16Unorm => Self::R16, + Sf::R16Snorm => Self::R16Snorm, + Sf::Rg16Unorm => Self::Rg16, + Sf::Rg16Snorm => Self::Rg16Snorm, + Sf::Rgba16Unorm => Self::Rgba16, + Sf::Rgba16Snorm => Self::Rgba16Snorm, } } } diff --git a/src/back/wgsl/writer.rs b/src/back/wgsl/writer.rs index 51091f8be1..b2cec92da3 100644 --- a/src/back/wgsl/writer.rs +++ b/src/back/wgsl/writer.rs @@ -1987,6 +1987,12 @@ const fn storage_format_str(format: crate::StorageFormat) -> &'static str { Sf::Rgba32Uint => "rgba32uint", Sf::Rgba32Sint => "rgba32sint", Sf::Rgba32Float => "rgba32float", + Sf::R16Unorm => "r16unorm", + Sf::R16Snorm => "r16snorm", + Sf::Rg16Unorm => "rg16unorm", + Sf::Rg16Snorm => "rg16snorm", + Sf::Rgba16Unorm => "rgba16unorm", + Sf::Rgba16Snorm => "rgba16snorm", } } diff --git a/src/front/glsl/parser/types.rs b/src/front/glsl/parser/types.rs index 7a7757c9c3..93396823eb 100644 --- a/src/front/glsl/parser/types.rs +++ b/src/front/glsl/parser/types.rs @@ -385,15 +385,18 @@ fn map_image_format(word: &str) -> Option { "r11f_g11f_b10f" => Sf::Rg11b10Float, "r32f" => Sf::R32Float, "r16f" => Sf::R16Float, - "rgba16" => Sf::Rgba16Float, + "rgba16" => Sf::Rgba16Unorm, "rgb10_a2" => Sf::Rgb10a2Unorm, "rgba8" => Sf::Rgba8Unorm, - "rg16" => Sf::Rg16Float, + "rg16" => Sf::Rg16Unorm, "rg8" => Sf::Rg8Unorm, - "r16" => Sf::R16Float, + "r16" => Sf::R16Unorm, "r8" => Sf::R8Unorm, + "rgba16_snorm" => Sf::Rgba16Snorm, "rgba8_snorm" => Sf::Rgba8Snorm, + "rg16_snorm" => Sf::Rg16Snorm, "rg8_snorm" => Sf::Rg8Snorm, + "r16_snorm" => Sf::R16Snorm, "r8_snorm" => Sf::R8Snorm, // int-image-format-qualifier: "rgba32i" => Sf::Rgba32Sint, @@ -416,9 +419,6 @@ fn map_image_format(word: &str) -> Option { "r16ui" => Sf::R16Uint, "r8ui" => Sf::R8Uint, // TODO: These next ones seem incorrect to me - // "rgba16_snorm" => Sf::Rgba16Float, - // "rg16_snorm" => Sf::Rg16Float, - // "r16_snorm" => Sf::R16Float, // "rgb10_a2ui" => Sf::Rgb10a2Unorm, _ => return None, }; diff --git a/src/front/spv/convert.rs b/src/front/spv/convert.rs index af7d2b0836..2967555d2b 100644 --- a/src/front/spv/convert.rs +++ b/src/front/spv/convert.rs @@ -84,6 +84,8 @@ pub(super) fn map_image_format(word: spirv::Word) -> Result Ok(crate::StorageFormat::R8Snorm), Some(spirv::ImageFormat::R8ui) => Ok(crate::StorageFormat::R8Uint), Some(spirv::ImageFormat::R8i) => Ok(crate::StorageFormat::R8Sint), + Some(spirv::ImageFormat::R16) => Ok(crate::StorageFormat::R16Unorm), + Some(spirv::ImageFormat::R16Snorm) => Ok(crate::StorageFormat::R16Snorm), Some(spirv::ImageFormat::R16ui) => Ok(crate::StorageFormat::R16Uint), Some(spirv::ImageFormat::R16i) => Ok(crate::StorageFormat::R16Sint), Some(spirv::ImageFormat::R16f) => Ok(crate::StorageFormat::R16Float), @@ -94,6 +96,8 @@ pub(super) fn map_image_format(word: spirv::Word) -> Result Ok(crate::StorageFormat::R32Uint), Some(spirv::ImageFormat::R32i) => Ok(crate::StorageFormat::R32Sint), Some(spirv::ImageFormat::R32f) => Ok(crate::StorageFormat::R32Float), + Some(spirv::ImageFormat::Rg16) => Ok(crate::StorageFormat::Rg16Unorm), + Some(spirv::ImageFormat::Rg16Snorm) => Ok(crate::StorageFormat::Rg16Snorm), Some(spirv::ImageFormat::Rg16ui) => Ok(crate::StorageFormat::Rg16Uint), Some(spirv::ImageFormat::Rg16i) => Ok(crate::StorageFormat::Rg16Sint), Some(spirv::ImageFormat::Rg16f) => Ok(crate::StorageFormat::Rg16Float), @@ -106,6 +110,8 @@ pub(super) fn map_image_format(word: spirv::Word) -> Result Ok(crate::StorageFormat::Rg32Uint), Some(spirv::ImageFormat::Rg32i) => Ok(crate::StorageFormat::Rg32Sint), Some(spirv::ImageFormat::Rg32f) => Ok(crate::StorageFormat::Rg32Float), + Some(spirv::ImageFormat::Rgba16) => Ok(crate::StorageFormat::Rgba16Unorm), + Some(spirv::ImageFormat::Rgba16Snorm) => Ok(crate::StorageFormat::Rgba16Snorm), Some(spirv::ImageFormat::Rgba16ui) => Ok(crate::StorageFormat::Rgba16Uint), Some(spirv::ImageFormat::Rgba16i) => Ok(crate::StorageFormat::Rgba16Sint), Some(spirv::ImageFormat::Rgba16f) => Ok(crate::StorageFormat::Rgba16Float), diff --git a/src/front/wgsl/conv.rs b/src/front/wgsl/conv.rs index 25acdcb217..645f90b011 100644 --- a/src/front/wgsl/conv.rs +++ b/src/front/wgsl/conv.rs @@ -63,6 +63,8 @@ pub fn map_storage_format(word: &str, span: Span) -> Result Sf::R8Snorm, "r8uint" => Sf::R8Uint, "r8sint" => Sf::R8Sint, + "r16unorm" => Sf::R16Unorm, + "r16snorm" => Sf::R16Snorm, "r16uint" => Sf::R16Uint, "r16sint" => Sf::R16Sint, "r16float" => Sf::R16Float, @@ -73,6 +75,8 @@ pub fn map_storage_format(word: &str, span: Span) -> Result Sf::R32Uint, "r32sint" => Sf::R32Sint, "r32float" => Sf::R32Float, + "rg16unorm" => Sf::Rg16Unorm, + "rg16snorm" => Sf::Rg16Snorm, "rg16uint" => Sf::Rg16Uint, "rg16sint" => Sf::Rg16Sint, "rg16float" => Sf::Rg16Float, @@ -85,6 +89,8 @@ pub fn map_storage_format(word: &str, span: Span) -> Result Sf::Rg32Uint, "rg32sint" => Sf::Rg32Sint, "rg32float" => Sf::Rg32Float, + "rgba16unorm" => Sf::Rgba16Unorm, + "rgba16snorm" => Sf::Rgba16Snorm, "rgba16uint" => Sf::Rgba16Uint, "rgba16sint" => Sf::Rgba16Sint, "rgba16float" => Sf::Rgba16Float, diff --git a/src/front/wgsl/mod.rs b/src/front/wgsl/mod.rs index 80d542952c..c4821ba62b 100644 --- a/src/front/wgsl/mod.rs +++ b/src/front/wgsl/mod.rs @@ -687,6 +687,12 @@ impl crate::StorageFormat { Sf::Rgba32Uint => "rgba32uint", Sf::Rgba32Sint => "rgba32sint", Sf::Rgba32Float => "rgba32float", + Sf::R16Unorm => "r16unorm", + Sf::R16Snorm => "r16snorm", + Sf::Rg16Unorm => "rg16unorm", + Sf::Rg16Snorm => "rg16snorm", + Sf::Rgba16Unorm => "rgba16unorm", + Sf::Rgba16Snorm => "rgba16snorm", } } } diff --git a/src/lib.rs b/src/lib.rs index 4497c14acb..7054520082 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -531,6 +531,14 @@ pub enum StorageFormat { Rgba32Uint, Rgba32Sint, Rgba32Float, + + // Normalized 16-bit per channel formats + R16Unorm, + R16Snorm, + Rg16Unorm, + Rg16Snorm, + Rgba16Unorm, + Rgba16Snorm, } /// Sub-class of the image type. diff --git a/src/proc/mod.rs b/src/proc/mod.rs index c718c33b24..f30158c113 100644 --- a/src/proc/mod.rs +++ b/src/proc/mod.rs @@ -52,6 +52,12 @@ impl From for super::ScalarKind { Sf::Rgba32Uint => Sk::Uint, Sf::Rgba32Sint => Sk::Sint, Sf::Rgba32Float => Sk::Float, + Sf::R16Unorm => Sk::Float, + Sf::R16Snorm => Sk::Float, + Sf::Rg16Unorm => Sk::Float, + Sf::Rg16Snorm => Sk::Float, + Sf::Rgba16Unorm => Sk::Float, + Sf::Rgba16Snorm => Sk::Float, } } } diff --git a/src/valid/interface.rs b/src/valid/interface.rs index fdc1cf43ed..67130ddc68 100644 --- a/src/valid/interface.rs +++ b/src/valid/interface.rs @@ -435,6 +435,35 @@ impl super::Validator { return Err(GlobalVariableError::InvalidType(var.space)); } }; + let inner_ty = match &types[var.ty].inner { + &crate::TypeInner::BindingArray { base, .. } => &types[base].inner, + ty => ty, + }; + if let crate::TypeInner::Image { + class: + crate::ImageClass::Storage { + format: + crate::StorageFormat::R16Unorm + | crate::StorageFormat::R16Snorm + | crate::StorageFormat::Rg16Unorm + | crate::StorageFormat::Rg16Snorm + | crate::StorageFormat::Rgba16Unorm + | crate::StorageFormat::Rgba16Snorm, + .. + }, + .. + } = *inner_ty + { + if !self + .capabilities + .contains(Capabilities::STORAGE_TEXTURE_16BIT_NORM_FORMATS) + { + return Err(GlobalVariableError::UnsupportedCapability( + Capabilities::STORAGE_TEXTURE_16BIT_NORM_FORMATS, + )); + } + } + (TypeFlags::empty(), true) } crate::AddressSpace::Private | crate::AddressSpace::WorkGroup => { diff --git a/src/valid/mod.rs b/src/valid/mod.rs index 7679223f03..25fdf20ccc 100644 --- a/src/valid/mod.rs +++ b/src/valid/mod.rs @@ -87,7 +87,7 @@ bitflags::bitflags! { #[derive(Default)] #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] - pub struct Capabilities: u8 { + pub struct Capabilities: u16 { /// Support for [`AddressSpace:PushConstant`]. const PUSH_CONSTANT = 0x1; /// Float values with width = 8. @@ -104,6 +104,8 @@ bitflags::bitflags! { const CLIP_DISTANCE = 0x40; /// Support for [`Builtin::CullDistance`]. const CULL_DISTANCE = 0x80; + /// Support for 16-bit normalized storage texture formats. + const STORAGE_TEXTURE_16BIT_NORM_FORMATS = 0x100; } }