veloren_voxygen/render/
buffer.rs

1use bytemuck::Pod;
2use wgpu::util::DeviceExt;
3
4pub struct Buffer<T: Copy + Pod> {
5    pub(super) buf: wgpu::Buffer,
6    // Size in number of elements
7    // TODO: determine if this is a good name
8    len: usize,
9    phantom_data: std::marker::PhantomData<T>,
10}
11
12impl<T: Copy + Pod> Buffer<T> {
13    pub fn new(device: &wgpu::Device, usage: wgpu::BufferUsages, data: &[T]) -> Self {
14        let contents = bytemuck::cast_slice(data);
15
16        Self {
17            buf: device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
18                label: None,
19                contents,
20                usage,
21            }),
22            len: data.len(),
23            phantom_data: std::marker::PhantomData,
24        }
25    }
26
27    #[expect(clippy::len_without_is_empty)]
28    pub fn len(&self) -> usize { self.len }
29}
30
31pub struct DynamicBuffer<T: Copy + Pod>(Buffer<T>);
32
33impl<T: Copy + Pod> DynamicBuffer<T> {
34    pub fn new(device: &wgpu::Device, len: usize, usage: wgpu::BufferUsages) -> Self {
35        let buffer = Buffer {
36            buf: device.create_buffer(&wgpu::BufferDescriptor {
37                label: None,
38                mapped_at_creation: false,
39                size: len as u64 * std::mem::size_of::<T>() as u64,
40                usage: usage | wgpu::BufferUsages::COPY_DST,
41            }),
42            len,
43            phantom_data: std::marker::PhantomData,
44        };
45        Self(buffer)
46    }
47
48    pub fn update(&self, queue: &wgpu::Queue, vals: &[T], offset: usize) {
49        if !vals.is_empty() {
50            queue.write_buffer(
51                &self.buf,
52                offset as u64 * std::mem::size_of::<T>() as u64,
53                bytemuck::cast_slice(vals),
54            )
55        }
56    }
57}
58
59impl<T: Copy + Pod> std::ops::Deref for DynamicBuffer<T> {
60    type Target = Buffer<T>;
61
62    fn deref(&self) -> &Self::Target { &self.0 }
63}