use std::fmt::Debug;
pub unsafe trait Vertex: Copy {
fn vertex_desc() -> VertexDesc;
}
unsafe impl Vertex for () {
fn vertex_desc() -> VertexDesc {
Vec::new()
}
}
pub trait Deinterleave<T> {
const RANK: usize;
}
pub type VertexDesc = Vec<VertexBufferDesc>;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct VertexBufferDesc {
pub index: usize,
pub name: &'static str,
pub instancing: VertexInstancing,
pub attrib_desc: VertexAttribDesc,
}
impl VertexBufferDesc {
pub fn new<S>(sem: S, instancing: VertexInstancing, attrib_desc: VertexAttribDesc) -> Self
where
S: Semantics,
{
let index = sem.index();
let name = sem.name();
VertexBufferDesc {
index,
name,
instancing,
attrib_desc,
}
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum VertexInstancing {
On,
Off,
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct VertexAttribDesc {
pub ty: VertexAttribType,
pub dim: VertexAttribDim,
pub unit_size: usize,
pub align: usize,
}
impl VertexAttribDesc {
pub fn normalize(self) -> Self {
VertexAttribDesc {
ty: self.ty.normalize(),
..self
}
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum VertexAttribType {
Integral(Normalized),
Unsigned(Normalized),
Floating,
Boolean,
}
impl VertexAttribType {
pub fn normalize(self) -> Self {
match self {
VertexAttribType::Integral(Normalized::No) => VertexAttribType::Integral(Normalized::Yes),
VertexAttribType::Unsigned(Normalized::No) => VertexAttribType::Unsigned(Normalized::Yes),
_ => self,
}
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Normalized {
Yes,
No,
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum VertexAttribDim {
Dim1,
Dim2,
Dim3,
Dim4,
}
pub unsafe trait VertexAttrib {
const VERTEX_ATTRIB_DESC: VertexAttribDesc;
}
pub trait Semantics: Sized + Copy + Clone + Debug {
fn index(&self) -> usize;
fn name(&self) -> &'static str;
fn semantics_set() -> Vec<SemanticsDesc>;
}
impl Semantics for () {
fn index(&self) -> usize {
0
}
fn name(&self) -> &'static str {
""
}
fn semantics_set() -> Vec<SemanticsDesc> {
Vec::new()
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct SemanticsDesc {
pub index: usize,
pub name: String,
}
pub trait HasSemantics {
type Sem: Semantics;
const SEMANTICS: Self::Sem;
}
#[inline(always)]
const fn size_of<T>() -> usize {
#[cfg(feature = "std")]
{
::std::mem::size_of::<T>()
}
#[cfg(not(feature = "std"))]
{
::core::mem::size_of::<T>()
}
}
#[inline(always)]
const fn align_of<T>() -> usize {
#[cfg(feature = "std")]
{
::std::mem::align_of::<T>()
}
#[cfg(not(feature = "std"))]
{
::core::mem::align_of::<T>()
}
}
macro_rules! impl_vertex_attribute {
($t:ty, $q:ty, $attr_ty:expr, $dim:expr) => {
unsafe impl VertexAttrib for $t {
const VERTEX_ATTRIB_DESC: VertexAttribDesc = VertexAttribDesc {
ty: $attr_ty,
dim: $dim,
unit_size: $crate::vertex::size_of::<$q>(),
align: $crate::vertex::align_of::<$q>(),
};
}
};
($t:ty, $attr_ty:expr) => {
impl_vertex_attribute!($t, $t, $attr_ty, VertexAttribDim::Dim1);
impl_vertex_attribute!([$t; 1], $t, $attr_ty, VertexAttribDim::Dim1);
impl_vertex_attribute!([$t; 2], $t, $attr_ty, VertexAttribDim::Dim2);
impl_vertex_attribute!([$t; 3], $t, $attr_ty, VertexAttribDim::Dim3);
impl_vertex_attribute!([$t; 4], $t, $attr_ty, VertexAttribDim::Dim4);
};
}
impl_vertex_attribute!(i8, VertexAttribType::Integral(Normalized::No));
impl_vertex_attribute!(i16, VertexAttribType::Integral(Normalized::No));
impl_vertex_attribute!(i32, VertexAttribType::Integral(Normalized::No));
impl_vertex_attribute!(u8, VertexAttribType::Unsigned(Normalized::No));
impl_vertex_attribute!(u16, VertexAttribType::Unsigned(Normalized::No));
impl_vertex_attribute!(u32, VertexAttribType::Unsigned(Normalized::No));
impl_vertex_attribute!(f32, VertexAttribType::Floating);
impl_vertex_attribute!(f64, VertexAttribType::Floating);
impl_vertex_attribute!(bool, VertexAttribType::Boolean);