diff options
Diffstat (limited to 'src/instance.rs')
| -rw-r--r-- | src/instance.rs | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/src/instance.rs b/src/instance.rs index eded8cf..dc1ee40 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -3,7 +3,7 @@ use std::mem::size_of; use bytemuck::{Pod, Zeroable}; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub struct InstanceId(pub(crate) usize); +pub struct InstanceId(usize); #[repr(C)] #[derive(Copy, Clone, Debug, PartialEq, Pod, Zeroable)] @@ -58,3 +58,92 @@ impl Instance { } } } + +pub struct InstanceBuffer { + instances: Vec<Instance>, + instance_buffer: wgpu::Buffer, + instance_buffer_size: usize, +} + +fn create_buffer(device: &wgpu::Device, instances: &Vec<Instance>) -> wgpu::Buffer { + device.create_buffer(&wgpu::BufferDescriptor { + label: Some("Sprite Instance Buffer"), + size: (instances.capacity() * size_of::<Instance>()) as wgpu::BufferAddress, + usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }) +} + +impl InstanceBuffer { + pub(crate) fn new(device: &wgpu::Device, capacity: usize) -> Self { + let instances = Vec::with_capacity(capacity); + let instance_buffer_size = instances.capacity(); + let instance_buffer = device.create_buffer(&wgpu::BufferDescriptor { + label: Some("Sprite Instance Buffer"), + size: (instance_buffer_size * size_of::<Instance>()) as wgpu::BufferAddress, + usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST, + mapped_at_creation: false, + }); + + Self { + instances, + instance_buffer, + instance_buffer_size, + } + } + + pub fn len(&self) -> u32 { + self.instances + .len() + .try_into() + .expect("expected less than 3 billion instances") + } + + pub fn is_empty(&self) -> bool { + self.instances.is_empty() + } + + pub const fn buffer_size(&self) -> usize { + self.instance_buffer_size + } + + pub(crate) fn buffer_slice(&self) -> wgpu::BufferSlice { + self.instance_buffer.slice(..) + } + + pub fn push_instance(&mut self, instance: Instance) -> InstanceId { + let index = self.instances.len(); + self.instances.push(instance); + InstanceId(index) + } + + pub fn get_instance(&self, id: InstanceId) -> Option<&Instance> { + self.instances.get(id.0) + } + + pub fn get_instance_mut(&mut self, id: InstanceId) -> Option<&mut Instance> { + self.instances.get_mut(id.0) + } + + pub fn clear(&mut self) { + self.instances.clear(); + } + + fn expand_buffer(&mut self, device: &wgpu::Device) { + self.instance_buffer_size = self.instances.capacity(); + self.instance_buffer = create_buffer(device, &self.instances); + } + + #[profiling::function] + pub(crate) fn fill_buffer(&mut self, device: &wgpu::Device, queue: &wgpu::Queue) { + if self.instances.len() > self.instance_buffer_size { + self.expand_buffer(device); + } + + queue.write_buffer( + &self.instance_buffer, + 0 as wgpu::BufferAddress, + bytemuck::cast_slice(&self.instances), + ); + } +} |
