crevice_notan/std140/
dynamic_uniform.rs

1use bytemuck::{Pod, Zeroable};
2
3use crate::internal::max;
4use crate::std140::{AsStd140, Std140};
5
6/// Wrapper type that aligns the inner type to at least 256 bytes.
7///
8/// This type is useful for ensuring correct alignment when creating dynamic
9/// uniform buffers in APIs like WebGPU.
10pub struct DynamicUniform<T>(pub T);
11
12impl<T: AsStd140> AsStd140 for DynamicUniform<T> {
13    type Output = DynamicUniformStd140<<T as AsStd140>::Output>;
14
15    fn as_std140(&self) -> Self::Output {
16        DynamicUniformStd140(self.0.as_std140())
17    }
18
19    fn from_std140(value: Self::Output) -> Self {
20        DynamicUniform(<T as AsStd140>::from_std140(value.0))
21    }
22}
23
24/// std140 variant of [`DynamicUniform`].
25#[derive(Clone, Copy)]
26#[repr(transparent)]
27pub struct DynamicUniformStd140<T>(T);
28
29unsafe impl<T: Std140> Std140 for DynamicUniformStd140<T> {
30    const ALIGNMENT: usize = max(256, T::ALIGNMENT);
31}
32
33unsafe impl<T: Zeroable> Zeroable for DynamicUniformStd140<T> {}
34unsafe impl<T: Pod> Pod for DynamicUniformStd140<T> {}
35
36#[cfg(test)]
37mod test {
38    use super::*;
39
40    use crate::std140::AsStd140;
41
42    #[test]
43    fn size_is_unchanged() {
44        assert_eq!(
45            DynamicUniform::<f32>::std140_size_static(),
46            f32::std140_size_static()
47        );
48    }
49
50    #[test]
51    #[cfg(feature = "std")]
52    fn alignment_applies() {
53        use crate::std140;
54
55        let mut output = Vec::new();
56        let mut writer = std140::Writer::new(&mut output);
57
58        writer.write(&DynamicUniform(0.0f32)).unwrap();
59        assert_eq!(writer.len(), 4);
60
61        writer.write(&DynamicUniform(1.0f32)).unwrap();
62        assert_eq!(writer.len(), 260);
63    }
64}