naga_types/lib.rs
1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![no_std]
3extern crate alloc;
4#[cfg(any(feature = "std", test))]
5extern crate std;
6
7pub mod glsl;
8pub mod hlsl;
9pub mod msl;
10pub mod spv;
11pub mod wgsl;
12
13/// Create a Markdown link definition referring to the `wgpu` crate.
14///
15/// This macro should be used inside a `#[doc = ...]` attribute.
16/// The two arguments should be string literals or macros that expand to string literals.
17/// If the module in which the item using this macro is located is not the crate root,
18/// use the `../` syntax.
19///
20/// We cannot simply use rustdoc links to `wgpu` because it is one of our dependents.
21/// This link adapts to work in locally generated documentation (`cargo doc`) by default,
22/// and work with `docs.rs` URL structure when building for `docs.rs`.
23///
24/// Note: This macro cannot be used outside this crate, because `cfg(docsrs)` will not apply.
25#[cfg(not(docsrs))]
26#[macro_export]
27macro_rules! link_to_wgpu_docs {
28 ([$reference:expr]: $url_path:expr) => {
29 concat!("[", $reference, "]: ../wgpu/", $url_path)
30 };
31
32 (../ [$reference:expr]: $url_path:expr) => {
33 concat!("[", $reference, "]: ../../wgpu/", $url_path)
34 };
35}
36#[cfg(docsrs)]
37#[macro_export]
38macro_rules! link_to_wgpu_docs {
39 ($(../)? [$reference:expr]: $url_path:expr) => {
40 concat!(
41 "[",
42 $reference,
43 // URL path will have a base URL of https://docs.rs/
44 "]: /wgpu/",
45 // The version of wgpu-types is not necessarily the same as the version of wgpu
46 // if a patch release of either has been published, so we cannot use the full version
47 // number. docs.rs will interpret this single number as a Cargo-style version
48 // requirement and redirect to the latest compatible version.
49 //
50 // This technique would break if `wgpu` and `wgpu-types` ever switch to having distinct
51 // major version numbering. An alternative would be to hardcode the corresponding `wgpu`
52 // version, but that would give us another thing to forget to update.
53 env!("CARGO_PKG_VERSION_MAJOR"),
54 "/wgpu/",
55 $url_path
56 )
57 };
58}
59
60/// Create a Markdown link definition referring to an item in the `wgpu` crate.
61///
62/// This macro should be used inside a `#[doc = ...]` attribute.
63/// See [`link_to_wgpu_docs`] for more details.
64#[macro_export]
65macro_rules! link_to_wgpu_item {
66 ($kind:ident $name:ident) => {
67 $crate::link_to_wgpu_docs!(
68 [concat!("`", stringify!($name), "`")]: concat!(stringify!($kind), ".", stringify!($name), ".html")
69 )
70 };
71}
72
73/// Create a Markdown link definition referring to the `wgpu_core` crate.
74///
75/// This macro should be used inside a `#[doc = ...]` attribute.
76/// See [`link_to_wgpu_docs`] for more details.
77#[cfg(not(docsrs))]
78#[macro_export]
79macro_rules! link_to_wgc_docs {
80 ([$reference:expr]: $url_path:expr) => {
81 concat!("[", $reference, "]: ../wgpu_core/", $url_path)
82 };
83
84 (../ [$reference:expr]: $url_path:expr) => {
85 concat!("[", $reference, "]: ../../wgpu_core/", $url_path)
86 };
87}
88#[cfg(docsrs)]
89#[macro_export]
90macro_rules! link_to_wgc_docs {
91 ($(../)? [$reference:expr]: $url_path:expr) => {
92 concat!(
93 "[",
94 $reference,
95 // URL path will have a base URL of https://docs.rs/
96 "]: /wgpu_core/",
97 // The version of wgpu-types is not necessarily the same as the version of wgpu_core
98 // if a patch release of either has been published, so we cannot use the full version
99 // number. docs.rs will interpret this single number as a Cargo-style version
100 // requirement and redirect to the latest compatible version.
101 //
102 // This technique would break if `wgpu_core` and `wgpu-types` ever switch to having
103 // distinct major version numbering. An alternative would be to hardcode the
104 // corresponding `wgpu_core` version, but that would give us another thing to forget
105 // to update.
106 env!("CARGO_PKG_VERSION_MAJOR"),
107 "/wgpu_core/",
108 $url_path
109 )
110 };
111}
112
113/// Stage of the programmable pipeline.
114#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
115#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
116#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
117#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
118pub enum ShaderStage {
119 /// A vertex shader, in a render pipeline.
120 Vertex,
121
122 /// A task shader, in a mesh render pipeline.
123 Task,
124
125 /// A mesh shader, in a mesh render pipeline.
126 Mesh,
127
128 /// A fragment shader, in a render pipeline.
129 Fragment,
130
131 /// Compute pipeline shader.
132 Compute,
133
134 /// A ray generation shader, in a ray tracing pipeline.
135 RayGeneration,
136
137 /// A miss shader, in a ray tracing pipeline.
138 Miss,
139
140 /// A any hit shader, in a ray tracing pipeline.
141 AnyHit,
142
143 /// A closest hit shader, in a ray tracing pipeline.
144 ClosestHit,
145}
146
147impl ShaderStage {
148 pub const fn compute_like(self) -> bool {
149 match self {
150 Self::Vertex | Self::Fragment => false,
151 Self::Compute | Self::Task | Self::Mesh => true,
152 Self::RayGeneration | Self::AnyHit | Self::ClosestHit | Self::Miss => false,
153 }
154 }
155
156 /// Mesh or task shader
157 pub const fn mesh_like(self) -> bool {
158 matches!(self, Self::Task | Self::Mesh)
159 }
160}
161
162/// Hash map that is faster but not resilient to DoS attacks.
163/// (Similar to rustc_hash::FxHashMap but using hashbrown::HashMap instead of alloc::collections::HashMap.)
164/// To construct a new instance: `FastHashMap::default()`
165pub type FastHashMap<K, T> =
166 hashbrown::HashMap<K, T, core::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
167
168/// Hash set that is faster but not resilient to DoS attacks.
169/// (Similar to rustc_hash::FxHashSet but using hashbrown::HashSet instead of alloc::collections::HashMap.)
170pub type FastHashSet<K> =
171 hashbrown::HashSet<K, core::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
172
173/// Insertion-order-preserving hash set (`IndexSet<K>`), but with the same
174/// hasher as `FastHashSet<K>` (faster but not resilient to DoS attacks).
175pub type FastIndexSet<K> =
176 indexmap::IndexSet<K, core::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
177
178/// Insertion-order-preserving hash map (`IndexMap<K, V>`), but with the same
179/// hasher as `FastHashMap<K, V>` (faster but not resilient to DoS attacks).
180pub type FastIndexMap<K, V> =
181 indexmap::IndexMap<K, V, core::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
182
183/// Pipeline binding information for global resources.
184#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
185#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
186#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
187#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
188pub struct ResourceBinding {
189 /// The bind group index.
190 pub group: u32,
191 /// Binding number within the group.
192 pub binding: u32,
193}
194
195#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
196#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
197#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
198pub struct TaskDispatchLimits {
199 pub max_mesh_workgroups_per_dim: u32,
200 pub max_mesh_workgroups_total: u32,
201}
202
203/// Corresponds to [WebGPU `GPUVertexFormat`](
204/// https://gpuweb.github.io/gpuweb/#enumdef-gpuvertexformat).
205#[repr(u32)]
206#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
207#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
208#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
209#[cfg_attr(
210 any(feature = "serialize", feature = "deserialize"),
211 serde(rename_all = "lowercase")
212)]
213pub enum VertexFormat {
214 /// One unsigned byte (u8). `u32` in shaders.
215 Uint8 = 0,
216 /// Two unsigned bytes (u8). `vec2<u32>` in shaders.
217 Uint8x2 = 1,
218 /// Four unsigned bytes (u8). `vec4<u32>` in shaders.
219 Uint8x4 = 2,
220 /// One signed byte (i8). `i32` in shaders.
221 Sint8 = 3,
222 /// Two signed bytes (i8). `vec2<i32>` in shaders.
223 Sint8x2 = 4,
224 /// Four signed bytes (i8). `vec4<i32>` in shaders.
225 Sint8x4 = 5,
226 /// One unsigned byte (u8). [0, 255] converted to float [0, 1] `f32` in shaders.
227 Unorm8 = 6,
228 /// Two unsigned bytes (u8). [0, 255] converted to float [0, 1] `vec2<f32>` in shaders.
229 Unorm8x2 = 7,
230 /// Four unsigned bytes (u8). [0, 255] converted to float [0, 1] `vec4<f32>` in shaders.
231 Unorm8x4 = 8,
232 /// One signed byte (i8). [−127, 127] converted to float [−1, 1] `f32` in shaders.
233 Snorm8 = 9,
234 /// Two signed bytes (i8). [−127, 127] converted to float [−1, 1] `vec2<f32>` in shaders.
235 Snorm8x2 = 10,
236 /// Four signed bytes (i8). [−127, 127] converted to float [−1, 1] `vec4<f32>` in shaders.
237 Snorm8x4 = 11,
238 /// One unsigned short (u16). `u32` in shaders.
239 Uint16 = 12,
240 /// Two unsigned shorts (u16). `vec2<u32>` in shaders.
241 Uint16x2 = 13,
242 /// Four unsigned shorts (u16). `vec4<u32>` in shaders.
243 Uint16x4 = 14,
244 /// One signed short (i16). `i32` in shaders.
245 Sint16 = 15,
246 /// Two signed shorts (i16). `vec2<i32>` in shaders.
247 Sint16x2 = 16,
248 /// Four signed shorts (i16). `vec4<i32>` in shaders.
249 Sint16x4 = 17,
250 /// One unsigned short (u16). [0, 65535] converted to float [0, 1] `f32` in shaders.
251 Unorm16 = 18,
252 /// Two unsigned shorts (u16). [0, 65535] converted to float [0, 1] `vec2<f32>` in shaders.
253 Unorm16x2 = 19,
254 /// Four unsigned shorts (u16). [0, 65535] converted to float [0, 1] `vec4<f32>` in shaders.
255 Unorm16x4 = 20,
256 /// One signed short (i16). [−32767, 32767] converted to float [−1, 1] `f32` in shaders.
257 Snorm16 = 21,
258 /// Two signed shorts (i16). [−32767, 32767] converted to float [−1, 1] `vec2<f32>` in shaders.
259 Snorm16x2 = 22,
260 /// Four signed shorts (i16). [−32767, 32767] converted to float [−1, 1] `vec4<f32>` in shaders.
261 Snorm16x4 = 23,
262 /// One half-precision float (no Rust equiv). `f32` in shaders.
263 Float16 = 24,
264 /// Two half-precision floats (no Rust equiv). `vec2<f32>` in shaders.
265 Float16x2 = 25,
266 /// Four half-precision floats (no Rust equiv). `vec4<f32>` in shaders.
267 Float16x4 = 26,
268 /// One single-precision float (f32). `f32` in shaders.
269 Float32 = 27,
270 /// Two single-precision floats (f32). `vec2<f32>` in shaders.
271 Float32x2 = 28,
272 /// Three single-precision floats (f32). `vec3<f32>` in shaders.
273 Float32x3 = 29,
274 /// Four single-precision floats (f32). `vec4<f32>` in shaders.
275 Float32x4 = 30,
276 /// One unsigned int (u32). `u32` in shaders.
277 Uint32 = 31,
278 /// Two unsigned ints (u32). `vec2<u32>` in shaders.
279 Uint32x2 = 32,
280 /// Three unsigned ints (u32). `vec3<u32>` in shaders.
281 Uint32x3 = 33,
282 /// Four unsigned ints (u32). `vec4<u32>` in shaders.
283 Uint32x4 = 34,
284 /// One signed int (i32). `i32` in shaders.
285 Sint32 = 35,
286 /// Two signed ints (i32). `vec2<i32>` in shaders.
287 Sint32x2 = 36,
288 /// Three signed ints (i32). `vec3<i32>` in shaders.
289 Sint32x3 = 37,
290 /// Four signed ints (i32). `vec4<i32>` in shaders.
291 Sint32x4 = 38,
292 /// One double-precision float (f64). `f32` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
293 ///
294 /// [`Features::VERTEX_ATTRIBUTE_64BIT`]: ../wgpu/struct.Features.html#associatedconstant.VERTEX_ATTRIBUTE_64BIT
295 Float64 = 39,
296 /// Two double-precision floats (f64). `vec2<f32>` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
297 ///
298 /// [`Features::VERTEX_ATTRIBUTE_64BIT`]: ../wgpu/struct.Features.html#associatedconstant.VERTEX_ATTRIBUTE_64BIT
299 Float64x2 = 40,
300 /// Three double-precision floats (f64). `vec3<f32>` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
301 ///
302 /// [`Features::VERTEX_ATTRIBUTE_64BIT`]: ../wgpu/struct.Features.html#associatedconstant.VERTEX_ATTRIBUTE_64BIT
303 Float64x3 = 41,
304 /// Four double-precision floats (f64). `vec4<f32>` in shaders. Requires [`Features::VERTEX_ATTRIBUTE_64BIT`].
305 ///
306 /// [`Features::VERTEX_ATTRIBUTE_64BIT`]: ../wgpu/struct.Features.html#associatedconstant.VERTEX_ATTRIBUTE_64BIT
307 Float64x4 = 42,
308 /// Three unsigned 10-bit integers and one 2-bit integer, packed into a 32-bit integer (u32). [0, 1023] and [0, 3] converted to float [0, 1] `vec4<f32>` in shaders.
309 #[cfg_attr(
310 any(feature = "serialize", feature = "deserialize"),
311 serde(rename = "unorm10-10-10-2")
312 )]
313 Unorm10_10_10_2 = 43,
314 /// Four unsigned 8-bit integers (u8) in BGRA. [0, 255] converted to float [0, 1] `vec4<f32>` RGBA in shaders.
315 #[cfg_attr(
316 any(feature = "serialize", feature = "deserialize"),
317 serde(rename = "unorm8x4-bgra")
318 )]
319 Unorm8x4Bgra = 44,
320 /// Three signed 10-bit integers and one 2-bit integer, packed into a 32-bit integer (u32). [−511, 511] and [−1, 1] converted to float [−1, 1] `vec4<f32>` in shaders.
321 #[cfg_attr(
322 any(feature = "serialize", feature = "deserialize"),
323 serde(rename = "snorm10-10-10-2")
324 )]
325 Snorm10_10_10_2 = 45,
326}
327
328impl VertexFormat {
329 /// Returns the byte size of the format.
330 #[must_use]
331 pub const fn size(&self) -> u64 {
332 match self {
333 Self::Uint8 | Self::Sint8 | Self::Unorm8 | Self::Snorm8 => 1,
334 Self::Uint8x2
335 | Self::Sint8x2
336 | Self::Unorm8x2
337 | Self::Snorm8x2
338 | Self::Uint16
339 | Self::Sint16
340 | Self::Unorm16
341 | Self::Snorm16
342 | Self::Float16 => 2,
343 Self::Uint8x4
344 | Self::Sint8x4
345 | Self::Unorm8x4
346 | Self::Snorm8x4
347 | Self::Uint16x2
348 | Self::Sint16x2
349 | Self::Unorm16x2
350 | Self::Snorm16x2
351 | Self::Float16x2
352 | Self::Float32
353 | Self::Uint32
354 | Self::Sint32
355 | Self::Unorm10_10_10_2
356 | Self::Unorm8x4Bgra
357 | Self::Snorm10_10_10_2 => 4,
358 Self::Uint16x4
359 | Self::Sint16x4
360 | Self::Unorm16x4
361 | Self::Snorm16x4
362 | Self::Float16x4
363 | Self::Float32x2
364 | Self::Uint32x2
365 | Self::Sint32x2
366 | Self::Float64 => 8,
367 Self::Float32x3 | Self::Uint32x3 | Self::Sint32x3 => 12,
368 Self::Float32x4 | Self::Uint32x4 | Self::Sint32x4 | Self::Float64x2 => 16,
369 Self::Float64x3 => 24,
370 Self::Float64x4 => 32,
371 }
372 }
373
374 /// Returns the size read by an acceleration structure build of the vertex format. This is
375 /// slightly different from [`Self::size`] because the alpha component of 4-component formats
376 /// are not read in an acceleration structure build, allowing for a smaller stride.
377 #[must_use]
378 pub const fn min_acceleration_structure_vertex_stride(&self) -> u64 {
379 match self {
380 Self::Float16x2 | Self::Snorm16x2 => 4,
381 Self::Float32x3 => 12,
382 Self::Float32x2 => 8,
383 // This is the minimum value from DirectX
384 // > A16 component is ignored, other data can be packed there, such as setting vertex stride to 6 bytes
385 //
386 // https://microsoft.github.io/DirectX-Specs/d3d/Raytracing.html#d3d12_raytracing_geometry_triangles_desc
387 //
388 // Vulkan does not express a minimum stride.
389 Self::Float16x4 | Self::Snorm16x4 => 6,
390 _ => unreachable!(),
391 }
392 }
393
394 /// Returns the alignment required for `wgpu::BlasTriangleGeometry::vertex_stride`
395 #[must_use]
396 pub const fn acceleration_structure_stride_alignment(&self) -> u64 {
397 match self {
398 Self::Float16x4 | Self::Float16x2 | Self::Snorm16x4 | Self::Snorm16x2 => 2,
399 Self::Float32x2 | Self::Float32x3 => 4,
400 _ => unreachable!(),
401 }
402 }
403}