2021-06-21 23:28:52 +00:00
|
|
|
use crate::{render_resource::Buffer, renderer::RenderDevice};
|
2021-05-30 22:54:48 +00:00
|
|
|
use bevy_core::{cast_slice, Pod};
|
2021-06-21 23:28:52 +00:00
|
|
|
use wgpu::BufferUsage;
|
2021-04-11 20:13:07 +00:00
|
|
|
|
|
|
|
pub struct BufferVec<T: Pod> {
|
|
|
|
values: Vec<T>,
|
2021-06-21 23:28:52 +00:00
|
|
|
staging_buffer: Option<Buffer>,
|
|
|
|
buffer: Option<Buffer>,
|
2021-04-11 20:13:07 +00:00
|
|
|
capacity: usize,
|
|
|
|
item_size: usize,
|
|
|
|
buffer_usage: BufferUsage,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Pod> Default for BufferVec<T> {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
values: Vec::new(),
|
|
|
|
staging_buffer: None,
|
|
|
|
buffer: None,
|
|
|
|
capacity: 0,
|
|
|
|
buffer_usage: BufferUsage::all(),
|
|
|
|
item_size: std::mem::size_of::<T>(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Pod> BufferVec<T> {
|
|
|
|
pub fn new(buffer_usage: BufferUsage) -> Self {
|
|
|
|
Self {
|
|
|
|
buffer_usage,
|
|
|
|
..Default::default()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[inline]
|
2021-06-21 23:28:52 +00:00
|
|
|
pub fn staging_buffer(&self) -> Option<&Buffer> {
|
|
|
|
self.staging_buffer.as_ref()
|
2021-04-11 20:13:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2021-06-21 23:28:52 +00:00
|
|
|
pub fn buffer(&self) -> Option<&Buffer> {
|
|
|
|
self.buffer.as_ref()
|
2021-04-11 20:13:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn capacity(&self) -> usize {
|
|
|
|
self.capacity
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn push(&mut self, value: T) -> usize {
|
|
|
|
if self.values.len() < self.capacity {
|
|
|
|
let index = self.values.len();
|
|
|
|
self.values.push(value);
|
|
|
|
index
|
|
|
|
} else {
|
|
|
|
panic!(
|
|
|
|
"Cannot push value because capacity of {} has been reached",
|
|
|
|
self.capacity
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-21 23:28:52 +00:00
|
|
|
pub fn reserve(&mut self, capacity: usize, device: &RenderDevice) {
|
2021-04-11 20:13:07 +00:00
|
|
|
if capacity > self.capacity {
|
|
|
|
self.capacity = capacity;
|
2021-06-21 23:28:52 +00:00
|
|
|
let size = (self.item_size * capacity) as wgpu::BufferAddress;
|
|
|
|
self.staging_buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
|
|
|
|
label: None,
|
2021-04-11 20:13:07 +00:00
|
|
|
size,
|
2021-06-21 23:28:52 +00:00
|
|
|
usage: BufferUsage::COPY_SRC | BufferUsage::MAP_WRITE,
|
2021-04-11 20:13:07 +00:00
|
|
|
mapped_at_creation: false,
|
|
|
|
}));
|
2021-06-21 23:28:52 +00:00
|
|
|
self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
|
|
|
|
label: None,
|
2021-04-11 20:13:07 +00:00
|
|
|
size,
|
2021-06-21 23:28:52 +00:00
|
|
|
usage: BufferUsage::COPY_DST | self.buffer_usage,
|
2021-04-11 20:13:07 +00:00
|
|
|
mapped_at_creation: false,
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-21 23:28:52 +00:00
|
|
|
pub fn reserve_and_clear(&mut self, capacity: usize, device: &RenderDevice) {
|
2021-04-11 20:13:07 +00:00
|
|
|
self.clear();
|
2021-06-21 23:28:52 +00:00
|
|
|
self.reserve(capacity, device);
|
2021-04-11 20:13:07 +00:00
|
|
|
}
|
|
|
|
|
2021-06-21 23:28:52 +00:00
|
|
|
pub fn write_to_staging_buffer(&self, render_device: &RenderDevice) {
|
|
|
|
if let Some(staging_buffer) = &self.staging_buffer {
|
2021-07-07 00:04:43 +00:00
|
|
|
let end = (self.values.len() * self.item_size) as u64;
|
|
|
|
let slice = staging_buffer.slice(0..end);
|
2021-06-21 23:28:52 +00:00
|
|
|
render_device.map_buffer(&slice, wgpu::MapMode::Write);
|
|
|
|
{
|
|
|
|
let mut data = slice.get_mapped_range_mut();
|
|
|
|
let bytes: &[u8] = cast_slice(&self.values);
|
|
|
|
data.copy_from_slice(bytes);
|
|
|
|
}
|
|
|
|
staging_buffer.unmap();
|
2021-04-11 20:13:07 +00:00
|
|
|
}
|
|
|
|
}
|
2021-06-21 23:28:52 +00:00
|
|
|
pub fn write_to_buffer(&self, command_encoder: &mut wgpu::CommandEncoder) {
|
|
|
|
if let (Some(staging_buffer), Some(uniform_buffer)) = (&self.staging_buffer, &self.buffer) {
|
|
|
|
command_encoder.copy_buffer_to_buffer(
|
2021-04-11 20:13:07 +00:00
|
|
|
staging_buffer,
|
|
|
|
0,
|
|
|
|
uniform_buffer,
|
|
|
|
0,
|
|
|
|
(self.values.len() * self.item_size) as u64,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn clear(&mut self) {
|
|
|
|
self.values.clear();
|
|
|
|
}
|
|
|
|
}
|