1use luminance::shader::types::{Mat22, Mat33, Mat44, Vec2, Vec3, Vec4};
6
7pub trait Std140: Copy {
12 type Encoded: Copy;
13
14 fn std140_encode(self) -> Self::Encoded;
16
17 fn std140_decode(encoded: Self::Encoded) -> Self;
19}
20
21#[repr(C, align(4))]
25#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
26pub struct Aligned4<T>(pub T);
27
28#[repr(C, align(8))]
32#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
33pub struct Aligned8<T>(pub T);
34
35#[repr(C, align(16))]
39#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
40pub struct Aligned16<T>(pub T);
41
42#[repr(C, align(32))]
46#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
47pub struct Aligned32<T>(pub T);
48
49macro_rules! impl_Std140_id {
51 ($t:ty) => {
52 impl Std140 for $t {
53 type Encoded = $t;
54
55 fn std140_encode(self) -> Self::Encoded {
56 self
57 }
58
59 fn std140_decode(encoded: Self::Encoded) -> Self {
60 encoded
61 }
62 }
63 };
64}
65
66macro_rules! impl_Std140_Aligned4 {
68 ($t:ty) => {
69 impl Std140 for $t {
70 type Encoded = Aligned4<$t>;
71
72 fn std140_encode(self) -> Self::Encoded {
73 Aligned4(self)
74 }
75
76 fn std140_decode(encoded: Self::Encoded) -> Self {
77 encoded.0
78 }
79 }
80 };
81}
82
83macro_rules! impl_Std140_Aligned8 {
85 ($t:ty) => {
86 impl Std140 for $t {
87 type Encoded = Aligned8<$t>;
88
89 fn std140_encode(self) -> Self::Encoded {
90 Aligned8(self)
91 }
92
93 fn std140_decode(encoded: Self::Encoded) -> Self {
94 encoded.0
95 }
96 }
97 };
98}
99
100macro_rules! impl_Std140_Aligned16 {
102 ($t:ty) => {
103 impl Std140 for $t {
104 type Encoded = Aligned16<$t>;
105
106 fn std140_encode(self) -> Self::Encoded {
107 Aligned16(self)
108 }
109
110 fn std140_decode(encoded: Self::Encoded) -> Self {
111 encoded.0
112 }
113 }
114 };
115}
116
117macro_rules! impl_Std140_Aligned32 {
119 ($t:ty) => {
120 impl Std140 for $t {
121 type Encoded = Aligned32<$t>;
122
123 fn std140_encode(self) -> Self::Encoded {
124 Aligned32(self)
125 }
126
127 fn std140_decode(encoded: Self::Encoded) -> Self {
128 encoded.0
129 }
130 }
131 };
132}
133
134impl_Std140_id!(f32);
135impl_Std140_Aligned8!(Vec2<f32>);
136impl_Std140_Aligned16!(Vec3<f32>);
137impl_Std140_Aligned16!(Vec4<f32>);
138
139impl_Std140_id!(f64);
140impl_Std140_Aligned16!(Vec2<f64>);
141impl_Std140_Aligned32!(Vec3<f64>);
142impl_Std140_Aligned32!(Vec4<f64>);
143
144impl_Std140_id!(i32);
145impl_Std140_Aligned8!(Vec2<i32>);
146impl_Std140_Aligned16!(Vec3<i32>);
147impl_Std140_Aligned16!(Vec4<i32>);
148
149impl_Std140_id!(u32);
150impl_Std140_Aligned8!(Vec2<u32>);
151impl_Std140_Aligned16!(Vec3<u32>);
152impl_Std140_Aligned16!(Vec4<u32>);
153
154impl_Std140_Aligned4!(bool);
155
156impl Std140 for Vec2<bool> {
157 type Encoded = Aligned8<Vec2<Aligned4<bool>>>;
158
159 fn std140_encode(self) -> Self::Encoded {
160 let Vec2([x, y]) = self;
161 Aligned8(Vec2::new(Aligned4(x), Aligned4(y)))
162 }
163
164 fn std140_decode(encoded: Self::Encoded) -> Self {
165 let Aligned8(Vec2([Aligned4(x), Aligned4(y)])) = encoded;
166 Vec2::new(x, y)
167 }
168}
169
170impl_Std140_Aligned16!(Vec3<bool>);
171impl_Std140_Aligned16!(Vec4<bool>);
172
173impl Std140 for Mat22<f32> {
174 type Encoded = Aligned16<[Aligned16<[f32; 2]>; 2]>;
175
176 fn std140_encode(self) -> Self::Encoded {
177 let [a, b]: [[f32; 2]; 2] = self.into();
178 Aligned16([Aligned16(a), Aligned16(b)])
179 }
180
181 fn std140_decode(encoded: Self::Encoded) -> Self {
182 let Aligned16([Aligned16(a), Aligned16(b)]) = encoded;
183 [a, b].into()
184 }
185}
186
187impl Std140 for Mat22<f64> {
188 type Encoded = Aligned32<[Aligned32<[f64; 2]>; 2]>;
189
190 fn std140_encode(self) -> Self::Encoded {
191 let [a, b]: [[f64; 2]; 2] = self.into();
192 Aligned32([Aligned32(a), Aligned32(b)])
193 }
194
195 fn std140_decode(encoded: Self::Encoded) -> Self {
196 let Aligned32([Aligned32(a), Aligned32(b)]) = encoded;
197 [a, b].into()
198 }
199}
200
201impl Std140 for Mat33<f32> {
202 type Encoded = Aligned16<[Aligned16<[f32; 3]>; 3]>;
203
204 fn std140_encode(self) -> Self::Encoded {
205 let [a, b, c]: [[f32; 3]; 3] = self.into();
206 Aligned16([Aligned16(a), Aligned16(b), Aligned16(c)])
207 }
208
209 fn std140_decode(encoded: Self::Encoded) -> Self {
210 let Aligned16([Aligned16(a), Aligned16(b), Aligned16(c)]) = encoded;
211 [a, b, c].into()
212 }
213}
214
215impl Std140 for Mat33<f64> {
216 type Encoded = Aligned32<[Aligned32<[f64; 3]>; 3]>;
217
218 fn std140_encode(self) -> Self::Encoded {
219 let [a, b, c]: [[f64; 3]; 3] = self.into();
220 Aligned32([Aligned32(a), Aligned32(b), Aligned32(c)])
221 }
222
223 fn std140_decode(encoded: Self::Encoded) -> Self {
224 let Aligned32([Aligned32(a), Aligned32(b), Aligned32(c)]) = encoded;
225 [a, b, c].into()
226 }
227}
228
229impl Std140 for Mat44<f32> {
230 type Encoded = Aligned16<[Aligned16<[f32; 4]>; 4]>;
231
232 fn std140_encode(self) -> Self::Encoded {
233 let [a, b, c, d]: [[f32; 4]; 4] = self.into();
234 Aligned16([Aligned16(a), Aligned16(b), Aligned16(c), Aligned16(d)])
235 }
236
237 fn std140_decode(encoded: Self::Encoded) -> Self {
238 let Aligned16([Aligned16(a), Aligned16(b), Aligned16(c), Aligned16(d)]) = encoded;
239 [a, b, c, d].into()
240 }
241}
242
243impl Std140 for Mat44<f64> {
244 type Encoded = Aligned32<[Aligned32<[f64; 4]>; 4]>;
245
246 fn std140_encode(self) -> Self::Encoded {
247 let [a, b, c, d]: [[f64; 4]; 4] = self.into();
248 Aligned32([Aligned32(a), Aligned32(b), Aligned32(c), Aligned32(d)])
249 }
250
251 fn std140_decode(encoded: Self::Encoded) -> Self {
252 let Aligned32([Aligned32(a), Aligned32(b), Aligned32(c), Aligned32(d)]) = encoded;
253 [a, b, c, d].into()
254 }
255}
256
257#[repr(transparent)]
259#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
260pub struct ArrElem<T>(pub T);
261
262impl<T> Std140 for ArrElem<T>
263where
264 T: Std140,
265{
266 type Encoded = Aligned16<<T as Std140>::Encoded>;
267
268 fn std140_encode(self) -> Self::Encoded {
269 Aligned16(self.0.std140_encode())
270 }
271
272 fn std140_decode(encoded: Self::Encoded) -> Self {
273 ArrElem(<T as Std140>::std140_decode(encoded.0))
274 }
275}
276
277#[cfg(test)]
278mod tests {
279 use super::*;
280 use luminance::shader::types::{Vec3, Vec4};
281 use std::mem;
282
283 fn assert_size_align<T>(size: usize, align: usize)
284 where
285 T: Std140,
286 {
287 assert_eq!(mem::size_of::<<T as Std140>::Encoded>(), size);
288 assert_eq!(mem::align_of::<<T as Std140>::Encoded>(), align);
289 }
290
291 #[test]
292 fn f32() {
293 assert_size_align::<f32>(4, 4);
294 }
295
296 #[test]
297 fn aligned16() {
298 assert_eq!(std::mem::size_of::<Aligned16<f32>>(), 16);
299 assert_eq!(std::mem::size_of::<Aligned16<Aligned16<f32>>>(), 16);
300 }
301
302 #[test]
303 fn vec2() {
304 assert_size_align::<Vec2<f32>>(8, 8);
305 assert_size_align::<Vec2<f64>>(16, 16);
306 }
307
308 #[test]
309 fn vec3() {
310 assert_size_align::<Vec3<f32>>(16, 16);
311 assert_size_align::<Vec3<f64>>(32, 32);
312 }
313
314 #[test]
315 fn vec4() {
316 assert_size_align::<Vec4<f32>>(16, 16);
317 assert_size_align::<Vec4<f64>>(32, 32);
318 }
319
320 #[test]
321 fn i32() {
322 assert_size_align::<i32>(4, 4);
323 }
324
325 #[test]
326 fn ivec2() {
327 assert_size_align::<Vec2<i32>>(8, 8);
328 }
329
330 #[test]
331 fn ivec3() {
332 assert_size_align::<Vec3<i32>>(16, 16);
333 }
334
335 #[test]
336 fn ivec4() {
337 assert_size_align::<Vec4<i32>>(16, 16);
338 }
339
340 #[test]
341 fn u32() {
342 assert_size_align::<u32>(4, 4);
343 }
344
345 #[test]
346 fn uvec2() {
347 assert_size_align::<Vec2<u32>>(8, 8);
348 }
349
350 #[test]
351 fn uvec3() {
352 assert_size_align::<Vec3<i32>>(16, 16);
353 }
354
355 #[test]
356 fn uvec4() {
357 assert_size_align::<Vec4<i32>>(16, 16);
358 }
359
360 #[test]
361 fn bool() {
362 assert_size_align::<bool>(4, 4);
363 }
364
365 #[test]
366 fn bvec2() {
367 assert_size_align::<Vec2<bool>>(8, 8);
368 }
369
370 #[test]
371 fn bvec3() {
372 assert_size_align::<Vec3<bool>>(16, 16);
373 }
374
375 #[test]
376 fn bvec4() {
377 assert_size_align::<Vec4<bool>>(16, 16);
378 }
379
380 #[test]
381 fn mat22() {
382 assert_size_align::<Mat22<f32>>(32, 16);
383 }
384
385 #[test]
386 fn mat33() {
387 assert_size_align::<Mat33<f32>>(48, 16);
388 }
389
390 #[test]
391 fn mat44() {
392 assert_size_align::<Mat44<f32>>(64, 16);
393 }
394
395 #[test]
396 fn vec2_arrayed() {
397 assert_size_align::<ArrElem<Vec2<f32>>>(16, 16);
398 assert_size_align::<ArrElem<Vec2<f64>>>(16, 16);
399 }
400
401 #[test]
402 fn vec3_array() {
403 assert_size_align::<ArrElem<Vec3<f32>>>(16, 16);
404 assert_size_align::<ArrElem<Vec3<f64>>>(32, 32);
405 }
406
407 #[test]
408 fn vec4_array() {
409 assert_size_align::<ArrElem<Vec4<f32>>>(16, 16);
410 assert_size_align::<ArrElem<Vec4<f64>>>(32, 32);
411 }
412
413 #[test]
414 fn mat22_array() {
415 assert_size_align::<ArrElem<Mat22<f32>>>(32, 16);
416 assert_size_align::<ArrElem<Mat22<f64>>>(64, 32);
417 }
418
419 #[test]
420 fn mat33_array() {
421 assert_size_align::<ArrElem<Mat33<f32>>>(48, 16);
422 assert_size_align::<ArrElem<Mat33<f64>>>(96, 32);
423 }
424
425 #[test]
426 fn mat44_array() {
427 assert_size_align::<ArrElem<Mat44<f32>>>(64, 16);
428 assert_size_align::<ArrElem<Mat44<f64>>>(128, 32);
429 }
430}