wgpu/
macros.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//! Convenience macros

#[cfg(doc)]
use crate::{VertexAttribute, VertexBufferLayout, VertexFormat};

/// Macro to produce an array of [`VertexAttribute`].
///
/// The input is a sequence of pairs of shader locations (expression of type [`u32`]) and
/// variant names of [`VertexFormat`].
///
/// The return value has type `[VertexAttribute; N]`, where `N` is the number of inputs.
///
/// Offsets are calculated automatically,
/// using the assumption that there is no padding or other data between attributes.
///
/// # Example
///
/// ```
/// // Suppose that this is our vertex format:
/// #[repr(C, packed)]
/// struct Vertex {
///     foo: [f32; 2],
///     bar: f32,
///     baz: [u16; 4],
/// }
///
/// // Then these attributes match it:
/// let attrs = wgpu::vertex_attr_array![
///     0 => Float32x2,
///     1 => Float32,
///     2 => Uint16x4,
/// ];
///
/// // Here's the full data structure the macro produced:
/// use wgpu::{VertexAttribute as A, VertexFormat as F};
/// assert_eq!(attrs, [
///     A { format: F::Float32x2, offset:  0, shader_location: 0, },
///     A { format: F::Float32,   offset:  8, shader_location: 1, },
///     A { format: F::Uint16x4,  offset: 12, shader_location: 2, },
/// ]);
/// ```
///
/// See [`VertexBufferLayout`] for an example building on this one.
#[macro_export]
macro_rules! vertex_attr_array {
    ($($location:expr => $format:ident),* $(,)?) => {
        $crate::_vertex_attr_array_helper!([] ; 0; $($location => $format ,)*)
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! _vertex_attr_array_helper {
    ([$($t:expr,)*] ; $off:expr ;) => { [$($t,)*] };
    ([$($t:expr,)*] ; $off:expr ; $location:expr => $format:ident, $($ll:expr => $ii:ident ,)*) => {
        $crate::_vertex_attr_array_helper!(
            [$($t,)*
            $crate::VertexAttribute {
                format: $crate::VertexFormat :: $format,
                offset: $off,
                shader_location: $location,
            },];
            $off + $crate::VertexFormat :: $format.size();
            $($ll => $ii ,)*
        )
    };
}

#[test]
fn test_vertex_attr_array() {
    let attrs = vertex_attr_array![0 => Float32x2, 3 => Uint16x4];
    // VertexAttribute does not support PartialEq, so we cannot test directly
    assert_eq!(attrs.len(), 2);
    assert_eq!(attrs[0].offset, 0);
    assert_eq!(attrs[0].shader_location, 0);
    assert_eq!(attrs[1].offset, size_of::<(f32, f32)>() as u64);
    assert_eq!(attrs[1].shader_location, 3);
}

/// Macro to load a SPIR-V module statically.
///
/// It ensures the word alignment as well as the magic number.
///
/// Return type: [`crate::ShaderModuleDescriptor`]
#[macro_export]
#[cfg(feature = "spirv")]
macro_rules! include_spirv {
    ($($token:tt)*) => {
        {
            //log::info!("including '{}'", $($token)*);
            $crate::ShaderModuleDescriptor {
                label: Some($($token)*),
                source: $crate::util::make_spirv(include_bytes!($($token)*)),
            }
        }
    };
}

/// Macro to load raw SPIR-V data statically, for use with [`Features::SPIRV_SHADER_PASSTHROUGH`].
///
/// It ensures the word alignment as well as the magic number.
///
/// [`Features::SPIRV_SHADER_PASSTHROUGH`]: crate::Features::SPIRV_SHADER_PASSTHROUGH
#[macro_export]
macro_rules! include_spirv_raw {
    ($($token:tt)*) => {
        {
            //log::info!("including '{}'", $($token)*);
            $crate::ShaderModuleDescriptorSpirV {
                label: $crate::__macro_helpers::Some($($token)*),
                source: $crate::util::make_spirv_raw($crate::__macro_helpers::include_bytes!($($token)*)),
            }
        }
    };
}

/// Load WGSL source code from a file at compile time.
///
/// The loaded path is relative to the path of the file containing the macro call, in the same way
/// as [`include_str!`] operates.
///
/// ```ignore
/// fn main() {
///     let module: ShaderModuleDescriptor = include_wgsl!("shader.wgsl");
/// }
/// ```
#[macro_export]
macro_rules! include_wgsl {
    ($($token:tt)*) => {
        {
            //log::info!("including '{}'", $($token)*);
            $crate::ShaderModuleDescriptor {
                label: $crate::__macro_helpers::Some($($token)*),
                source: $crate::ShaderSource::Wgsl($crate::__macro_helpers::Cow::Borrowed($crate::__macro_helpers::include_str!($($token)*))),
            }
        }
    };
}

#[doc(hidden)]
pub mod helpers {
    pub use alloc::borrow::Cow;
    pub use core::{include_bytes, include_str};
    pub use Some;
}