Skip to main content

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). [&minus;127, 127] converted to float [&minus;1, 1] `f32` in shaders.
233    Snorm8 = 9,
234    /// Two signed bytes (i8). [&minus;127, 127] converted to float [&minus;1, 1] `vec2<f32>` in shaders.
235    Snorm8x2 = 10,
236    /// Four signed bytes (i8). [&minus;127, 127] converted to float [&minus;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). [&minus;32767, 32767] converted to float [&minus;1, 1] `f32` in shaders.
257    Snorm16 = 21,
258    /// Two signed shorts (i16). [&minus;32767, 32767] converted to float [&minus;1, 1] `vec2<f32>` in shaders.
259    Snorm16x2 = 22,
260    /// Four signed shorts (i16). [&minus;32767, 32767] converted to float [&minus;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). [&minus;511, 511] and [&minus;1, 1] converted to float [&minus;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}