#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg))]
pub type Int = i32;
pub type Uint = u32;
pub type Float = f32;
pub type Double = f64;
#[repr(transparent)]
#[derive(Debug, Copy, Clone, Default, PartialEq, PartialOrd)]
pub struct Bool(u32);
impl Bool {
pub fn new(value: bool) -> Self {
Self(value as u32)
}
}
impl From<Bool> for bool {
fn from(other: Bool) -> Self {
other.0 != 0
}
}
impl From<bool> for Bool {
fn from(other: bool) -> Self {
Self(other as u32)
}
}
#[cfg(feature = "bytemuck")]
unsafe impl bytemuck::Zeroable for Bool {}
#[cfg(feature = "bytemuck")]
unsafe impl bytemuck::Pod for Bool {}
macro_rules! define_vectors {
( $(( $name:ident, $mint_name:ident, $prim:ident * $count:literal, align: $align:literal, size: $size:literal ),)* ) => {
$(
define_vectors!(@impl
$name,
mint::$mint_name<$prim>,
$prim,
$count,
$align,
concat!(
"Vector of ", stringify!($count), " `", stringify!($prim), "` values. ",
"Has size ", stringify!($size), " and alignment ", stringify!($align), "."
),
concat!(
"Construct a `", stringify!($name), "` from any type which is convertable into a ",
"`mint::", stringify!($mint_name), "<", stringify!($prim), ">`."
)
);
)*
};
(@impl $name:ident, $mint_type:ty, $ty:ty, $count:literal, $align:literal, $doc:expr, $mint_doc:expr) => {
#[doc = $doc]
#[repr(C, align($align))]
#[derive(Debug, Copy, Clone, Default, PartialEq, PartialOrd)]
pub struct $name {
pub inner: [$ty; $count],
}
#[cfg(feature = "bytemuck")]
unsafe impl bytemuck::Zeroable for $name {}
#[cfg(feature = "bytemuck")]
unsafe impl bytemuck::Pod for $name {}
impl $name {
#[inline(always)]
pub fn new(inner: [$ty; $count]) -> Self {
Self {
inner,
}
}
#[cfg(feature = "mint")]
#[cfg_attr(docsrs, doc(cfg(feature = "mint")))]
#[doc = $mint_doc]
#[inline(always)]
pub fn from_mint<T: Into<$mint_type>>(value: T) -> Self {
Self::from(value.into())
}
}
#[cfg(feature = "mint")]
impl From<$mint_type> for $name {
#[inline(always)]
fn from(other: $mint_type) -> Self {
let inner: [$ty; $count] = other.into();
Self { inner }
}
}
impl From<[$ty; $count]> for $name {
#[inline(always)]
fn from(inner: [$ty; $count]) -> Self {
Self {
inner,
}
}
}
#[cfg(feature = "mint")]
impl From<$name> for $mint_type {
#[inline(always)]
fn from(other: $name) -> Self {
other.inner.into()
}
}
impl From<$name> for [$ty; $count] {
#[inline(always)]
fn from(other: $name) -> Self {
other.inner
}
}
};
}
define_vectors! {
(Vec2, Vector2, f32 * 2, align: 8, size: 8),
(Vec3, Vector3, f32 * 3, align: 16, size: 12),
(Vec4, Vector4, f32 * 4, align: 16, size: 16),
(DVec2, Vector2, f64 * 2, align: 16, size: 16),
(DVec3, Vector3, f64 * 3, align: 32, size: 24),
(DVec4, Vector4, f64 * 4, align: 32, size: 32),
(UVec2, Vector2, u32 * 2, align: 8, size: 8),
(UVec3, Vector3, u32 * 3, align: 16, size: 12),
(UVec4, Vector4, u32 * 4, align: 16, size: 16),
(IVec2, Vector2, i32 * 2, align: 8, size: 8),
(IVec3, Vector3, i32 * 3, align: 16, size: 12),
(IVec4, Vector4, i32 * 4, align: 16, size: 16),
(BVec2, Vector2, Bool * 2, align: 8, size: 8),
(BVec3, Vector3, Bool * 3, align: 16, size: 12),
(BVec4, Vector4, Bool * 4, align: 16, size: 16),
}
macro_rules! define_matrices {
( $(( $name:ident, $mint_name:ident, $prim_ty:ty, $row_ty:ty, $rows:literal * $cols:literal, align: $align:literal, size: $size:literal, pad: $pad:literal, [$($idx:literal),*] ),)* ) => {
$(
define_matrices!(@impl
$name,
mint::$mint_name<$prim_ty>,
$align,
$prim_ty,
$row_ty,
$rows,
$cols,
$pad,
[$( $idx ),*],
concat!(
"Matrix of `", stringify!($prim_ty), "` values with ", stringify!($rows), " rows and ", stringify!($cols), " columns. ",
"Has size ", stringify!($size), " and alignment ", stringify!($align), "."
),
concat!(
"Construct a `", stringify!($name), "` from any type which is convertable into a ",
"`mint::", stringify!($mint_name), "<", stringify!($prim_ty), ">`."
)
);
)*
};
(@impl $name:ident, $mint_type:ty, $align:literal, $inner_ty:ty, $ty:ty, $count_x:literal, $count_y:literal, $padding:literal, [$( $idx:literal ),*], $doc:expr, $mint_doc:expr) => {
#[doc = $doc]
#[repr(C, align($align))]
#[derive(Debug, Copy, Clone, Default, PartialEq, PartialOrd)]
pub struct $name {
pub inner: [$ty; $count_y],
_padding: [u8; $padding],
}
#[cfg(feature = "bytemuck")]
unsafe impl bytemuck::Zeroable for $name {}
#[cfg(feature = "bytemuck")]
unsafe impl bytemuck::Pod for $name {}
impl $name {
#[inline(always)]
pub fn new(inner: [$ty; $count_y]) -> Self {
Self { inner, _padding: [0; $padding] }
}
#[cfg(feature = "mint")]
#[cfg_attr(docsrs, doc(cfg(feature = "mint")))]
#[doc = $mint_doc]
#[inline(always)]
pub fn from_mint<T: Into<$mint_type>>(value: T) -> Self {
Self::from(value.into())
}
}
#[cfg(feature = "mint")]
impl From<$mint_type> for $name {
#[inline(always)]
fn from(other: $mint_type) -> Self {
let as_arr: [$inner_ty; $count_x * $count_y] = other.into();
as_arr.into()
}
}
impl From<[$ty; $count_y]> for $name {
#[inline(always)]
fn from(inner: [$ty; $count_y]) -> Self {
Self { inner, _padding: [0; $padding] }
}
}
impl From<[$inner_ty; $count_x * $count_y]> for $name {
#[inline(always)]
fn from(inner: [$inner_ty; $count_x * $count_y]) -> Self {
let d2: [[$inner_ty; $count_x]; $count_y] = unsafe { core::mem::transmute(inner) };
Self {
inner: [$(<$ty>::from(d2[$idx])),*],
_padding: [0; $padding],
}
}
}
impl From<[[$inner_ty; $count_x]; $count_y]> for $name {
#[inline(always)]
fn from(inner: [[$inner_ty; $count_x]; $count_y]) -> Self {
Self {
inner: [$(<$ty>::from(inner[$idx])),*],
_padding: [0; $padding],
}
}
}
#[cfg(feature = "mint")]
impl From<$name> for $mint_type {
#[inline(always)]
fn from(other: $name) -> Self {
let as_arr = <[[$inner_ty; $count_x]; $count_y]>::from(other);
as_arr.into()
}
}
impl From<$name> for [$ty; $count_y] {
#[inline(always)]
fn from(other: $name) -> Self {
other.inner
}
}
impl From<$name> for [$inner_ty; $count_x * $count_y] {
#[inline(always)]
fn from(other: $name) -> Self {
let d2: [[$inner_ty; $count_x]; $count_y] = [$(<[$inner_ty; $count_x]>::from(other.inner[$idx])),*];
unsafe { core::mem::transmute(d2) }
}
}
impl From<$name> for [[$inner_ty; $count_x]; $count_y] {
#[inline(always)]
fn from(other: $name) -> Self {
[$(<[$inner_ty; $count_x]>::from(other.inner[$idx])),*]
}
}
};
}
define_matrices! {
(Mat2x2, ColumnMatrix2, f32, Vec2, 2 * 2, align: 8, size: 16, pad: 0, [0, 1]),
(Mat2x3, ColumnMatrix2x3, f32, Vec2, 2 * 3, align: 8, size: 32, pad: 8, [0, 1, 2]),
(Mat2x4, ColumnMatrix2x4, f32, Vec2, 2 * 4, align: 8, size: 32, pad: 0, [0, 1, 2, 3]),
(Mat3x2, ColumnMatrix3x2, f32, Vec3, 3 * 2, align: 16, size: 32, pad: 4, [0, 1]),
(Mat3x3, ColumnMatrix3, f32, Vec3, 3 * 3, align: 16, size: 48, pad: 4, [0, 1, 2]),
(Mat3x4, ColumnMatrix3x4, f32, Vec3, 3 * 4, align: 16, size: 64, pad: 4, [0, 1, 2, 3]),
(Mat4x2, ColumnMatrix4x2, f32, Vec4, 4 * 2, align: 16, size: 32, pad: 0, [0, 1]),
(Mat4x3, ColumnMatrix4x3, f32, Vec4, 4 * 3, align: 16, size: 48, pad: 0, [0, 1, 2]),
(Mat4x4, ColumnMatrix4, f32, Vec4, 4 * 4, align: 16, size: 64, pad: 0, [0, 1, 2, 3]),
(DMat2x2, ColumnMatrix2, f64, DVec2, 2 * 2, align: 16, size: 32, pad: 0, [0, 1]),
(DMat2x3, ColumnMatrix2x3, f64, DVec2, 2 * 3, align: 16, size: 48, pad: 0, [0, 1, 2]),
(DMat2x4, ColumnMatrix2x4, f64, DVec2, 2 * 4, align: 16, size: 64, pad: 0, [0, 1, 2, 3]),
(DMat3x2, ColumnMatrix3x2, f64, DVec3, 3 * 2, align: 32, size: 64, pad: 0, [0, 1]),
(DMat3x3, ColumnMatrix3, f64, DVec3, 3 * 3, align: 32, size: 96, pad: 0, [0, 1, 2]),
(DMat3x4, ColumnMatrix3x4, f64, DVec3, 3 * 4, align: 32, size: 128, pad: 0, [0, 1, 2, 3]),
(DMat4x2, ColumnMatrix4x2, f64, DVec4, 4 * 2, align: 32, size: 64, pad: 0, [0, 1]),
(DMat4x3, ColumnMatrix4x3, f64, DVec4, 4 * 3, align: 32, size: 96, pad: 0, [0, 1, 2]),
(DMat4x4, ColumnMatrix4, f64, DVec4, 4 * 4, align: 32, size: 128, pad: 0, [0, 1, 2, 3]),
}
pub type Mat2 = Mat2x2;
pub type Mat3 = Mat3x3;
pub type Mat4 = Mat4x4;
pub type DMat2 = DMat2x2;
pub type DMat3 = DMat3x3;
pub type DMat4 = DMat4x4;
#[repr(C, align(16))]
#[derive(Debug, Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct ArrayMember<T>(pub T);
#[cfg(feature = "bytemuck")]
unsafe impl<T: bytemuck::Zeroable> bytemuck::Zeroable for ArrayMember<T> {}
#[cfg(feature = "bytemuck")]
unsafe impl<T: bytemuck::Pod> bytemuck::Pod for ArrayMember<T> {}
#[repr(C, align(256))]
#[derive(Debug, Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct DynamicOffsetMember<T>(pub T);
#[cfg(feature = "bytemuck")]
unsafe impl<T: bytemuck::Zeroable> bytemuck::Zeroable for DynamicOffsetMember<T> {}
#[cfg(feature = "bytemuck")]
unsafe impl<T: bytemuck::Pod> bytemuck::Pod for DynamicOffsetMember<T> {}
pub mod padding {
macro_rules! define_padding {
($name:ident, $count:literal <- $doc:literal) => {
#[doc = $doc]
#[repr(C)]
#[derive(Debug, Copy, Clone, Default, PartialEq, PartialOrd)]
pub struct $name {
_padding: [u8; $count],
}
#[cfg(feature = "bytemuck")]
unsafe impl bytemuck::Zeroable for $name {}
#[cfg(feature = "bytemuck")]
unsafe impl bytemuck::Pod for $name {}
impl $name {
#[inline(always)]
pub fn new() -> Self {
Self::default()
}
}
};
}
define_padding!(Pad1Float, 4 <- "Padding the size of a single float/uint/int. 4 bytes.");
define_padding!(Pad2Float, 8 <- "Padding the size of two floats/uints/ints. 8 bytes.");
define_padding!(Pad3Float, 12 <- "Padding the size of three floats/uints/ints. 12 bytes.");
define_padding!(Pad4Float, 16 <- "Padding the size of four floats/uints/ints. 16 bytes.");
define_padding!(Pad1Double, 8 <- "Padding the size of a single double. 8 bytes.");
define_padding!(Pad2Double, 16 <- "Padding the size of two doubles. 16 bytes.");
define_padding!(Pad3Double, 24 <- "Padding the size of three doubles. 24 bytes.");
define_padding!(Pad4Double, 32 <- "Padding the size of four doubles. 32 bytes.");
}
#[cfg(test)]
mod test {
use crate::*;
use core::mem::size_of;
use glsl_layout::AsStd140;
use std::ptr::null;
#[repr(C)]
struct Test1 {
a: Vec3,
b: u32,
}
#[repr(C)]
struct Test2 {
a: std140::vec3,
b: std140::uint,
}
#[derive(AsStd140)]
struct Test3 {
a: glsl_layout::vec3,
b: glsl_layout::int,
}
type Test3U = <Test3 as AsStd140>::Std140;
#[test]
fn sizes() {
assert_eq!((&unsafe { &*null::<Test3U>() }.b) as *const i32 as usize, 12);
assert_eq!(size_of::<Test3U>(), 16);
}
}