//! Utilities for buffer operations. pub mod dynamic; pub mod r#static; use std::marker::PhantomData; use std::ops::RangeBounds; #[derive(Debug)] pub struct Buffer { label: &'static str, size: u64, usage: wgpu::BufferUsages, raw: wgpu::Buffer, type_: PhantomData, } impl Buffer { pub fn new( device: &wgpu::Device, label: &'static str, amount: usize, usage: wgpu::BufferUsages, ) -> Self { let size = next_copy_size::(amount); let raw = device.create_buffer(&wgpu::BufferDescriptor { label: Some(label), size, usage, mapped_at_creation: false, }); Self { label, size, usage, raw, type_: PhantomData, } } pub fn resize(&mut self, device: &wgpu::Device, new_count: usize) -> bool { let new_size = (std::mem::size_of::() * new_count) as u64; if self.size < new_size { self.raw = device.create_buffer(&wgpu::BufferDescriptor { label: Some(self.label), size: new_size, usage: self.usage, mapped_at_creation: false, }); self.size = new_size; true } else { false } } pub fn write( &self, queue: &wgpu::Queue, offset_count: usize, contents: &[T], ) { queue.write_buffer( &self.raw, (std::mem::size_of::() * offset_count) as u64, bytemuck::cast_slice(contents), ); } pub fn slice( &self, bounds: impl RangeBounds, ) -> wgpu::BufferSlice<'_> { self.raw.slice(bounds) } } fn next_copy_size(amount: usize) -> u64 { let align_mask = wgpu::COPY_BUFFER_ALIGNMENT - 1; (((std::mem::size_of::() * amount).next_power_of_two() as u64 + align_mask) & !align_mask) .max(wgpu::COPY_BUFFER_ALIGNMENT) }