1use encase::{
2 self,
3 private::{AlignmentValue, Writer},
4};
5use wgpu;
6
7#[derive(Clone)]
10pub struct Buffer {
11 pub buffer: wgpu::Buffer,
12 pub size_bytes: usize,
13 cpu_byte_buffer: Vec<u8>,
14 offset: usize,
15 alignment: AlignmentValue,
16}
17
18impl Buffer {
19 pub fn new_empty(device: &wgpu::Device, usage: wgpu::BufferUsages, label: wgpu::Label, size_bytes: usize) -> Self {
20 let buffer = device.create_buffer(&wgpu::BufferDescriptor {
21 label,
22 size: size_bytes as u64,
23 usage,
24 mapped_at_creation: false,
25 });
26
27 let cpu_byte_buffer = Vec::new();
28
29 Self {
30 buffer,
31 size_bytes,
32 cpu_byte_buffer,
34 offset: 0,
35 alignment: AlignmentValue::new(256),
36 }
37 }
38
39 pub fn is_empty(&self) -> bool {
40 self.size_bytes == 0
41 }
42
43 pub fn write_buffer(&mut self, queue: &wgpu::Queue, offset_bytes: usize, data: &[u8]) {
44 queue.write_buffer(&self.buffer, offset_bytes as u64, bytemuck::cast_slice(data));
45 }
46
47 pub fn push_cpu_chunk_aligned<T: encase::ShaderType + encase::internal::WriteInto>(&mut self, chunk: &T) -> u32 {
53 let offset = self.offset;
54 let mut writer = Writer::new(chunk, &mut self.cpu_byte_buffer, offset).unwrap();
55 chunk.write_into(&mut writer);
56 self.offset += usize::try_from(self.alignment.round_up(chunk.size().get())).unwrap();
58 u32::try_from(offset).unwrap()
59 }
60
61 pub fn push_cpu_chunk_packed<T: encase::ShaderType + encase::internal::WriteInto>(&mut self, chunk: &T) {
68 let offset = self.offset;
69 let mut writer = Writer::new(chunk, &mut self.cpu_byte_buffer, offset).unwrap();
70 chunk.write_into(&mut writer);
71 self.offset += usize::try_from(chunk.size().get()).unwrap();
72 }
73
74 pub fn upload_from_cpu_chunks(&mut self, queue: &wgpu::Queue) {
76 queue.write_buffer(&self.buffer, 0, self.cpu_byte_buffer.as_slice());
78 }
79
80 pub fn reset_chunks_offset(&mut self) {
83 self.offset = 0;
84 }
85
86 pub fn reset_chunks_offset_if_necessary(&mut self) {
91 if self.offset > self.size_bytes / 2 {
93 self.offset = 0;
94 }
95 }
96
97 pub fn offset(&self) -> usize {
98 self.offset
99 }
100}