summaryrefslogtreecommitdiff
path: root/src/instance.rs
diff options
context:
space:
mode:
authorMicha White <botahamec@outlook.com>2022-10-12 12:06:37 -0400
committerMicha White <botahamec@outlook.com>2022-10-12 12:06:37 -0400
commit3c1822640f09d23c55a5e9a8fe4d131eb539d2f4 (patch)
treed2180000735118faeceb5148c3c5552381e6d0fc /src/instance.rs
parent3352e94bade525c9922b448208b1e6c44fc3340d (diff)
Move out instance logic
Diffstat (limited to 'src/instance.rs')
-rw-r--r--src/instance.rs91
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),
+ );
+ }
+}