wgpu_types/
vertex.rs

1//! Types for defining vertex attributes and their buffers.
2
3#[cfg(any(feature = "serde", test))]
4use serde::{Deserialize, Serialize};
5
6use crate::{link_to_wgpu_docs, link_to_wgpu_item};
7
8#[cfg(doc)]
9use crate::Features;
10
11/// Whether a vertex buffer is indexed by vertex or by instance.
12///
13/// Consider a call to [`RenderPass::draw`] like this:
14///
15/// ```ignore
16/// render_pass.draw(vertices, instances)
17/// ```
18///
19/// where `vertices` is a `Range<u32>` of vertex indices, and
20/// `instances` is a `Range<u32>` of instance indices.
21///
22/// For this call, `wgpu` invokes the vertex shader entry point once
23/// for every possible `(v, i)` pair, where `v` is drawn from
24/// `vertices` and `i` is drawn from `instances`. These invocations
25/// may happen in any order, and will usually run in parallel.
26///
27/// Each vertex buffer has a step mode, established by the
28/// [`step_mode`] field of its [`VertexBufferLayout`], given when the
29/// pipeline was created. Buffers whose step mode is [`Vertex`] use
30/// `v` as the index into their contents, whereas buffers whose step
31/// mode is [`Instance`] use `i`. The indicated buffer element then
32/// contributes zero or more attribute values for the `(v, i)` vertex
33/// shader invocation to use, based on the [`VertexBufferLayout`]'s
34/// [`attributes`] list.
35///
36/// You can visualize the results from all these vertex shader
37/// invocations as a matrix with a row for each `i` from `instances`,
38/// and with a column for each `v` from `vertices`. In one sense, `v`
39/// and `i` are symmetrical: both are used to index vertex buffers and
40/// provide attribute values.  But the key difference between `v` and
41/// `i` is that line and triangle primitives are built from the values
42/// of each row, along which `i` is constant and `v` varies, not the
43/// columns.
44///
45/// An indexed draw call works similarly:
46///
47/// ```ignore
48/// render_pass.draw_indexed(indices, base_vertex, instances)
49/// ```
50///
51/// The only difference is that `v` values are drawn from the contents
52/// of the index buffer&mdash;specifically, the subrange of the index
53/// buffer given by `indices`&mdash;instead of simply being sequential
54/// integers, as they are in a `draw` call.
55///
56/// A non-instanced call, where `instances` is `0..1`, is simply a
57/// matrix with only one row.
58///
59/// Corresponds to [WebGPU `GPUVertexStepMode`](
60/// https://gpuweb.github.io/gpuweb/#enumdef-gpuvertexstepmode).
61///
62#[doc = link_to_wgpu_docs!(["`RenderPass::draw`"]: "struct.RenderPass.html#method.draw")]
63#[doc = link_to_wgpu_item!(struct VertexBufferLayout)]
64#[doc = link_to_wgpu_docs!(["`step_mode`"]: "struct.VertexBufferLayout.html#structfield.step_mode")]
65#[doc = link_to_wgpu_docs!(["`attributes`"]: "struct.VertexBufferLayout.html#structfield.attributes")]
66/// [`Vertex`]: VertexStepMode::Vertex
67/// [`Instance`]: VertexStepMode::Instance
68#[repr(C)]
69#[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq)]
70#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
71#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
72pub enum VertexStepMode {
73    /// Vertex data is advanced every vertex.
74    #[default]
75    Vertex = 0,
76    /// Vertex data is advanced every instance.
77    Instance = 1,
78}
79
80/// Vertex inputs (attributes) to shaders.
81///
82/// These are used to specify the individual attributes within a [`VertexBufferLayout`].
83/// See its documentation for an example.
84///
85/// The [`vertex_attr_array!`] macro can help create these with appropriate offsets.
86///
87/// Corresponds to [WebGPU `GPUVertexAttribute`](
88/// https://gpuweb.github.io/gpuweb/#dictdef-gpuvertexattribute).
89///
90#[doc = link_to_wgpu_docs!(["`vertex_attr_array!`"]: "macro.vertex_attr_array.html")]
91#[doc = link_to_wgpu_item!(struct VertexBufferLayout)]
92#[repr(C)]
93#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
94#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
95#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
96pub struct VertexAttribute {
97    /// Format of the input
98    pub format: VertexFormat,
99    /// Byte offset of the start of the input
100    pub offset: crate::BufferAddress,
101    /// Location for this input. Must match the location in the shader.
102    pub shader_location: crate::ShaderLocation,
103}
104
105/// Vertex Format for a [`VertexAttribute`] (input).
106///
107/// Corresponds to [WebGPU `GPUVertexFormat`](
108/// https://gpuweb.github.io/gpuweb/#enumdef-gpuvertexformat).
109#[repr(C)]
110#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
111#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
112#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
113pub enum VertexFormat {
114    /// One unsigned byte (u8). `u32` in shaders.
115    Uint8 = 0,
116    /// Two unsigned bytes (u8). `vec2<u32>` in shaders.
117    Uint8x2 = 1,
118    /// Four unsigned bytes (u8). `vec4<u32>` in shaders.
119    Uint8x4 = 2,
120    /// One signed byte (i8). `i32` in shaders.
121    Sint8 = 3,
122    /// Two signed bytes (i8). `vec2<i32>` in shaders.
123    Sint8x2 = 4,
124    /// Four signed bytes (i8). `vec4<i32>` in shaders.
125    Sint8x4 = 5,
126    /// One unsigned byte (u8). [0, 255] converted to float [0, 1] `f32` in shaders.
127    Unorm8 = 6,
128    /// Two unsigned bytes (u8). [0, 255] converted to float [0, 1] `vec2<f32>` in shaders.
129    Unorm8x2 = 7,
130    /// Four unsigned bytes (u8). [0, 255] converted to float [0, 1] `vec4<f32>` in shaders.
131    Unorm8x4 = 8,
132    /// One signed byte (i8). [&minus;127, 127] converted to float [&minus;1, 1] `f32` in shaders.
133    Snorm8 = 9,
134    /// Two signed bytes (i8). [&minus;127, 127] converted to float [&minus;1, 1] `vec2<f32>` in shaders.
135    Snorm8x2 = 10,
136    /// Four signed bytes (i8). [&minus;127, 127] converted to float [&minus;1, 1] `vec4<f32>` in shaders.
137    Snorm8x4 = 11,
138    /// One unsigned short (u16). `u32` in shaders.
139    Uint16 = 12,
140    /// Two unsigned shorts (u16). `vec2<u32>` in shaders.
141    Uint16x2 = 13,
142    /// Four unsigned shorts (u16). `vec4<u32>` in shaders.
143    Uint16x4 = 14,
144    /// One signed short (u16). `i32` in shaders.
145    Sint16 = 15,
146    /// Two signed shorts (i16). `vec2<i32>` in shaders.
147    Sint16x2 = 16,
148    /// Four signed shorts (i16). `vec4<i32>` in shaders.
149    Sint16x4 = 17,
150    /// One unsigned short (u16). [0, 65535] converted to float [0, 1] `f32` in shaders.
151    Unorm16 = 18,
152    /// Two unsigned shorts (u16). [0, 65535] converted to float [0, 1] `vec2<f32>` in shaders.
153    Unorm16x2 = 19,
154    /// Four unsigned shorts (u16). [0, 65535] converted to float [0, 1] `vec4<f32>` in shaders.
155    Unorm16x4 = 20,
156    /// One signed short (i16). [&minus;32767, 32767] converted to float [&minus;1, 1] `f32` in shaders.
157    Snorm16 = 21,
158    /// Two signed shorts (i16). [&minus;32767, 32767] converted to float [&minus;1, 1] `vec2<f32>` in shaders.
159    Snorm16x2 = 22,
160    /// Four signed shorts (i16). [&minus;32767, 32767] converted to float [&minus;1, 1] `vec4<f32>` in shaders.
161    Snorm16x4 = 23,
162    /// One half-precision float (no Rust equiv). `f32` in shaders.
163    Float16 = 24,
164    /// Two half-precision floats (no Rust equiv). `vec2<f32>` in shaders.
165    Float16x2 = 25,
166    /// Four half-precision floats (no Rust equiv). `vec4<f32>` in shaders.
167    Float16x4 = 26,
168    /// One single-precision float (f32). `f32` in shaders.
169    Float32 = 27,
170    /// Two single-precision floats (f32). `vec2<f32>` in shaders.
171    Float32x2 = 28,
172    /// Three single-precision floats (f32). `vec3<f32>` in shaders.
173    Float32x3 = 29,
174    /// Four single-precision floats (f32). `vec4<f32>` in shaders.
175    Float32x4 = 30,
176    /// One unsigned int (u32). `u32` in shaders.
177    Uint32 = 31,
178    /// Two unsigned ints (u32). `vec2<u32>` in shaders.
179    Uint32x2 = 32,
180    /// Three unsigned ints (u32). `vec3<u32>` in shaders.
181    Uint32x3 = 33,
182    /// Four unsigned ints (u32). `vec4<u32>` in shaders.
183    Uint32x4 = 34,
184    /// One signed int (i32). `i32` in shaders.
185    Sint32 = 35,
186    /// Two signed ints (i32). `vec2<i32>` in shaders.
187    Sint32x2 = 36,
188    /// Three signed ints (i32). `vec3<i32>` in shaders.
189    Sint32x3 = 37,
190    /// Four signed ints (i32). `vec4<i32>` in shaders.
191    Sint32x4 = 38,
192    /// One double-precision float (f64). `f32` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
193    Float64 = 39,
194    /// Two double-precision floats (f64). `vec2<f32>` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
195    Float64x2 = 40,
196    /// Three double-precision floats (f64). `vec3<f32>` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
197    Float64x3 = 41,
198    /// Four double-precision floats (f64). `vec4<f32>` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
199    Float64x4 = 42,
200    /// 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<f32>` in shaders.
201    #[cfg_attr(feature = "serde", serde(rename = "unorm10-10-10-2"))]
202    Unorm10_10_10_2 = 43,
203    /// Four unsigned 8-bit integers, packed into a 32-bit integer (u32). [0, 255] converted to float [0, 1] `vec4<f32>` in shaders.
204    #[cfg_attr(feature = "serde", serde(rename = "unorm8x4-bgra"))]
205    Unorm8x4Bgra = 44,
206}
207
208impl VertexFormat {
209    /// Returns the byte size of the format.
210    #[must_use]
211    pub const fn size(&self) -> u64 {
212        match self {
213            Self::Uint8 | Self::Sint8 | Self::Unorm8 | Self::Snorm8 => 1,
214            Self::Uint8x2
215            | Self::Sint8x2
216            | Self::Unorm8x2
217            | Self::Snorm8x2
218            | Self::Uint16
219            | Self::Sint16
220            | Self::Unorm16
221            | Self::Snorm16
222            | Self::Float16 => 2,
223            Self::Uint8x4
224            | Self::Sint8x4
225            | Self::Unorm8x4
226            | Self::Snorm8x4
227            | Self::Uint16x2
228            | Self::Sint16x2
229            | Self::Unorm16x2
230            | Self::Snorm16x2
231            | Self::Float16x2
232            | Self::Float32
233            | Self::Uint32
234            | Self::Sint32
235            | Self::Unorm10_10_10_2
236            | Self::Unorm8x4Bgra => 4,
237            Self::Uint16x4
238            | Self::Sint16x4
239            | Self::Unorm16x4
240            | Self::Snorm16x4
241            | Self::Float16x4
242            | Self::Float32x2
243            | Self::Uint32x2
244            | Self::Sint32x2
245            | Self::Float64 => 8,
246            Self::Float32x3 | Self::Uint32x3 | Self::Sint32x3 => 12,
247            Self::Float32x4 | Self::Uint32x4 | Self::Sint32x4 | Self::Float64x2 => 16,
248            Self::Float64x3 => 24,
249            Self::Float64x4 => 32,
250        }
251    }
252
253    /// Returns the size read by an acceleration structure build of the vertex format. This is
254    /// slightly different from [`Self::size`] because the alpha component of 4-component formats
255    /// are not read in an acceleration structure build, allowing for a smaller stride.
256    #[must_use]
257    pub const fn min_acceleration_structure_vertex_stride(&self) -> u64 {
258        match self {
259            Self::Float16x2 | Self::Snorm16x2 => 4,
260            Self::Float32x3 => 12,
261            Self::Float32x2 => 8,
262            // This is the minimum value from DirectX
263            // > A16 component is ignored, other data can be packed there, such as setting vertex stride to 6 bytes
264            //
265            // https://microsoft.github.io/DirectX-Specs/d3d/Raytracing.html#d3d12_raytracing_geometry_triangles_desc
266            //
267            // Vulkan does not express a minimum stride.
268            Self::Float16x4 | Self::Snorm16x4 => 6,
269            _ => unreachable!(),
270        }
271    }
272
273    /// Returns the alignment required for `wgpu::BlasTriangleGeometry::vertex_stride`
274    #[must_use]
275    pub const fn acceleration_structure_stride_alignment(&self) -> u64 {
276        match self {
277            Self::Float16x4 | Self::Float16x2 | Self::Snorm16x4 | Self::Snorm16x2 => 2,
278            Self::Float32x2 | Self::Float32x3 => 4,
279            _ => unreachable!(),
280        }
281    }
282}