Skip to main content

ursus_core/vulkan/resources/
growable_buffer.rs

1use crate::vulkan::MappedGpuBuffer;
2use ash::vk;
3
4pub struct GrowableBuffer {
5    inner: MappedGpuBuffer<u8>,
6    len: usize,
7    device: ash::Device,
8    physical_device: vk::PhysicalDevice,
9    instance: ash::Instance,
10    usage: vk::BufferUsageFlags,
11}
12
13impl GrowableBuffer {
14    pub fn new(
15        device: &ash::Device,
16        physical_device: vk::PhysicalDevice,
17        instance: &ash::Instance,
18        usage: vk::BufferUsageFlags,
19        initial_capacity: usize,
20    ) -> anyhow::Result<Self> {
21        let inner = MappedGpuBuffer::new(device, physical_device, instance, usage, initial_capacity.max(1))?;
22        Ok(Self { inner, len: 0, device: device.clone(), physical_device, instance: instance.clone(), usage })
23    }
24
25    pub fn buffer(&self) -> vk::Buffer {
26        self.inner.buffer
27    }
28
29    pub fn capacity(&self) -> usize {
30        self.inner.capacity
31    }
32
33    pub fn len(&self) -> usize {
34        self.len
35    }
36
37    pub fn is_empty(&self) -> bool {
38        self.len == 0
39    }
40
41    /// Replaces the buffer's contents with `bytes`, growing the underlying
42    /// GPU buffer first if it isn't large enough. Returns `true` if the
43    /// underlying `vk::Buffer` handle changed (a reallocation happened) -
44    /// callers that keep a descriptor pointing at this buffer must rewrite
45    /// that descriptor when this returns `true`.
46    pub fn upload(&mut self, bytes: &[u8]) -> anyhow::Result<bool> {
47        let mut reallocated = false;
48        if bytes.len() > self.inner.capacity {
49            let new_capacity = bytes.len().next_power_of_two();
50            self.inner =
51                MappedGpuBuffer::new(&self.device, self.physical_device, &self.instance, self.usage, new_capacity)?;
52            reallocated = true;
53        }
54        self.inner.upload_slice(bytes);
55        self.len = bytes.len();
56        Ok(reallocated)
57    }
58}