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