1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
//! Defines traits and types for working with data adhering to GLSL's `std140`

//! layout specification.


mod dynamic_uniform;
mod primitives;
mod sizer;
mod writer;

use std::mem::size_of;

use bytemuck::{bytes_of, Pod, Zeroable};

pub use self::dynamic_uniform::*;
pub use self::primitives::*;
pub use self::sizer::*;
pub use self::writer::*;
pub use crevice_derive::AsStd140;

/// Trait implemented for all `std140` primitives. Generally should not be

/// implemented outside this crate.

pub unsafe trait Std140: Copy + Zeroable + Pod {
    /// The required alignment of the type. Must be a power of two.

    ///

    /// This is distinct from the value returned by `std::mem::align_of` because

    /// `AsStd140` structs do not use Rust's alignment. This enables them to

    /// control and zero their padding bytes, making converting them to and from

    /// slices safe.

    const ALIGNMENT: usize;

    /// Casts the type to a byte array. Implementors should not override this

    /// method.

    ///

    /// # Safety

    /// This is always safe due to the requirements of [`bytemuck::Pod`] being a

    /// prerequisite for this trait.

    fn as_bytes(&self) -> &[u8] {
        bytes_of(self)
    }
}

/**
Trait implemented for all types that can be turned into `std140` values.

This trait can often be `#[derive]`'d instead of manually implementing it. Any
struct which contains only fields that also implement `AsStd140` can derive
`AsStd140`.

Types from the mint crate implement `AsStd140`, making them convenient for use
in uniform types. Most Rust geometry crates, like cgmath, nalgebra, and
ultraviolet support mint.

## Example

```glsl
uniform CAMERA {
    mat4 view;
    mat4 projection;
} camera;
```

```
use cgmath::prelude::*;
use cgmath::{Matrix4, Deg, perspective};
use crevice::std140::{AsStd140, Std140};

#[derive(AsStd140)]
struct CameraUniform {
    view: mint::ColumnMatrix4<f32>,
    projection: mint::ColumnMatrix4<f32>,
}

let camera = CameraUniform {
    view: Matrix4::identity().into(),
    projection: perspective(Deg(60.0), 16.0/9.0, 0.01, 100.0).into(),
};

# fn write_to_gpu_buffer(bytes: &[u8]) {}
let camera_std140 = camera.as_std140();
write_to_gpu_buffer(camera_std140.as_bytes());
```
*/
pub trait AsStd140 {
    /// The `std140` version of this value.

    type Std140Type: Std140;

    /// Convert this value into the `std140` version of itself.

    fn as_std140(&self) -> Self::Std140Type;

    /// Returns the size of the `std140` version of this type. Useful for

    /// pre-sizing buffers.

    fn std140_size(&self) -> usize {
        size_of::<Self::Std140Type>()
    }
}

impl<T> AsStd140 for T
where
    T: Std140,
{
    type Std140Type = Self;

    fn as_std140(&self) -> Self {
        *self
    }
}