typed primitive buffers + macro for creation

This commit is contained in:
2025-08-21 19:37:50 -04:00
parent b7f83b58a9
commit bde929b05a
5 changed files with 190 additions and 105 deletions

View File

@@ -1,27 +1,93 @@
use crate::Color;
pub use super::data::PrimitiveInstance;
use crate::{
Color, UiRegion,
render::{ArrBuf, data::PrimitiveInstance},
};
use bytemuck::Pod;
use wgpu::*;
#[derive(Default)]
pub struct Primitives {
pub instances: Vec<PrimitiveInstance>,
pub data: Vec<u32>,
pub(super) instances: Vec<PrimitiveInstance>,
pub(super) data: PrimitiveData,
}
/// NOTE: Self must have at least u32 alignment
pub trait PrimitiveData: bytemuck::Pod {
const DISCRIM: u32;
pub trait Primitive: Pod {
const BINDING: u32;
fn vec(data: &mut PrimitiveData) -> &mut Vec<Self>;
}
macro_rules! primitives {
($($name:ident: $ty:ty => $binding:expr,)*) => {
#[derive(Default)]
pub struct PrimitiveData {
$($name: Vec<$ty>,)*
}
pub struct PrimitiveBuffers {
$($name: ArrBuf<$ty>,)*
}
impl PrimitiveBuffers {
pub fn update(&mut self, device: &Device, queue: &Queue, data: &PrimitiveData) {
$(self.$name.update(device, queue, &data.$name);)*
}
}
impl PrimitiveBuffers {
pub const LEN: usize = primitives!(@count $($name)*);
pub fn buffers(&self) -> [&Buffer; Self::LEN] {
[
$(&self.$name.buffer)*
]
}
pub fn new(device: &Device) -> Self {
Self {
$($name: ArrBuf::new(
device,
BufferUsages::STORAGE | BufferUsages::COPY_DST,
stringify!($name),
))*
}
}
}
$(
unsafe impl bytemuck::Pod for $ty {}
unsafe impl bytemuck::Zeroable for $ty {}
impl Primitive for $ty {
const BINDING: u32 = $binding;
fn vec(data: &mut PrimitiveData) -> &mut Vec<Self> {
&mut data.$name
}
}
)*
};
(@count $t1:tt, $($t:tt),+) => { 1 + gen!(@count $($t),+) };
(@count $t:tt) => { 1 };
}
primitives!(
rects: RoundedRectData => 0,
);
impl Primitives {
pub fn write<P: Primitive>(&mut self, data: P, region: UiRegion) {
let vec = P::vec(&mut self.data);
let i = vec.len() as u32;
self.instances.push(PrimitiveInstance {
region,
idx: i,
binding: P::BINDING,
});
vec.push(data);
}
}
#[repr(C)]
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
#[derive(Copy, Clone)]
pub struct RoundedRectData {
pub color: Color<u8>,
pub radius: f32,
pub thickness: f32,
pub inner_radius: f32,
}
impl PrimitiveData for RoundedRectData {
const DISCRIM: u32 = 0;
}