glsl_layout/
array.rs

1use crate::align::Align16;
2use crate::uniform::{Std140, Uniform};
3use std::{
4    marker::PhantomData,
5    slice::{Iter as SliceIter, IterMut as SliceIterMut},
6};
7
8pub(crate) trait MapArray<A, F> {
9    fn map_array(values: A, f: F) -> Self;
10}
11
12/// Aligning wrapper.
13/// Elements for array are aligned to 16 bytes (size of vec4) at least.
14#[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)]
15#[repr(C, align(16))]
16pub struct Element<T: Uniform>(pub T, pub T::Align);
17
18impl<T> From<T> for Element<T>
19where
20    T: Uniform,
21{
22    fn from(values: T) -> Self {
23        Element(values, Default::default())
24    }
25}
26
27impl<T> AsRef<T> for Element<T>
28where
29    T: Uniform,
30{
31    fn as_ref(&self) -> &T {
32        &self.0
33    }
34}
35
36impl<T> AsMut<T> for Element<T>
37where
38    T: Uniform,
39{
40    fn as_mut(&mut self) -> &mut T {
41        &mut self.0
42    }
43}
44
45/// Array of `Element`s.
46/// This type implements useful traits for converting from unwrapped types.
47#[derive(Clone, Copy, Debug, Default, PartialOrd, PartialEq, Ord, Eq, Hash)]
48#[repr(C, align(16))]
49pub struct Array<T, A>(pub A, pub PhantomData<fn(T)>);
50
51impl<T, A> Array<T, A> {
52    pub fn new(array: A) -> Self {
53        Array(array, PhantomData)
54    }
55}
56
57impl<T, A> AsRef<A> for Array<T, A> {
58    fn as_ref(&self) -> &A {
59        &self.0
60    }
61}
62
63impl<T, A> AsMut<A> for Array<T, A> {
64    fn as_mut(&mut self) -> &mut A {
65        &mut self.0
66    }
67}
68
69impl<T, A> Array<T, A>
70where
71    T: Uniform,
72    A: AsMut<[Element<T>]> + AsRef<[Element<T>]>,
73{
74    pub fn iter(&self) -> ArrayIter<SliceIter<Element<T>>> {
75        ArrayIter(self.0.as_ref().iter())
76    }
77
78    pub fn iter_mut(&mut self) -> ArrayIter<SliceIterMut<Element<T>>> {
79        ArrayIter(self.0.as_mut().iter_mut())
80    }
81}
82
83impl<'a, T, A> IntoIterator for &'a Array<T, A>
84where
85    T: Uniform,
86    A: AsMut<[Element<T>]> + AsRef<[Element<T>]>,
87{
88    type Item = &'a T;
89    type IntoIter = ArrayIter<SliceIter<'a, Element<T>>>;
90
91    fn into_iter(self) -> ArrayIter<SliceIter<'a, Element<T>>> {
92        self.iter()
93    }
94}
95
96impl<'a, T, A> IntoIterator for &'a mut Array<T, A>
97where
98    T: Uniform,
99    A: AsMut<[Element<T>]> + AsRef<[Element<T>]>,
100{
101    type Item = &'a mut T;
102    type IntoIter = ArrayIter<SliceIterMut<'a, Element<T>>>;
103
104    fn into_iter(self) -> ArrayIter<SliceIterMut<'a, Element<T>>> {
105        self.iter_mut()
106    }
107}
108
109/// Array ref iterator
110/// Iterate over references to inner values.
111pub struct ArrayIter<I>(I);
112
113impl<'a, T> Iterator for ArrayIter<SliceIter<'a, Element<T>>>
114where
115    T: Uniform,
116{
117    type Item = &'a T;
118
119    fn next(&mut self) -> Option<&'a T> {
120        self.0.next().map(|elem| &elem.0)
121    }
122}
123
124impl<'a, T> ExactSizeIterator for ArrayIter<SliceIter<'a, Element<T>>>
125where
126    T: Uniform,
127{
128    fn len(&self) -> usize {
129        self.0.len()
130    }
131}
132
133impl<'a, T> DoubleEndedIterator for ArrayIter<SliceIter<'a, Element<T>>>
134where
135    T: Uniform,
136{
137    fn next_back(&mut self) -> Option<&'a T> {
138        self.0.next_back().map(|elem| &elem.0)
139    }
140}
141
142impl<'a, T> Iterator for ArrayIter<SliceIterMut<'a, Element<T>>>
143where
144    T: Uniform,
145{
146    type Item = &'a mut T;
147
148    fn next(&mut self) -> Option<&'a mut T> {
149        self.0.next().map(|elem| &mut elem.0)
150    }
151}
152
153impl<'a, T> ExactSizeIterator for ArrayIter<SliceIterMut<'a, Element<T>>>
154where
155    T: Uniform,
156{
157    fn len(&self) -> usize {
158        self.0.len()
159    }
160}
161
162impl<'a, T> DoubleEndedIterator for ArrayIter<SliceIterMut<'a, Element<T>>>
163where
164    T: Uniform,
165{
166    fn next_back(&mut self) -> Option<&'a mut T> {
167        self.0.next_back().map(|elem| &mut elem.0)
168    }
169}
170
171impl<T, U, F, const N: usize> MapArray<[T; N], F> for [U; N]
172where
173    F: FnMut(T) -> U,
174{
175    fn map_array(values: [T; N], mut f: F) -> Self {
176        use std::{
177            mem::{ManuallyDrop, MaybeUninit},
178            ptr::{read, write},
179        };
180
181        // Use `ManuallyDrop<_>` to guard against panic safety issue.
182        // Upon panic in `f`, `values` isn't dropped
183        // and thus item copied by `read()` is dropped only once.
184        let values = ManuallyDrop::new(values);
185        unsafe {
186            let mut result: MaybeUninit<[U; N]> = MaybeUninit::zeroed();
187            for i in 0..N {
188                write(result.as_mut_ptr().cast::<U>().add(i), f(read(&values[i])));
189            }
190            result.assume_init()
191        }
192    }
193}
194
195impl<T, U, const N: usize> From<[T; N]> for Array<U, [U; N]>
196where
197    T: Into<U>,
198{
199    fn from(values: [T; N]) -> Self {
200        Array(MapArray::map_array(values, T::into), PhantomData)
201    }
202}
203
204impl<T, U, const N: usize> From<[T; N]> for Array<U, [Element<U>; N]>
205where
206    T: Into<U>,
207    U: Uniform,
208{
209    fn from(values: [T; N]) -> Self {
210        let values: [U; N] = MapArray::map_array(values, T::into);
211        Array(MapArray::map_array(values, U::into), PhantomData)
212    }
213}
214
215impl<T, const N: usize> Uniform for [T; N]
216where
217    T: Uniform,
218{
219    type Align = Align16;
220    type Std140 = Array<T::Std140, [Element<T::Std140>; N]>;
221
222    fn std140(&self) -> Array<T::Std140, [Element<T::Std140>; N]> {
223        use std::ptr::write;
224        unsafe {
225            // All elements of `result` is written.
226            let mut result: ::std::mem::MaybeUninit<[Element<T::Std140>; N]> =
227                ::std::mem::MaybeUninit::zeroed();
228            for (i, item) in self.iter().enumerate().take(N) {
229                write(
230                    result.as_mut_ptr().cast::<Element<T::Std140>>().add(i),
231                    item.std140().into(),
232                );
233            }
234            Array(result.assume_init(), PhantomData)
235        }
236    }
237}
238
239impl<T, const N: usize> Uniform for Array<T, [Element<T>; N]>
240where
241    T: Uniform,
242{
243    type Align = Align16;
244    type Std140 = Array<T::Std140, [Element<T::Std140>; N]>;
245
246    fn std140(&self) -> Array<T::Std140, [Element<T::Std140>; N]> {
247        use std::ptr::write;
248        unsafe {
249            // All elements of `result` is written.
250            let mut result: ::std::mem::MaybeUninit<[Element<T::Std140>; N]> =
251                ::std::mem::MaybeUninit::zeroed();
252            for i in 0..N {
253                write(
254                    result.as_mut_ptr().cast::<Element<T::Std140>>().add(i),
255                    self.0[i].0.std140().into(),
256                );
257            }
258            Array(result.assume_init(), PhantomData)
259        }
260    }
261}
262
263unsafe impl<T, const N: usize> Std140 for Array<T, [Element<T>; N]> where T: Std140 {}
264
265#[test]
266fn test_array() {
267    use crate::{mat4, vec2, vec3};
268
269    let _ = [vec2::default(), vec2::default()].std140();
270    let _ = [
271        vec3::default(),
272        vec3::default(),
273        vec3::default(),
274        vec3::default(),
275        vec3::default(),
276        vec3::default(),
277        vec3::default(),
278        vec3::default(),
279        vec3::default(),
280        vec3::default(),
281        vec3::default(),
282        vec3::default(),
283        vec3::default(),
284        vec3::default(),
285        vec3::default(),
286        vec3::default(),
287        vec3::default(),
288        vec3::default(),
289    ]
290    .std140();
291
292    let _ = [
293        mat4::default(),
294        mat4::default(),
295        mat4::default(),
296        mat4::default(),
297        mat4::default(),
298        mat4::default(),
299        mat4::default(),
300        mat4::default(),
301        mat4::default(),
302        mat4::default(),
303        mat4::default(),
304        mat4::default(),
305        mat4::default(),
306        mat4::default(),
307        mat4::default(),
308        mat4::default(),
309        mat4::default(),
310        mat4::default(),
311    ]
312    .std140();
313}