mew/
shaderstruct.rs

1#[allow(unused_imports)]
2use crate::shaderprimitive;
3
4/// Declare a shader struct (to use in a storage buffer).
5///
6/// ```rust
7/// shader_struct! { $NAME [
8///     0 $FIELD => $TYPE,
9///     1 $FIELD => $TYPE,
10///     2 $FIELD => $TYPE,
11///     ...
12/// ] }
13/// ```
14/// - `$NAME` is the name of your struct.  
15/// - `$FIELD` is the struct's public field name.  
16/// - `$TYPE` is the field's primitive type (see [`shaderprimitive`]).
17///
18/// Note that fields **must** be numbered correctly, starting from 0. This is
19/// because I don't know how to teach macros how to count.
20///
21/// Also, the fields are *not* rearranged to be optimized to their alignment
22/// rules, though they should be padded correctly.
23#[macro_export]
24macro_rules! shader_struct {
25    { $struct:ident [
26        $( $num:tt $field:ident => $ty:ident ),* $(,)?
27    ] } => {
28        #[derive(Clone, Debug)]
29        #[repr(C)]
30        pub struct $struct {
31            $( pub $field: $crate::shaderprimitive::$ty, )*
32            _padding: [u8; Self::PADDING],
33        }
34
35        impl $struct {
36            //pub const SUM_SIZE: usize = ::std::mem::size_of::<( $( $ty, )* )>();
37            pub const SUM_SIZE: usize = {
38                #[repr(C)]
39                struct SizeTest {
40                    $( $field: $crate::shaderprimitive::$ty, )*
41                }
42                ::std::mem::size_of::<SizeTest>()
43            };
44            pub const MAX_SIZE: usize = $crate::max_size! { $( $crate::shaderprimitive::$ty )* };
45            pub const NEXT_MULT: usize = Self::SUM_SIZE.next_multiple_of(Self::MAX_SIZE);
46            pub const PADDING: usize = Self::NEXT_MULT - Self::SUM_SIZE;
47        }
48
49        impl $crate::shaderstruct::MewShaderStruct for $struct {
50            type Bytes = [u8; Self::NEXT_MULT];
51            type Inners = ( $( <$crate::shaderprimitive::$ty as $crate::shaderprimitive::MewShaderPrimitive>::Inner , )* );
52
53            fn from_inners(inners: Self::Inners) -> Self {
54                #[allow(unused_imports)]
55                use $crate::shaderprimitive::MewShaderPrimitive;
56                Self {
57                    $( $field: $crate::shaderprimitive::$ty::from_inner(inners.$num), )*
58                    _padding: [0; Self::PADDING],
59                }
60            }
61
62            fn from_bytes(bytes: Self::Bytes) -> Self {
63                unsafe { ::std::mem::transmute(bytes) }
64            }
65
66            fn zeroed() -> Self {
67                unsafe {
68                    Self {
69                        //$( $field: [0; $crate::shader_struct! { @size $ty } ], )*
70                        $( $field: ::std::mem::zeroed(), )*
71                        _padding: [0; Self::PADDING],
72                    }
73                }
74            }
75        }
76
77
78        impl From<[u8; Self::NEXT_MULT]> for $struct {
79            fn from(bytes: [u8; Self::NEXT_MULT]) -> Self {
80                use $crate::shaderstruct::MewShaderStruct;
81                Self::from_bytes(bytes)
82            }
83        }
84        impl From<( $( <$crate::shaderprimitive::$ty as $crate::shaderprimitive::MewShaderPrimitive>::Inner , )* )> for $struct {
85            fn from(inners: ( $( <$crate::shaderprimitive::$ty as $crate::shaderprimitive::MewShaderPrimitive>::Inner , )* )) -> Self {
86                use $crate::shaderstruct::MewShaderStruct;
87                Self::from_inners(inners)
88            }
89        }
90
91        impl AsRef<[u8; Self::NEXT_MULT]> for $struct {
92            fn as_ref(&self) -> &[u8; Self::NEXT_MULT] {
93                unsafe { ::std::mem::transmute(self) }
94            }
95        }
96        impl AsMut<[u8; Self::NEXT_MULT]> for $struct {
97            fn as_mut(&mut self) -> &mut [u8; Self::NEXT_MULT] {
98                unsafe { ::std::mem::transmute(self) }
99            }
100        }
101
102        impl Default for $struct {
103            fn default() -> Self {
104                use $crate::shaderstruct::MewShaderStruct;
105                Self::zeroed()
106            }
107        }
108    }
109}
110pub use shader_struct;
111
112
113pub trait MewShaderStruct {
114    type Bytes;
115    type Inners;
116    fn from_inners(inners: Self::Inners) -> Self;
117    fn from_bytes(bytes: Self::Bytes) -> Self;
118    fn zeroed() -> Self;
119}