typed primitive buffers + macro for creation
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user