diff options
Diffstat (limited to 'wgpu/src/buffer.rs')
-rw-r--r-- | wgpu/src/buffer.rs | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/wgpu/src/buffer.rs b/wgpu/src/buffer.rs index 7c092d0b..c210dd4e 100644 --- a/wgpu/src/buffer.rs +++ b/wgpu/src/buffer.rs @@ -1,3 +1,89 @@ //! Utilities for buffer operations. pub mod dynamic; pub mod r#static; + +use std::marker::PhantomData; +use std::ops::RangeBounds; + +#[derive(Debug)] +pub struct Buffer<T> { + label: &'static str, + size: u64, + usage: wgpu::BufferUsages, + raw: wgpu::Buffer, + type_: PhantomData<T>, +} + +impl<T: bytemuck::Pod> Buffer<T> { + pub fn new( + device: &wgpu::Device, + label: &'static str, + amount: usize, + usage: wgpu::BufferUsages, + ) -> Self { + let size = next_copy_size::<T>(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::<T>() * 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::<T>() * offset_count) as u64, + bytemuck::cast_slice(contents), + ); + } + + pub fn slice( + &self, + bounds: impl RangeBounds<wgpu::BufferAddress>, + ) -> wgpu::BufferSlice<'_> { + self.raw.slice(bounds) + } +} + +fn next_copy_size<T>(amount: usize) -> u64 { + let align_mask = wgpu::COPY_BUFFER_ALIGNMENT - 1; + + (((std::mem::size_of::<T>() * amount).next_power_of_two() as u64 + + align_mask) + & !align_mask) + .max(wgpu::COPY_BUFFER_ALIGNMENT) +} |