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—specifically, the subrange of the index
53/// buffer given by `indices`—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). [−127, 127] converted to float [−1, 1] `f32` in shaders.
133 Snorm8 = 9,
134 /// Two signed bytes (i8). [−127, 127] converted to float [−1, 1] `vec2<f32>` in shaders.
135 Snorm8x2 = 10,
136 /// Four signed bytes (i8). [−127, 127] converted to float [−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). [−32767, 32767] converted to float [−1, 1] `f32` in shaders.
157 Snorm16 = 21,
158 /// Two signed shorts (i16). [−32767, 32767] converted to float [−1, 1] `vec2<f32>` in shaders.
159 Snorm16x2 = 22,
160 /// Four signed shorts (i16). [−32767, 32767] converted to float [−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}