use bytemuck::Pod; use wgpu::util::DeviceExt; pub struct Buffer { pub(super) buf: wgpu::Buffer, // Size in number of elements // TODO: determine if this is a good name len: usize, phantom_data: std::marker::PhantomData, } impl Buffer { pub fn new(device: &wgpu::Device, usage: wgpu::BufferUsage, data: &[T]) -> Self { let contents = bytemuck::cast_slice(data); Self { buf: device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: None, contents, usage, }), len: data.len(), phantom_data: std::marker::PhantomData, } } #[allow(clippy::len_without_is_empty)] pub fn len(&self) -> usize { self.len } } pub struct DynamicBuffer(Buffer); impl DynamicBuffer { pub fn new(device: &wgpu::Device, len: usize, usage: wgpu::BufferUsage) -> Self { let buffer = Buffer { buf: device.create_buffer(&wgpu::BufferDescriptor { label: None, mapped_at_creation: false, size: len as u64 * std::mem::size_of::() as u64, usage: usage | wgpu::BufferUsage::COPY_DST, }), len, phantom_data: std::marker::PhantomData, }; Self(buffer) } pub fn update(&self, queue: &wgpu::Queue, vals: &[T], offset: usize) { if !vals.is_empty() { queue.write_buffer( &self.buf, offset as u64 * std::mem::size_of::() as u64, bytemuck::cast_slice(vals), ) } } } impl std::ops::Deref for DynamicBuffer { type Target = Buffer; fn deref(&self) -> &Self::Target { &self.0 } }