From 21ff9686a7f2cb0caa358651b285a8a409e22b2c Mon Sep 17 00:00:00 2001 From: Christofer Nolander Date: Mon, 16 Dec 2024 16:18:50 +0100 Subject: [PATCH] Add 1-component `({s,u}{int,norm}{8,16}`, `float16`) and `unorm8x4-bgra` vertex formats (#6632) * feat: add missing 8/16-bit vertex formats (and 8-bit bgra) #6614 * add tests for 1-component vertex formats (and bgra) * metal: unpacking function for 1-component vertex formats * test: use proper alignment for float16 vertex format * changelog: new vertex formats --- CHANGELOG.md | 1 + naga/src/back/msl/mod.rs | 88 +++++++++------ naga/src/back/msl/writer.rs | 131 ++++++++++++++++++++++ tests/tests/vertex_formats/draw.vert.wgsl | 67 +++++++++++ tests/tests/vertex_formats/mod.rs | 46 +++++++- wgpu-core/src/validation.rs | 11 +- wgpu-hal/src/auxil/dxgi/conv.rs | 10 ++ wgpu-hal/src/gles/conv.rs | 10 ++ wgpu-hal/src/metal/conv.rs | 10 ++ wgpu-hal/src/metal/device.rs | 18 ++- wgpu-hal/src/vulkan/conv.rs | 10 ++ wgpu-types/src/lib.rs | 105 +++++++++++------ wgpu/src/backend/webgpu.rs | 10 ++ 13 files changed, 439 insertions(+), 78 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 383de4e71c..9bf86be289 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -130,6 +130,7 @@ By @ErichDonGubler in [#6456](https://github.com/gfx-rs/wgpu/pull/6456), [#6148] - Implement `quantizeToF16()` for WGSL frontend, and WGSL, SPIR-V, HLSL, MSL, and GLSL backends. By @jamienicol in [#6519](https://github.com/gfx-rs/wgpu/pull/6519). - Add support for GLSL `usampler*` and `isampler*`. By @DavidPeicho in [#6513](https://github.com/gfx-rs/wgpu/pull/6513). - Expose Ray Query flags as constants in WGSL. Implement candidate intersections. By @kvark in [#5429](https://github.com/gfx-rs/wgpu/pull/5429) +- Add new vertex formats (`{U,S}{int,norm}{8,16}`, `Float16` and `Unorm8x4Bgra`). By @nolanderc in [#6632](https://github.com/gfx-rs/wgpu/pull/6632) - Allow for override-expressions in `workgroup_size`. By @KentSlaney in [#6635](https://github.com/gfx-rs/wgpu/pull/6635). - Add support for OpAtomicCompareExchange in SPIR-V frontend. By @schell in [#6590](https://github.com/gfx-rs/wgpu/pull/6590). - Implement type inference for abstract arguments to user-defined functions. By @jamienicol in [#6577](https://github.com/gfx-rs/wgpu/pull/6577). diff --git a/naga/src/back/msl/mod.rs b/naga/src/back/msl/mod.rs index ccce7c2a27..78651001fd 100644 --- a/naga/src/back/msl/mod.rs +++ b/naga/src/back/msl/mod.rs @@ -238,72 +238,90 @@ impl Default for Options { #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] pub enum VertexFormat { + /// One unsigned byte (u8). `u32` in shaders. + Uint8 = 0, /// Two unsigned bytes (u8). `vec2` in shaders. - Uint8x2 = 0, + Uint8x2 = 1, /// Four unsigned bytes (u8). `vec4` in shaders. - Uint8x4 = 1, + Uint8x4 = 2, + /// One signed byte (i8). `i32` in shaders. + Sint8 = 3, /// Two signed bytes (i8). `vec2` in shaders. - Sint8x2 = 2, + Sint8x2 = 4, /// Four signed bytes (i8). `vec4` in shaders. - Sint8x4 = 3, + Sint8x4 = 5, + /// One unsigned byte (u8). [0, 255] converted to float [0, 1] `f32` in shaders. + Unorm8 = 6, /// Two unsigned bytes (u8). [0, 255] converted to float [0, 1] `vec2` in shaders. - Unorm8x2 = 4, + Unorm8x2 = 7, /// Four unsigned bytes (u8). [0, 255] converted to float [0, 1] `vec4` in shaders. - Unorm8x4 = 5, + Unorm8x4 = 8, + /// One signed byte (i8). [-127, 127] converted to float [-1, 1] `f32` in shaders. + Snorm8 = 9, /// Two signed bytes (i8). [-127, 127] converted to float [-1, 1] `vec2` in shaders. - Snorm8x2 = 6, + Snorm8x2 = 10, /// Four signed bytes (i8). [-127, 127] converted to float [-1, 1] `vec4` in shaders. - Snorm8x4 = 7, + Snorm8x4 = 11, + /// One unsigned short (u16). `u32` in shaders. + Uint16 = 12, /// Two unsigned shorts (u16). `vec2` in shaders. - Uint16x2 = 8, + Uint16x2 = 13, /// Four unsigned shorts (u16). `vec4` in shaders. - Uint16x4 = 9, + Uint16x4 = 14, + /// One signed short (u16). `i32` in shaders. + Sint16 = 15, /// Two signed shorts (i16). `vec2` in shaders. - Sint16x2 = 10, + Sint16x2 = 16, /// Four signed shorts (i16). `vec4` in shaders. - Sint16x4 = 11, + Sint16x4 = 17, + /// One unsigned short (u16). [0, 65535] converted to float [0, 1] `f32` in shaders. + Unorm16 = 18, /// Two unsigned shorts (u16). [0, 65535] converted to float [0, 1] `vec2` in shaders. - Unorm16x2 = 12, + Unorm16x2 = 19, /// Four unsigned shorts (u16). [0, 65535] converted to float [0, 1] `vec4` in shaders. - Unorm16x4 = 13, + Unorm16x4 = 20, + /// One signed short (i16). [-32767, 32767] converted to float [-1, 1] `f32` in shaders. + Snorm16 = 21, /// Two signed shorts (i16). [-32767, 32767] converted to float [-1, 1] `vec2` in shaders. - Snorm16x2 = 14, + Snorm16x2 = 22, /// Four signed shorts (i16). [-32767, 32767] converted to float [-1, 1] `vec4` in shaders. - Snorm16x4 = 15, + Snorm16x4 = 23, + /// One half-precision float (no Rust equiv). `f32` in shaders. + Float16 = 24, /// Two half-precision floats (no Rust equiv). `vec2` in shaders. - Float16x2 = 16, + Float16x2 = 25, /// Four half-precision floats (no Rust equiv). `vec4` in shaders. - Float16x4 = 17, + Float16x4 = 26, /// One single-precision float (f32). `f32` in shaders. - Float32 = 18, + Float32 = 27, /// Two single-precision floats (f32). `vec2` in shaders. - Float32x2 = 19, + Float32x2 = 28, /// Three single-precision floats (f32). `vec3` in shaders. - Float32x3 = 20, + Float32x3 = 29, /// Four single-precision floats (f32). `vec4` in shaders. - Float32x4 = 21, + Float32x4 = 30, /// One unsigned int (u32). `u32` in shaders. - Uint32 = 22, + Uint32 = 31, /// Two unsigned ints (u32). `vec2` in shaders. - Uint32x2 = 23, + Uint32x2 = 32, /// Three unsigned ints (u32). `vec3` in shaders. - Uint32x3 = 24, + Uint32x3 = 33, /// Four unsigned ints (u32). `vec4` in shaders. - Uint32x4 = 25, + Uint32x4 = 34, /// One signed int (i32). `i32` in shaders. - Sint32 = 26, + Sint32 = 35, /// Two signed ints (i32). `vec2` in shaders. - Sint32x2 = 27, + Sint32x2 = 36, /// Three signed ints (i32). `vec3` in shaders. - Sint32x3 = 28, + Sint32x3 = 37, /// Four signed ints (i32). `vec4` in shaders. - Sint32x4 = 29, + Sint32x4 = 38, /// Three unsigned 10-bit integers and one 2-bit integer, packed into a 32-bit integer (u32). [0, 1024] converted to float [0, 1] `vec4` in shaders. - #[cfg_attr( - any(feature = "serialize", feature = "deserialize"), - serde(rename = "unorm10-10-10-2") - )] - Unorm10_10_10_2 = 34, + #[cfg_attr(feature = "serde", serde(rename = "unorm10-10-10-2"))] + Unorm10_10_10_2 = 43, + /// Four unsigned 8-bit integers, packed into a 32-bit integer (u32). [0, 255] converted to float [0, 1] `vec4` in shaders. + #[cfg_attr(feature = "serde", serde(rename = "unorm8x4-bgra"))] + Unorm8x4Bgra = 44, } /// A mapping of vertex buffers and their attributes to shader diff --git a/naga/src/back/msl/writer.rs b/naga/src/back/msl/writer.rs index 3a1a637f3f..28ddd1cea1 100644 --- a/naga/src/back/msl/writer.rs +++ b/naga/src/back/msl/writer.rs @@ -4014,6 +4014,13 @@ template ) -> Result<(String, u32, u32), Error> { use back::msl::VertexFormat::*; match format { + Uint8 => { + let name = self.namer.call("unpackUint8"); + writeln!(self.out, "uint {name}(metal::uchar b0) {{")?; + writeln!(self.out, "{}return uint(b0);", back::INDENT)?; + writeln!(self.out, "}}")?; + Ok((name, 1, 1)) + } Uint8x2 => { let name = self.namer.call("unpackUint8x2"); writeln!( @@ -4042,6 +4049,13 @@ template writeln!(self.out, "}}")?; Ok((name, 4, 4)) } + Sint8 => { + let name = self.namer.call("unpackSint8"); + writeln!(self.out, "int {name}(metal::uchar b0) {{")?; + writeln!(self.out, "{}return int(as_type(b0));", back::INDENT)?; + writeln!(self.out, "}}")?; + Ok((name, 1, 1)) + } Sint8x2 => { let name = self.namer.call("unpackSint8x2"); writeln!( @@ -4078,6 +4092,17 @@ template writeln!(self.out, "}}")?; Ok((name, 4, 4)) } + Unorm8 => { + let name = self.namer.call("unpackUnorm8"); + writeln!(self.out, "float {name}(metal::uchar b0) {{")?; + writeln!( + self.out, + "{}return float(float(b0) / 255.0f);", + back::INDENT + )?; + writeln!(self.out, "}}")?; + Ok((name, 1, 1)) + } Unorm8x2 => { let name = self.namer.call("unpackUnorm8x2"); writeln!( @@ -4114,6 +4139,17 @@ template writeln!(self.out, "}}")?; Ok((name, 4, 4)) } + Snorm8 => { + let name = self.namer.call("unpackSnorm8"); + writeln!(self.out, "float {name}(metal::uchar b0) {{")?; + writeln!( + self.out, + "{}return float(metal::max(-1.0f, as_type(b0) / 127.0f));", + back::INDENT + )?; + writeln!(self.out, "}}")?; + Ok((name, 1, 1)) + } Snorm8x2 => { let name = self.namer.call("unpackSnorm8x2"); writeln!( @@ -4150,6 +4186,21 @@ template writeln!(self.out, "}}")?; Ok((name, 4, 4)) } + Uint16 => { + let name = self.namer.call("unpackUint16"); + writeln!( + self.out, + "metal::uint {name}(metal::uint b0, \ + metal::uint b1) {{" + )?; + writeln!( + self.out, + "{}return metal::uint(b1 << 8 | b0);", + back::INDENT + )?; + writeln!(self.out, "}}")?; + Ok((name, 2, 1)) + } Uint16x2 => { let name = self.namer.call("unpackUint16x2"); writeln!( @@ -4192,6 +4243,21 @@ template writeln!(self.out, "}}")?; Ok((name, 8, 4)) } + Sint16 => { + let name = self.namer.call("unpackSint16"); + writeln!( + self.out, + "int {name}(metal::ushort b0, \ + metal::ushort b1) {{" + )?; + writeln!( + self.out, + "{}return int(as_type(metal::ushort(b1 << 8 | b0)));", + back::INDENT + )?; + writeln!(self.out, "}}")?; + Ok((name, 2, 1)) + } Sint16x2 => { let name = self.namer.call("unpackSint16x2"); writeln!( @@ -4234,6 +4300,21 @@ template writeln!(self.out, "}}")?; Ok((name, 8, 4)) } + Unorm16 => { + let name = self.namer.call("unpackUnorm16"); + writeln!( + self.out, + "float {name}(metal::ushort b0, \ + metal::ushort b1) {{" + )?; + writeln!( + self.out, + "{}return float(float(b1 << 8 | b0) / 65535.0f);", + back::INDENT + )?; + writeln!(self.out, "}}")?; + Ok((name, 2, 1)) + } Unorm16x2 => { let name = self.namer.call("unpackUnorm16x2"); writeln!( @@ -4276,6 +4357,21 @@ template writeln!(self.out, "}}")?; Ok((name, 8, 4)) } + Snorm16 => { + let name = self.namer.call("unpackSnorm16"); + writeln!( + self.out, + "float {name}(metal::ushort b0, \ + metal::ushort b1) {{" + )?; + writeln!( + self.out, + "{}return metal::unpack_snorm2x16_to_float(b1 << 8 | b0).x;", + back::INDENT + )?; + writeln!(self.out, "}}")?; + Ok((name, 2, 1)) + } Snorm16x2 => { let name = self.namer.call("unpackSnorm16x2"); writeln!( @@ -4315,6 +4411,21 @@ template writeln!(self.out, "}}")?; Ok((name, 8, 4)) } + Float16 => { + let name = self.namer.call("unpackFloat16"); + writeln!( + self.out, + "float {name}(metal::ushort b0, \ + metal::ushort b1) {{" + )?; + writeln!( + self.out, + "{}return float(as_type(metal::ushort(b1 << 8 | b0)));", + back::INDENT + )?; + writeln!(self.out, "}}")?; + Ok((name, 2, 1)) + } Float16x2 => { let name = self.namer.call("unpackFloat16x2"); writeln!( @@ -4679,6 +4790,26 @@ template writeln!(self.out, "}}")?; Ok((name, 4, 4)) } + Unorm8x4Bgra => { + let name = self.namer.call("unpackUnorm8x4Bgra"); + writeln!( + self.out, + "metal::float4 {name}(metal::uchar b0, \ + metal::uchar b1, \ + metal::uchar b2, \ + metal::uchar b3) {{" + )?; + writeln!( + self.out, + "{}return metal::float4(float(b2) / 255.0f, \ + float(b1) / 255.0f, \ + float(b0) / 255.0f, \ + float(b3) / 255.0f);", + back::INDENT + )?; + writeln!(self.out, "}}")?; + Ok((name, 4, 4)) + } } } diff --git a/tests/tests/vertex_formats/draw.vert.wgsl b/tests/tests/vertex_formats/draw.vert.wgsl index bf6a08aac6..33fc05eb21 100644 --- a/tests/tests/vertex_formats/draw.vert.wgsl +++ b/tests/tests/vertex_formats/draw.vert.wgsl @@ -225,6 +225,7 @@ struct AttributeBlock4{ @location(3) float32x4: vec4, @location(4) float16x2: vec2, @location(5) float16x4: vec4, + @location(6) float16: f32, } @vertex @@ -260,6 +261,8 @@ fn vertex_block_4(v_in: AttributeBlock4) -> @builtin(position) vec4 all_float16 = accumulate_float16(all_float16, v_in.float16x4.z); all_float16 = accumulate_float16(all_float16, v_in.float16x4.w); + all_float16 = accumulate_float16(all_float16, v_in.float16); + checksums[index_float16] = f32(all_float16); return vec4(0.0); @@ -286,6 +289,70 @@ fn vertex_block_5(v_in: AttributeBlock5) -> @builtin(position) vec4 return vec4(0.0); } +struct AttributeBlock6 { + @location(0) uint16: u32, + @location(1) sint16: i32, + @location(2) unorm16: f32, + @location(3) snorm16: f32, + @location(4) uint8: u32, + @location(5) sint8: i32, + @location(6) unorm8: f32, + @location(7) snorm8: f32, +} + +@vertex +fn vertex_block_6(v_in: AttributeBlock6) -> @builtin(position) vec4 +{ + init_checksums(); + + // Accumulate all unorm into one checksum value. + var all_unorm: f32 = 0.0; + all_unorm = accumulate_unorm(all_unorm, v_in.unorm16); + all_unorm = accumulate_unorm(all_unorm, v_in.unorm8); + checksums[index_unorm] = f32(all_unorm); + + // Accumulate all snorm into one checksum value. + var all_snorm: f32 = 0.0; + all_snorm = accumulate_snorm(all_snorm, v_in.snorm16); + all_snorm = accumulate_snorm(all_snorm, v_in.snorm8); + checksums[index_snorm] = f32(all_snorm); + + // Accumulate all uint into one checksum value. + var all_uint: u32 = 0; + all_uint = accumulate_uint(all_uint, v_in.uint16); + all_uint = accumulate_uint(all_uint, v_in.uint8); + checksums[index_uint] = f32(all_uint); + + // Accumulate all sint into one checksum value. + var all_sint: i32 = 0; + all_sint = accumulate_sint(all_sint, v_in.sint16); + all_sint = accumulate_sint(all_sint, v_in.sint8); + checksums[index_sint] = f32(all_sint); + + return vec4(0.0); +} + +struct AttributeBlock7 { + @location(0) unorm8x4_bgra: vec4, +} + +@vertex +fn vertex_block_7(v_in: AttributeBlock7) -> @builtin(position) vec4 +{ + init_checksums(); + + // Accumulate all unorm into one checksum value. + var all_unorm: f32 = 0.0; + all_unorm = accumulate_unorm(all_unorm, v_in.unorm8x4_bgra.r); + all_unorm = accumulate_unorm(all_unorm, v_in.unorm8x4_bgra.g); + all_unorm = accumulate_unorm(all_unorm, v_in.unorm8x4_bgra.b); + all_unorm = accumulate_unorm(all_unorm, v_in.unorm8x4_bgra.a); + + checksums[index_unorm] = f32(all_unorm); + + return vec4(0.0); +} + fn accumulate_uint(accum: u32, val: u32) -> u32 { return accum + val; } diff --git a/tests/tests/vertex_formats/mod.rs b/tests/tests/vertex_formats/mod.rs index e956455786..c8a538c4f6 100644 --- a/tests/tests/vertex_formats/mod.rs +++ b/tests/tests/vertex_formats/mod.rs @@ -14,6 +14,8 @@ enum TestCase { SintsBig, Floats, Unorm1010102, + SingleSmallNormsAndInts, + Unorm8x4Bgra, } struct Test<'a> { @@ -68,6 +70,22 @@ async fn vertex_formats_all(ctx: TestingContext) { 3 => Float32x4, 4 => Float16x2, 5 => Float16x4, + 6 => Float16, + ]; + + let attributes_block_6 = &wgpu::vertex_attr_array![ + 0 => Uint16, + 1 => Sint16, + 2 => Unorm16, + 3 => Snorm16, + 4 => Uint8, + 5 => Sint8, + 6 => Unorm8, + 7 => Snorm8, + ]; + + let attributes_block_7 = &wgpu::vertex_attr_array![ + 0 => Unorm8x4Bgra, ]; let tests = vec![ @@ -145,11 +163,37 @@ async fn vertex_formats_all(ctx: TestingContext) { 66u8, // Float32x3 (-2.0, -102.0, 100.0) 0u8, 0u8, 92u8, 66u8, 0u8, 0u8, 72u8, 194u8, 0u8, 0u8, 32u8, 65u8, 0u8, 0u8, 128u8, 63u8, // Float32x4 (55.0, -50.0, 10.0, 1.0) + 0u8, 68u8, // Float16 (4.0) 0u8, 60u8, 72u8, 53u8, // Float16x2 (1.0, 0.33) 72u8, 57u8, 0u8, 192u8, 0u8, 188u8, 0u8, 184u8, // Float16x4 (0.66, -2.0, -1.0, -0.5) ], - checksums: &[0.0, 0.0, 0.0, 0.0, -1.5, 16.0], + checksums: &[0.0, 0.0, 0.0, 0.0, 2.5, 16.0], + }, + Test { + case: TestCase::SingleSmallNormsAndInts, + entry_point: "vertex_block_6", + attributes: attributes_block_6, + input: &[ + 1u8, 2u8, // Uint16 (513) + 1u8, 2u8, // Sint16 (513) + 0u8, 64u8, // Unorm16 (0.25) + 0u8, 64u8, // Snorm16 (0.5) + 32u8, // Uint8 (32) + 255u8, // Sint8 (-1) + 128u8, // Unorm8 (0.5) + 128u8, // Snorm8 (-1) + ], + checksums: &[513.0 + 32.0, 513.0 - 1.0, 0.25 + 0.5, 0.5 - 1.0, 0.0, 0.0], + }, + Test { + case: TestCase::Unorm8x4Bgra, + entry_point: "vertex_block_7", + attributes: attributes_block_7, + input: &[ + 128u8, 85u8, 170u8, 64u8, // Unorm8x4Bgra (0.67, 0.33, 0.5, 0.25) + ], + checksums: &[0.0, 0.0, 1.75, 0.0, 0.0, 0.0], }, ]; diff --git a/wgpu-core/src/validation.rs b/wgpu-core/src/validation.rs index b1c0051902..9ac2d6f787 100644 --- a/wgpu-core/src/validation.rs +++ b/wgpu-core/src/validation.rs @@ -640,7 +640,7 @@ impl NumericType { use wgt::VertexFormat as Vf; let (dim, scalar) = match format { - Vf::Uint32 => (NumericDimension::Scalar, Scalar::U32), + Vf::Uint8 | Vf::Uint16 | Vf::Uint32 => (NumericDimension::Scalar, Scalar::U32), Vf::Uint8x2 | Vf::Uint16x2 | Vf::Uint32x2 => { (NumericDimension::Vector(Vs::Bi), Scalar::U32) } @@ -648,7 +648,7 @@ impl NumericType { Vf::Uint8x4 | Vf::Uint16x4 | Vf::Uint32x4 => { (NumericDimension::Vector(Vs::Quad), Scalar::U32) } - Vf::Sint32 => (NumericDimension::Scalar, Scalar::I32), + Vf::Sint8 | Vf::Sint16 | Vf::Sint32 => (NumericDimension::Scalar, Scalar::I32), Vf::Sint8x2 | Vf::Sint16x2 | Vf::Sint32x2 => { (NumericDimension::Vector(Vs::Bi), Scalar::I32) } @@ -656,7 +656,9 @@ impl NumericType { Vf::Sint8x4 | Vf::Sint16x4 | Vf::Sint32x4 => { (NumericDimension::Vector(Vs::Quad), Scalar::I32) } - Vf::Float32 => (NumericDimension::Scalar, Scalar::F32), + Vf::Unorm8 | Vf::Unorm16 | Vf::Snorm8 | Vf::Snorm16 | Vf::Float16 | Vf::Float32 => { + (NumericDimension::Scalar, Scalar::F32) + } Vf::Unorm8x2 | Vf::Snorm8x2 | Vf::Unorm16x2 @@ -670,7 +672,8 @@ impl NumericType { | Vf::Snorm16x4 | Vf::Float16x4 | Vf::Float32x4 - | Vf::Unorm10_10_10_2 => (NumericDimension::Vector(Vs::Quad), Scalar::F32), + | Vf::Unorm10_10_10_2 + | Vf::Unorm8x4Bgra => (NumericDimension::Vector(Vs::Quad), Scalar::F32), Vf::Float64 => (NumericDimension::Scalar, Scalar::F64), Vf::Float64x2 => (NumericDimension::Vector(Vs::Bi), Scalar::F64), Vf::Float64x3 => (NumericDimension::Vector(Vs::Tri), Scalar::F64), diff --git a/wgpu-hal/src/auxil/dxgi/conv.rs b/wgpu-hal/src/auxil/dxgi/conv.rs index ad64f044cc..0f94575df8 100644 --- a/wgpu-hal/src/auxil/dxgi/conv.rs +++ b/wgpu-hal/src/auxil/dxgi/conv.rs @@ -235,6 +235,10 @@ pub fn map_vertex_format(format: wgt::VertexFormat) -> Dxgi::Common::DXGI_FORMAT use Dxgi::Common::*; match format { + Vf::Unorm8 => DXGI_FORMAT_R8_UNORM, + Vf::Snorm8 => DXGI_FORMAT_R8_SNORM, + Vf::Uint8 => DXGI_FORMAT_R8_UINT, + Vf::Sint8 => DXGI_FORMAT_R8_SINT, Vf::Unorm8x2 => DXGI_FORMAT_R8G8_UNORM, Vf::Snorm8x2 => DXGI_FORMAT_R8G8_SNORM, Vf::Uint8x2 => DXGI_FORMAT_R8G8_UINT, @@ -243,6 +247,11 @@ pub fn map_vertex_format(format: wgt::VertexFormat) -> Dxgi::Common::DXGI_FORMAT Vf::Snorm8x4 => DXGI_FORMAT_R8G8B8A8_SNORM, Vf::Uint8x4 => DXGI_FORMAT_R8G8B8A8_UINT, Vf::Sint8x4 => DXGI_FORMAT_R8G8B8A8_SINT, + Vf::Unorm16 => DXGI_FORMAT_R16_UNORM, + Vf::Snorm16 => DXGI_FORMAT_R16_SNORM, + Vf::Uint16 => DXGI_FORMAT_R16_UINT, + Vf::Sint16 => DXGI_FORMAT_R16_SINT, + Vf::Float16 => DXGI_FORMAT_R16_FLOAT, Vf::Unorm16x2 => DXGI_FORMAT_R16G16_UNORM, Vf::Snorm16x2 => DXGI_FORMAT_R16G16_SNORM, Vf::Uint16x2 => DXGI_FORMAT_R16G16_UINT, @@ -266,6 +275,7 @@ pub fn map_vertex_format(format: wgt::VertexFormat) -> Dxgi::Common::DXGI_FORMAT Vf::Sint32x4 => DXGI_FORMAT_R32G32B32A32_SINT, Vf::Float32x4 => DXGI_FORMAT_R32G32B32A32_FLOAT, Vf::Unorm10_10_10_2 => DXGI_FORMAT_R10G10B10A2_UNORM, + Vf::Unorm8x4Bgra => DXGI_FORMAT_B8G8R8A8_UNORM, Vf::Float64 | Vf::Float64x2 | Vf::Float64x3 | Vf::Float64x4 => unimplemented!(), } } diff --git a/wgpu-hal/src/gles/conv.rs b/wgpu-hal/src/gles/conv.rs index 3a6d5ebb2e..029e03bf5e 100644 --- a/wgpu-hal/src/gles/conv.rs +++ b/wgpu-hal/src/gles/conv.rs @@ -182,6 +182,10 @@ pub(super) fn describe_vertex_format(vertex_format: wgt::VertexFormat) -> super: use wgt::VertexFormat as Vf; let (element_count, element_format, attrib_kind) = match vertex_format { + Vf::Unorm8 => (1, glow::UNSIGNED_BYTE, Vak::Float), + Vf::Snorm8 => (1, glow::BYTE, Vak::Float), + Vf::Uint8 => (1, glow::UNSIGNED_BYTE, Vak::Integer), + Vf::Sint8 => (1, glow::BYTE, Vak::Integer), Vf::Unorm8x2 => (2, glow::UNSIGNED_BYTE, Vak::Float), Vf::Snorm8x2 => (2, glow::BYTE, Vak::Float), Vf::Uint8x2 => (2, glow::UNSIGNED_BYTE, Vak::Integer), @@ -190,6 +194,11 @@ pub(super) fn describe_vertex_format(vertex_format: wgt::VertexFormat) -> super: Vf::Snorm8x4 => (4, glow::BYTE, Vak::Float), Vf::Uint8x4 => (4, glow::UNSIGNED_BYTE, Vak::Integer), Vf::Sint8x4 => (4, glow::BYTE, Vak::Integer), + Vf::Unorm16 => (1, glow::UNSIGNED_SHORT, Vak::Float), + Vf::Snorm16 => (1, glow::SHORT, Vak::Float), + Vf::Uint16 => (1, glow::UNSIGNED_SHORT, Vak::Integer), + Vf::Sint16 => (1, glow::SHORT, Vak::Integer), + Vf::Float16 => (1, glow::HALF_FLOAT, Vak::Float), Vf::Unorm16x2 => (2, glow::UNSIGNED_SHORT, Vak::Float), Vf::Snorm16x2 => (2, glow::SHORT, Vak::Float), Vf::Uint16x2 => (2, glow::UNSIGNED_SHORT, Vak::Integer), @@ -213,6 +222,7 @@ pub(super) fn describe_vertex_format(vertex_format: wgt::VertexFormat) -> super: Vf::Sint32x4 => (4, glow::INT, Vak::Integer), Vf::Float32x4 => (4, glow::FLOAT, Vak::Float), Vf::Unorm10_10_10_2 => (4, glow::UNSIGNED_INT_10_10_10_2, Vak::Float), + Vf::Unorm8x4Bgra => (glow::BGRA as i32, glow::UNSIGNED_BYTE, Vak::Float), Vf::Float64 | Vf::Float64x2 | Vf::Float64x3 | Vf::Float64x4 => unimplemented!(), }; diff --git a/wgpu-hal/src/metal/conv.rs b/wgpu-hal/src/metal/conv.rs index f56141d5a7..c6a213e0d0 100644 --- a/wgpu-hal/src/metal/conv.rs +++ b/wgpu-hal/src/metal/conv.rs @@ -192,6 +192,10 @@ pub fn map_vertex_format(format: wgt::VertexFormat) -> metal::MTLVertexFormat { use wgt::VertexFormat as Vf; match format { + Vf::Unorm8 => UCharNormalized, + Vf::Snorm8 => CharNormalized, + Vf::Uint8 => UChar, + Vf::Sint8 => Char, Vf::Unorm8x2 => UChar2Normalized, Vf::Snorm8x2 => Char2Normalized, Vf::Uint8x2 => UChar2, @@ -200,6 +204,11 @@ pub fn map_vertex_format(format: wgt::VertexFormat) -> metal::MTLVertexFormat { Vf::Snorm8x4 => Char4Normalized, Vf::Uint8x4 => UChar4, Vf::Sint8x4 => Char4, + Vf::Unorm16 => UShortNormalized, + Vf::Snorm16 => ShortNormalized, + Vf::Uint16 => UShort, + Vf::Sint16 => Short, + Vf::Float16 => Half, Vf::Unorm16x2 => UShort2Normalized, Vf::Snorm16x2 => Short2Normalized, Vf::Uint16x2 => UShort2, @@ -223,6 +232,7 @@ pub fn map_vertex_format(format: wgt::VertexFormat) -> metal::MTLVertexFormat { Vf::Sint32x4 => Int4, Vf::Float32x4 => Float4, Vf::Unorm10_10_10_2 => UInt1010102Normalized, + Vf::Unorm8x4Bgra => UChar4Normalized_BGRA, Vf::Float64 | Vf::Float64x2 | Vf::Float64x3 | Vf::Float64x4 => unimplemented!(), } } diff --git a/wgpu-hal/src/metal/device.rs b/wgpu-hal/src/metal/device.rs index 070b305747..73d6bcc0e2 100644 --- a/wgpu-hal/src/metal/device.rs +++ b/wgpu-hal/src/metal/device.rs @@ -62,22 +62,31 @@ fn create_depth_stencil_desc(state: &wgt::DepthStencilState) -> metal::DepthSten const fn convert_vertex_format_to_naga(format: wgt::VertexFormat) -> naga::back::msl::VertexFormat { match format { + wgt::VertexFormat::Uint8 => naga::back::msl::VertexFormat::Uint8, wgt::VertexFormat::Uint8x2 => naga::back::msl::VertexFormat::Uint8x2, wgt::VertexFormat::Uint8x4 => naga::back::msl::VertexFormat::Uint8x4, + wgt::VertexFormat::Sint8 => naga::back::msl::VertexFormat::Sint8, wgt::VertexFormat::Sint8x2 => naga::back::msl::VertexFormat::Sint8x2, wgt::VertexFormat::Sint8x4 => naga::back::msl::VertexFormat::Sint8x4, + wgt::VertexFormat::Unorm8 => naga::back::msl::VertexFormat::Unorm8, wgt::VertexFormat::Unorm8x2 => naga::back::msl::VertexFormat::Unorm8x2, wgt::VertexFormat::Unorm8x4 => naga::back::msl::VertexFormat::Unorm8x4, + wgt::VertexFormat::Snorm8 => naga::back::msl::VertexFormat::Snorm8, wgt::VertexFormat::Snorm8x2 => naga::back::msl::VertexFormat::Snorm8x2, wgt::VertexFormat::Snorm8x4 => naga::back::msl::VertexFormat::Snorm8x4, + wgt::VertexFormat::Uint16 => naga::back::msl::VertexFormat::Uint16, wgt::VertexFormat::Uint16x2 => naga::back::msl::VertexFormat::Uint16x2, wgt::VertexFormat::Uint16x4 => naga::back::msl::VertexFormat::Uint16x4, + wgt::VertexFormat::Sint16 => naga::back::msl::VertexFormat::Sint16, wgt::VertexFormat::Sint16x2 => naga::back::msl::VertexFormat::Sint16x2, wgt::VertexFormat::Sint16x4 => naga::back::msl::VertexFormat::Sint16x4, + wgt::VertexFormat::Unorm16 => naga::back::msl::VertexFormat::Unorm16, wgt::VertexFormat::Unorm16x2 => naga::back::msl::VertexFormat::Unorm16x2, wgt::VertexFormat::Unorm16x4 => naga::back::msl::VertexFormat::Unorm16x4, + wgt::VertexFormat::Snorm16 => naga::back::msl::VertexFormat::Snorm16, wgt::VertexFormat::Snorm16x2 => naga::back::msl::VertexFormat::Snorm16x2, wgt::VertexFormat::Snorm16x4 => naga::back::msl::VertexFormat::Snorm16x4, + wgt::VertexFormat::Float16 => naga::back::msl::VertexFormat::Float16, wgt::VertexFormat::Float16x2 => naga::back::msl::VertexFormat::Float16x2, wgt::VertexFormat::Float16x4 => naga::back::msl::VertexFormat::Float16x4, wgt::VertexFormat::Float32 => naga::back::msl::VertexFormat::Float32, @@ -93,7 +102,14 @@ const fn convert_vertex_format_to_naga(format: wgt::VertexFormat) -> naga::back: wgt::VertexFormat::Sint32x3 => naga::back::msl::VertexFormat::Sint32x3, wgt::VertexFormat::Sint32x4 => naga::back::msl::VertexFormat::Sint32x4, wgt::VertexFormat::Unorm10_10_10_2 => naga::back::msl::VertexFormat::Unorm10_10_10_2, - _ => unimplemented!(), + wgt::VertexFormat::Unorm8x4Bgra => naga::back::msl::VertexFormat::Unorm8x4Bgra, + + wgt::VertexFormat::Float64 + | wgt::VertexFormat::Float64x2 + | wgt::VertexFormat::Float64x3 + | wgt::VertexFormat::Float64x4 => { + unimplemented!() + } } } diff --git a/wgpu-hal/src/vulkan/conv.rs b/wgpu-hal/src/vulkan/conv.rs index 21ebd6c7b5..b5ae72b4db 100644 --- a/wgpu-hal/src/vulkan/conv.rs +++ b/wgpu-hal/src/vulkan/conv.rs @@ -375,22 +375,31 @@ pub fn map_index_format(index_format: wgt::IndexFormat) -> vk::IndexType { pub fn map_vertex_format(vertex_format: wgt::VertexFormat) -> vk::Format { use wgt::VertexFormat as Vf; match vertex_format { + Vf::Uint8 => vk::Format::R8_UINT, Vf::Uint8x2 => vk::Format::R8G8_UINT, Vf::Uint8x4 => vk::Format::R8G8B8A8_UINT, + Vf::Sint8 => vk::Format::R8_SINT, Vf::Sint8x2 => vk::Format::R8G8_SINT, Vf::Sint8x4 => vk::Format::R8G8B8A8_SINT, + Vf::Unorm8 => vk::Format::R8_UNORM, Vf::Unorm8x2 => vk::Format::R8G8_UNORM, Vf::Unorm8x4 => vk::Format::R8G8B8A8_UNORM, + Vf::Snorm8 => vk::Format::R8_SNORM, Vf::Snorm8x2 => vk::Format::R8G8_SNORM, Vf::Snorm8x4 => vk::Format::R8G8B8A8_SNORM, + Vf::Uint16 => vk::Format::R16_UINT, Vf::Uint16x2 => vk::Format::R16G16_UINT, Vf::Uint16x4 => vk::Format::R16G16B16A16_UINT, + Vf::Sint16 => vk::Format::R16_SINT, Vf::Sint16x2 => vk::Format::R16G16_SINT, Vf::Sint16x4 => vk::Format::R16G16B16A16_SINT, + Vf::Unorm16 => vk::Format::R16_UNORM, Vf::Unorm16x2 => vk::Format::R16G16_UNORM, Vf::Unorm16x4 => vk::Format::R16G16B16A16_UNORM, + Vf::Snorm16 => vk::Format::R16_SNORM, Vf::Snorm16x2 => vk::Format::R16G16_SNORM, Vf::Snorm16x4 => vk::Format::R16G16B16A16_SNORM, + Vf::Float16 => vk::Format::R16_SFLOAT, Vf::Float16x2 => vk::Format::R16G16_SFLOAT, Vf::Float16x4 => vk::Format::R16G16B16A16_SFLOAT, Vf::Float32 => vk::Format::R32_SFLOAT, @@ -410,6 +419,7 @@ pub fn map_vertex_format(vertex_format: wgt::VertexFormat) -> vk::Format { Vf::Float64x3 => vk::Format::R64G64B64_SFLOAT, Vf::Float64x4 => vk::Format::R64G64B64A64_SFLOAT, Vf::Unorm10_10_10_2 => vk::Format::A2B10G10R10_UNORM_PACK32, + Vf::Unorm8x4Bgra => vk::Format::B8G8R8A8_UNORM, } } diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index a7d1d6d8c1..b486f5fe06 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -5162,77 +5162,98 @@ pub struct VertexAttribute { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))] pub enum VertexFormat { + /// One unsigned byte (u8). `u32` in shaders. + Uint8 = 0, /// Two unsigned bytes (u8). `vec2` in shaders. - Uint8x2 = 0, + Uint8x2 = 1, /// Four unsigned bytes (u8). `vec4` in shaders. - Uint8x4 = 1, + Uint8x4 = 2, + /// One signed byte (i8). `i32` in shaders. + Sint8 = 3, /// Two signed bytes (i8). `vec2` in shaders. - Sint8x2 = 2, + Sint8x2 = 4, /// Four signed bytes (i8). `vec4` in shaders. - Sint8x4 = 3, + Sint8x4 = 5, + /// One unsigned byte (u8). [0, 255] converted to float [0, 1] `f32` in shaders. + Unorm8 = 6, /// Two unsigned bytes (u8). [0, 255] converted to float [0, 1] `vec2` in shaders. - Unorm8x2 = 4, + Unorm8x2 = 7, /// Four unsigned bytes (u8). [0, 255] converted to float [0, 1] `vec4` in shaders. - Unorm8x4 = 5, + Unorm8x4 = 8, + /// One signed byte (i8). [-127, 127] converted to float [-1, 1] `f32` in shaders. + Snorm8 = 9, /// Two signed bytes (i8). [-127, 127] converted to float [-1, 1] `vec2` in shaders. - Snorm8x2 = 6, + Snorm8x2 = 10, /// Four signed bytes (i8). [-127, 127] converted to float [-1, 1] `vec4` in shaders. - Snorm8x4 = 7, + Snorm8x4 = 11, + /// One unsigned short (u16). `u32` in shaders. + Uint16 = 12, /// Two unsigned shorts (u16). `vec2` in shaders. - Uint16x2 = 8, + Uint16x2 = 13, /// Four unsigned shorts (u16). `vec4` in shaders. - Uint16x4 = 9, + Uint16x4 = 14, + /// One signed short (u16). `i32` in shaders. + Sint16 = 15, /// Two signed shorts (i16). `vec2` in shaders. - Sint16x2 = 10, + Sint16x2 = 16, /// Four signed shorts (i16). `vec4` in shaders. - Sint16x4 = 11, + Sint16x4 = 17, + /// One unsigned short (u16). [0, 65535] converted to float [0, 1] `f32` in shaders. + Unorm16 = 18, /// Two unsigned shorts (u16). [0, 65535] converted to float [0, 1] `vec2` in shaders. - Unorm16x2 = 12, + Unorm16x2 = 19, /// Four unsigned shorts (u16). [0, 65535] converted to float [0, 1] `vec4` in shaders. - Unorm16x4 = 13, + Unorm16x4 = 20, + /// One signed short (i16). [-32767, 32767] converted to float [-1, 1] `f32` in shaders. + Snorm16 = 21, /// Two signed shorts (i16). [-32767, 32767] converted to float [-1, 1] `vec2` in shaders. - Snorm16x2 = 14, + Snorm16x2 = 22, /// Four signed shorts (i16). [-32767, 32767] converted to float [-1, 1] `vec4` in shaders. - Snorm16x4 = 15, + Snorm16x4 = 23, + /// One half-precision float (no Rust equiv). `f32` in shaders. + Float16 = 24, /// Two half-precision floats (no Rust equiv). `vec2` in shaders. - Float16x2 = 16, + Float16x2 = 25, /// Four half-precision floats (no Rust equiv). `vec4` in shaders. - Float16x4 = 17, + Float16x4 = 26, /// One single-precision float (f32). `f32` in shaders. - Float32 = 18, + Float32 = 27, /// Two single-precision floats (f32). `vec2` in shaders. - Float32x2 = 19, + Float32x2 = 28, /// Three single-precision floats (f32). `vec3` in shaders. - Float32x3 = 20, + Float32x3 = 29, /// Four single-precision floats (f32). `vec4` in shaders. - Float32x4 = 21, + Float32x4 = 30, /// One unsigned int (u32). `u32` in shaders. - Uint32 = 22, + Uint32 = 31, /// Two unsigned ints (u32). `vec2` in shaders. - Uint32x2 = 23, + Uint32x2 = 32, /// Three unsigned ints (u32). `vec3` in shaders. - Uint32x3 = 24, + Uint32x3 = 33, /// Four unsigned ints (u32). `vec4` in shaders. - Uint32x4 = 25, + Uint32x4 = 34, /// One signed int (i32). `i32` in shaders. - Sint32 = 26, + Sint32 = 35, /// Two signed ints (i32). `vec2` in shaders. - Sint32x2 = 27, + Sint32x2 = 36, /// Three signed ints (i32). `vec3` in shaders. - Sint32x3 = 28, + Sint32x3 = 37, /// Four signed ints (i32). `vec4` in shaders. - Sint32x4 = 29, + Sint32x4 = 38, /// One double-precision float (f64). `f32` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`]. - Float64 = 30, + Float64 = 39, /// Two double-precision floats (f64). `vec2` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`]. - Float64x2 = 31, + Float64x2 = 40, /// Three double-precision floats (f64). `vec3` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`]. - Float64x3 = 32, + Float64x3 = 41, /// Four double-precision floats (f64). `vec4` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`]. - Float64x4 = 33, + Float64x4 = 42, /// Three unsigned 10-bit integers and one 2-bit integer, packed into a 32-bit integer (u32). [0, 1024] converted to float [0, 1] `vec4` in shaders. #[cfg_attr(feature = "serde", serde(rename = "unorm10-10-10-2"))] - Unorm10_10_10_2 = 34, + Unorm10_10_10_2 = 43, + /// Four unsigned 8-bit integers, packed into a 32-bit integer (u32). [0, 255] converted to float [0, 1] `vec4` in shaders. + #[cfg_attr(feature = "serde", serde(rename = "unorm8x4-bgra"))] + Unorm8x4Bgra = 44, } impl VertexFormat { @@ -5240,7 +5261,16 @@ impl VertexFormat { #[must_use] pub const fn size(&self) -> u64 { match self { - Self::Uint8x2 | Self::Sint8x2 | Self::Unorm8x2 | Self::Snorm8x2 => 2, + Self::Uint8 | Self::Sint8 | Self::Unorm8 | Self::Snorm8 => 1, + Self::Uint8x2 + | Self::Sint8x2 + | Self::Unorm8x2 + | Self::Snorm8x2 + | Self::Uint16 + | Self::Sint16 + | Self::Unorm16 + | Self::Snorm16 + | Self::Float16 => 2, Self::Uint8x4 | Self::Sint8x4 | Self::Unorm8x4 @@ -5253,7 +5283,8 @@ impl VertexFormat { | Self::Float32 | Self::Uint32 | Self::Sint32 - | Self::Unorm10_10_10_2 => 4, + | Self::Unorm10_10_10_2 + | Self::Unorm8x4Bgra => 4, Self::Uint16x4 | Self::Sint16x4 | Self::Unorm16x4 diff --git a/wgpu/src/backend/webgpu.rs b/wgpu/src/backend/webgpu.rs index f0af7d0d75..2e16c603b2 100644 --- a/wgpu/src/backend/webgpu.rs +++ b/wgpu/src/backend/webgpu.rs @@ -526,22 +526,31 @@ fn map_vertex_format(format: wgt::VertexFormat) -> webgpu_sys::GpuVertexFormat { use webgpu_sys::GpuVertexFormat as vf; use wgt::VertexFormat; match format { + VertexFormat::Uint8 => vf::Uint8, VertexFormat::Uint8x2 => vf::Uint8x2, VertexFormat::Uint8x4 => vf::Uint8x4, + VertexFormat::Sint8 => vf::Sint8, VertexFormat::Sint8x2 => vf::Sint8x2, VertexFormat::Sint8x4 => vf::Sint8x4, + VertexFormat::Unorm8 => vf::Unorm8, VertexFormat::Unorm8x2 => vf::Unorm8x2, VertexFormat::Unorm8x4 => vf::Unorm8x4, + VertexFormat::Snorm8 => vf::Snorm8, VertexFormat::Snorm8x2 => vf::Snorm8x2, VertexFormat::Snorm8x4 => vf::Snorm8x4, + VertexFormat::Uint16 => vf::Uint16, VertexFormat::Uint16x2 => vf::Uint16x2, VertexFormat::Uint16x4 => vf::Uint16x4, + VertexFormat::Sint16 => vf::Sint16, VertexFormat::Sint16x2 => vf::Sint16x2, VertexFormat::Sint16x4 => vf::Sint16x4, + VertexFormat::Unorm16 => vf::Unorm16, VertexFormat::Unorm16x2 => vf::Unorm16x2, VertexFormat::Unorm16x4 => vf::Unorm16x4, + VertexFormat::Snorm16 => vf::Snorm16, VertexFormat::Snorm16x2 => vf::Snorm16x2, VertexFormat::Snorm16x4 => vf::Snorm16x4, + VertexFormat::Float16 => vf::Float16, VertexFormat::Float16x2 => vf::Float16x2, VertexFormat::Float16x4 => vf::Float16x4, VertexFormat::Float32 => vf::Float32, @@ -557,6 +566,7 @@ fn map_vertex_format(format: wgt::VertexFormat) -> webgpu_sys::GpuVertexFormat { VertexFormat::Sint32x3 => vf::Sint32x3, VertexFormat::Sint32x4 => vf::Sint32x4, VertexFormat::Unorm10_10_10_2 => vf::Unorm1010102, + VertexFormat::Unorm8x4Bgra => vf::Unorm8x4Bgra, VertexFormat::Float64 | VertexFormat::Float64x2 | VertexFormat::Float64x3