const_shader_layout/
compat.rs1use crate::ShaderLayout;
2
3pub trait ShaderLayoutCompat: ShaderLayout {
10 const ALIGN_CONSTRAINT: core::num::NonZero<u64> = Self::ALIGN;
13 const SIZE_CONSTRAINT: core::num::NonZero<u64> =
18 core::num::NonZero::new(size_of::<Self>() as u64).unwrap();
19}
20
21pub trait ShaderLayoutCompatArrayElement: crate::ShaderLayoutArrayElement {}
28
29#[macro_export]
31#[doc(hidden)]
32macro_rules! impl_shader_layout_compat {
33 ($($ty:ty),+$(,)?) => {
34 $(
35 $crate::impl_shader_layout!($ty);
36 impl $crate::ShaderLayoutCompat for $ty {}
37 )+
38 };
39 ($align:expr $(, $ty:ty)+$(,)?) => {
40 $(
41 $crate::impl_shader_layout!($align, $ty);
42 impl $crate::ShaderLayoutCompat for $ty {}
43 )+
44 };
45 ($align:expr, $align_constraint:expr $(, $ty:ty)+$(,)?) => {
46 $(
47 $crate::impl_shader_layout!($align, $ty);
48 impl $crate::ShaderLayoutCompat for $ty {
49 const ALIGN_CONSTRAINT: ::core::num::NonZero<u64> = ::core::num::NonZero::new($align_constraint).unwrap();
50 }
51 )+
52 };
53 ($align:expr, $align_constraint:expr, $size_constraint:expr $(, $ty:ty)+$(,)?) => {
54 const _: () ={
55 assert!((($size_constraint) as u64).is_multiple_of(16u64));
56 };
57 $(
58 $crate::impl_shader_layout!($align, $ty);
59 impl $crate::ShaderLayoutCompat for $ty {
60 const ALIGN_CONSTRAINT: ::core::num::NonZero<u64> = ::core::num::NonZero::new($align_constraint).unwrap();
61 const SIZE_CONSTRAINT: ::core::num::NonZero<u64> = ::core::num::NonZero::new($size_constraint).unwrap();
62 }
63 )+
64 };
65}
66
67#[macro_export]
68#[doc(hidden)]
69macro_rules! primitive_impl_shader_layout_compat_array_element {
70 ($($ty:ty),+$(,)?) => {
71 $(
72 $crate::impl_shader_layout_array_element!($ty);
73 $crate::impl_shader_layout_compat_array_element!($ty);
74 )+
75 };
76}
77
78#[macro_export]
87macro_rules! impl_shader_layout_compat_array_element {
88 ($($ty:ty),+$(,)?) => {
89 $(
90 impl $crate::ShaderLayoutCompatArrayElement for $ty {}
91
92 const _: () = {
94 const ELEMENT_ALIGN: u64 = <$ty as $crate::ShaderLayout>::ALIGN.get().next_multiple_of(16);
95 const N: usize = 1;
96 const ACTUAL_SIZE: u64 = size_of::<[$ty; N]>() as u64;
97 const SIZE: u64 = (size_of::<$ty>() as u64).next_multiple_of(ELEMENT_ALIGN) * N as u64;
98 if SIZE != ACTUAL_SIZE {
99 let mut msg = $crate::internal::MsgBuf::<256>::new();
100 msg.write_str("Failed to implement `ShaderLayoutCompatArrayElement`: `[")
101 .write_str(stringify!($ty))
102 .write_str("; N]` size (")
103 .write_usize(size_of::<[$ty; N]>())
104 .write_str(" * N) must be equal to its shader size (")
105 .write_u64(SIZE)
106 .write_str(" * N), i.e. the stride must be rounded up to `ALIGN` (")
107 .write_u64(ELEMENT_ALIGN)
108 .write_str(") and 16");
109 panic!("{}", msg.as_str());
110 }
111 };
112 )+
113 };
114}
115
116#[macro_export]
117macro_rules! impl_shader_layout_compat_struct {
118 (
119 $(#[$attr:meta])*
120 $vis:vis struct $struct_name:ident {
121 $(
122 $(#[$field_attr:meta])*
123 $field_vis:vis $field_name:ident : $field_ty:ty
124 ),* $(,)?
125 }
126 ) => {
127 $crate::impl_shader_layout_struct!(
128 $(#[$attr])*
129 $vis struct $struct_name {
130 $(
131 $(#[$field_attr])*
132 $field_vis $field_name: $field_ty
133 ),*
134 }
135 );
136
137 $(
138 const _: () = {
139 const MEMBER_ALIGN_CONSTRAINT: u64 = <$field_ty as $crate::ShaderLayoutCompat>::ALIGN_CONSTRAINT.get();
140 const MEMBER_SIZE_CONSTRAINT: u64 = <$field_ty as $crate::ShaderLayoutCompat>::SIZE_CONSTRAINT.get();
141 const MEMBER_SIZE: u64 = size_of::<$field_ty>() as u64;
142 const MEMBER_OFFSET: u64 = core::mem::offset_of!($struct_name, $field_name) as u64;
143
144 if MEMBER_SIZE != MEMBER_SIZE_CONSTRAINT {
145 let mut msg = $crate::internal::MsgBuf::<256>::new();
146 msg.write_str("Failed to impl `ShaderLayoutCompat`: field `")
147 .write_str(stringify!($struct_name))
148 .write_str("::")
149 .write_str(stringify!($field_name))
150 .write_str("` (`")
151 .write_str(stringify!($field_ty))
152 .write_str("`) size (")
153 .write_u64(MEMBER_SIZE)
154 .write_str(") must be `SIZE_CONSTRAINT` (")
155 .write_u64(MEMBER_SIZE_CONSTRAINT)
156 .write_str(") due to uniform layout constraints");
157 panic!("{}", msg.as_str());
158 }
159
160 if !MEMBER_OFFSET.is_multiple_of(MEMBER_ALIGN_CONSTRAINT) {
161 let mut msg = $crate::internal::MsgBuf::<256>::new();
162 msg.write_str("Failed to impl `ShaderLayoutCompat`: field `")
163 .write_str(stringify!($struct_name))
164 .write_str("::")
165 .write_str(stringify!($field_name))
166 .write_str("` (`")
167 .write_str(stringify!($field_ty))
168 .write_str("`) is not properly aligned. The offset is ")
169 .write_u64(MEMBER_OFFSET)
170 .write_str(" but required align is `ALIGN_CONSTRAINT` (")
171 .write_u64(MEMBER_ALIGN_CONSTRAINT)
172 .write_str(")");
173 panic!("{}", msg.as_str());
174 }
175 };
176 )*
177
178 impl $crate::ShaderLayoutCompat for $struct_name {
179 const ALIGN_CONSTRAINT: ::core::num::NonZero<u64> = {
180 const MEMBER_ALIGNS: &[u64] = &[$(
181 (<$field_ty as $crate::ShaderLayoutCompat>::ALIGN_CONSTRAINT.get())
182 ),*];
183
184 let mut max = MEMBER_ALIGNS[0];
185 let mut i = 1;
186 while i < MEMBER_ALIGNS.len() {
187 if MEMBER_ALIGNS[i] > max {
188 max = MEMBER_ALIGNS[i];
189 }
190 i += 1;
191 }
192 ::core::num::NonZero::new(max.next_multiple_of(16)).unwrap()
193 };
194 const SIZE_CONSTRAINT: ::core::num::NonZero<u64> = {
195 const MEMBER_SIZES: &[u64] = &[$(
196 (<$field_ty as $crate::ShaderLayoutCompat>::SIZE_CONSTRAINT.get())
197 ),*];
198
199 let mut sum = MEMBER_SIZES[0];
200 let mut i = 1;
201 while i < MEMBER_SIZES.len() {
202 sum += MEMBER_SIZES[i];
203 i += 1;
204 }
205 ::core::num::NonZero::new(sum.next_multiple_of(16)).unwrap()
206 };
207 }
208 };
209}
210
211#[macro_export]
221macro_rules! shader_layout_compat {
222 (
223 $(#[$attr:meta])*
224 $vis:vis struct $struct_name:ident {
225 $(
226 $(#[$field_attr:meta])*
227 $field_vis:vis $field_name:ident : $field_ty:ty
228 ),* $(,)?
229 }
230 ) => {
231 #[derive(Copy, Clone)]
232 #[repr(C)]
233 $(#[$attr])*
234 $vis struct $struct_name {
235 $(
236 $(#[$field_attr])*
237 $field_vis $field_name: $field_ty
238 ),*
239 }
240
241 $crate::impl_shader_layout_compat_struct!{
242 $(#[$attr])*
243 $vis struct $struct_name {
244 $(
245 $(#[$field_attr])*
246 $field_vis $field_name: $field_ty
247 ),*
248 }
249 }
250 };
251}