use std::marker::PhantomData; use crate::reflect::semantics::MemberOffset; pub trait UniformScalar: Copy + bytemuck::Pod {} impl UniformScalar for f32 {} impl UniformScalar for i32 {} impl UniformScalar for u32 {} pub struct NoUniformBinder; impl BindUniform, T> for NoUniformBinder { fn bind_uniform(_: T, _: Option<()>) -> Option<()> { None } } pub trait BindUniform { fn bind_uniform(value: T, ctx: C) -> Option<()>; } pub struct UniformStorage> { pub ubo: Box<[u8]>, pub push: Box<[u8]>, _h: PhantomData, _c: PhantomData } impl UniformStorage where H: BindUniform, H: BindUniform, H: BindUniform, H: for <'a> BindUniform, H: for <'a> BindUniform { pub fn new(ubo_size: usize, push_size: usize) -> Self { UniformStorage { ubo: vec![0u8; ubo_size].into_boxed_slice(), push: vec![0u8; push_size].into_boxed_slice(), _h: Default::default(), _c: Default::default(), } } #[inline(always)] fn write_scalar_inner(buffer: &mut [u8], value: T, ctx: C) where H: BindUniform { if let None = H::bind_uniform(value, ctx) { let buffer = bytemuck::cast_slice_mut(buffer); buffer[0] = value; }; } fn write_mat4_inner(buffer: &mut [u8], mat4: &[f32; 16], ctx: C) { if let None = H::bind_uniform(mat4, ctx) { let mat4 = bytemuck::cast_slice(mat4); buffer.copy_from_slice(mat4); } } fn write_vec4_inner(buffer: &mut [u8], vec4: impl Into<[f32; 4]>, ctx: C) { let vec4 = vec4.into(); if let None = H::bind_uniform(&vec4, ctx) { let vec4 = bytemuck::cast_slice(&vec4); buffer.copy_from_slice(vec4); } } pub fn bind_mat4(&mut self, offset: MemberOffset, value: &[f32; 16], ctx: C) { let (buffer, offset) = match offset { MemberOffset::Ubo(offset) => (&mut self.ubo, offset), MemberOffset::PushConstant(offset) => (&mut self.push, offset), }; Self::write_mat4_inner(&mut buffer[offset..][..16 * std::mem::size_of::()], value, ctx); } pub fn bind_vec4(&mut self, offset: MemberOffset, value: impl Into<[f32; 4]>, ctx: C) { let (buffer, offset) = match offset { MemberOffset::Ubo(offset) => (&mut self.ubo, offset), MemberOffset::PushConstant(offset) => (&mut self.push, offset), }; Self::write_vec4_inner(&mut buffer[offset..][..4 * std::mem::size_of::()], value, ctx); } pub fn bind_scalar(&mut self, offset: MemberOffset, value: T, ctx: C) where H: BindUniform { let (buffer, offset) = match offset { MemberOffset::Ubo(offset) => (&mut self.ubo, offset), MemberOffset::PushConstant(offset) => (&mut self.push, offset), }; Self::write_scalar_inner(&mut buffer[offset..][..std::mem::size_of::()], value, ctx) } }