mew/
vertexstruct.rs

1/// Declare a vertex struct (to use in a vertex buffer).
2///
3/// ```rust
4/// vertex_struct! { $NAME $STEP [
5///     0 $FIELD => $TYPE,
6///     1 $FIELD => $TYPE,
7///     2 $FIELD => $TYPE,
8///     ...
9/// ] }
10/// ```
11/// - `$NAME` is the name of your struct.  
12/// - `$STEP` is either omitted or the word "step" followed by "Vertex" or
13///   "Instance" to set the `VertexBufferLayout` `step_mode` attribute.  
14/// - `$FIELD` is the struct's public field name.  
15/// - `$TYPE` is the field's `VertexFormat`.
16///
17/// Note that fields *must* be numbered correctly, starting from 0. This is
18/// because I don't know how to teach macros how to count.
19///
20/// Also, the fields are *not* rearranged to be optimized to their alignment
21/// rules, though they should be padded correctly.
22#[macro_export]
23macro_rules! vertex_struct {
24    { $struct:ident [
25        $( $num:tt $field:ident => $attr:ident ),* $(,)?
26    ] } => {
27        $crate::vertex_struct! { $struct step Vertex [
28            $( $num $field => $attr , )*
29        ] }
30    };
31    { $struct:ident step $step:ident [
32        $( $num:tt $field:ident => $attr:ident ),* $(,)?
33    ] } => {
34        #[derive(Debug)]
35        #[repr(C, packed(2))]
36        pub struct $struct {
37            $( pub $field: $crate::vertexformat::$attr, )*
38            _padding: [u8; Self::PADDING],
39        }
40
41        impl $struct {
42            //pub const SUM_SIZE: usize = ::std::mem::size_of::<( $( $attr, )* )>();
43            //pub const SUM_SIZE: usize = sum_size! { $( $attr )* };
44            pub const SUM_SIZE: usize = {
45                #[repr(C, packed(2))]
46                struct SizeTest {
47                    $( $field: $crate::vertexformat::$attr, )*
48                }
49                ::std::mem::size_of::<SizeTest>()
50            };
51            pub const BYTES: usize = Self::SUM_SIZE.next_multiple_of(4);
52            pub const PADDING: usize = Self::BYTES - Self::SUM_SIZE;
53        }
54
55        impl $crate::vertexstruct::MewVertexStruct for $struct {
56            type Bytes = [u8; Self::BYTES];
57            type Inners = ( $( <$crate::vertexformat::$attr as $crate::vertexformat::MewVertexFormat>::Inner , )* );
58            type InnerRefs<'i> = ( $( &'i <$crate::vertexformat::$attr as $crate::vertexformat::MewVertexFormat>::Inner , )* );
59            type InnerMuts<'i> = ( $( &'i mut <$crate::vertexformat::$attr as $crate::vertexformat::MewVertexFormat>::Inner , )* );
60
61            fn from_inners(inners: Self::Inners) -> Self {
62                #[allow(unused_imports)]
63                use $crate::vertexformat::MewVertexFormat;
64                Self {
65                    $( $field: $crate::vertexformat::$attr::from_inner(inners.$num), )*
66                    _padding: [0; Self::PADDING],
67                }
68            }
69
70            /*
71            fn from_bytes(bytes: Self::Bytes) -> Self {
72                //unsafe { ::std::mem::transmute(bytes) }
73                todo!()
74            }
75            */
76
77            fn zeroed() -> Self {
78                unsafe {
79                    Self {
80                        $( $field: ::std::mem::zeroed(), )*
81                        _padding: [0; Self::PADDING],
82                    }
83                }
84            }
85
86            fn get_refs(&self) -> Self::InnerRefs<'_> {
87                unsafe {
88                    ( $( &*&raw const self.$field, )* )
89                }
90            }
91
92            fn get_muts(&mut self) -> Self::InnerMuts<'_> {
93                unsafe {
94                    ( $( &mut *&raw mut self.$field, )* )
95                }
96            }
97
98            fn vertex_layout() -> $crate::wgpu::VertexBufferLayout<'static> {
99                static ATTRIBUTES: [$crate::wgpu::VertexAttribute; $crate::len! { $( $num )* }] = $crate::wgpu::vertex_attr_array![ $( $num => $attr , )* ];
100                $crate::wgpu::VertexBufferLayout {
101                    //array_stride: ::std::mem::size_of::<Self>() as u64,
102                    array_stride: Self::BYTES as u64,
103                    step_mode: $crate::wgpu::VertexStepMode::$step,
104                    attributes: &ATTRIBUTES,
105                }
106            }
107        }
108
109
110        /*
111        impl From<[u8; Self::BYTES]> for $struct {
112            fn from(bytes: [u8; Self::BYTES]) -> Self {
113                use $crate::vertexstruct::MewVertexStruct;
114                Self::from_bytes(bytes)
115            }
116        }
117        */
118        impl From<( $( <$crate::vertexformat::$attr as $crate::vertexformat::MewVertexFormat>::Inner , )* )> for $struct {
119            fn from(inners: ( $( <$crate::vertexformat::$attr as $crate::vertexformat::MewVertexFormat>::Inner , )* )) -> Self {
120                use $crate::vertexstruct::MewVertexStruct;
121                Self::from_inners(inners)
122            }
123        }
124
125        impl AsRef<[u8; Self::BYTES]> for $struct {
126            fn as_ref(&self) -> &[u8; Self::BYTES] {
127                unsafe { ::std::mem::transmute(self) }
128            }
129        }
130        impl AsMut<[u8; Self::BYTES]> for $struct {
131            fn as_mut(&mut self) -> &mut [u8; Self::BYTES] {
132                unsafe { ::std::mem::transmute(self) }
133            }
134        }
135
136        impl Clone for $struct {
137            fn clone(&self) -> Self {
138                unsafe {
139                    Self {
140                        $( $field: *&raw const self.$field, )*
141                        _padding: [0; Self::PADDING],
142                    }
143                }
144            }
145        }
146
147        impl Default for $struct {
148            fn default() -> Self {
149                use $crate::vertexstruct::MewVertexStruct;
150                Self::zeroed()
151            }
152        }
153    }
154}
155pub use vertex_struct;
156
157
158pub trait MewVertexStruct {
159    type Bytes;
160    type Inners;
161    type InnerRefs<'i> where Self: 'i;
162    type InnerMuts<'i> where Self: 'i;
163    fn from_inners(inners: Self::Inners) -> Self;
164    //fn from_bytes(bytes: Self::Bytes) -> Self;
165    fn zeroed() -> Self;
166    fn get_refs<'i>(&'i self) -> Self::InnerRefs<'i>;
167    fn get_muts<'i>(&'i mut self) -> Self::InnerMuts<'i>;
168    fn vertex_layout() -> wgpu::VertexBufferLayout<'static>;
169}