Add GpuVec

This commit is contained in:
mars 2022-05-07 21:49:30 -06:00
parent ea3b065b28
commit fd12726efb
2 changed files with 113 additions and 0 deletions

112
src/gpu.rs Normal file
View File

@ -0,0 +1,112 @@
use bytemuck::Pod;
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
pub struct GpuVec<T> {
device: Arc<wgpu::Device>,
data: Vec<T>,
buffer: wgpu::Buffer,
capacity: usize,
usage: wgpu::BufferUsages,
label: Option<String>,
realign: Option<usize>,
}
impl<T: Clone + Pod> GpuVec<T> {
pub fn new(
device: Arc<wgpu::Device>,
usage: wgpu::BufferUsages,
initial_capacity: usize,
label: Option<String>,
) -> Self {
let capacity_bytes = initial_capacity * std::mem::size_of::<T>();
let usage = usage | wgpu::BufferUsages::COPY_DST;
let buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: label.as_ref().map(|s| s.as_str()),
size: capacity_bytes as wgpu::BufferAddress,
usage,
mapped_at_creation: false,
});
let data = Vec::with_capacity(initial_capacity);
let realign = if usage.contains(wgpu::BufferUsages::STORAGE) {
Some(device.limits().min_storage_buffer_offset_alignment as usize)
} else if usage.contains(wgpu::BufferUsages::UNIFORM) {
Some(device.limits().min_uniform_buffer_offset_alignment as usize)
} else {
None
};
Self {
device,
data,
buffer,
capacity: capacity_bytes,
usage,
label,
realign,
}
}
pub fn write(&mut self, queue: &wgpu::Queue) -> &wgpu::Buffer {
let capacity_bytes = self.buf_offset(self.data.capacity());
if capacity_bytes != self.capacity && capacity_bytes != 0 {
self.capacity = capacity_bytes;
self.buffer = self.device.create_buffer(&wgpu::BufferDescriptor {
label: self.label.as_ref().map(|s| s.as_str()),
size: capacity_bytes as wgpu::BufferAddress,
usage: self.usage,
mapped_at_creation: false,
});
}
let mut realigned = Vec::new();
let src_buf = if let Some(realign) = self.realign {
realigned.resize(self.data.len() * realign, 0);
for (index, elem) in self.data.iter().enumerate() {
let elem = [elem.clone()];
let casted: &[u8] = bytemuck::cast_slice(&elem);
let dst_offset = index * realign;
realigned[dst_offset..(dst_offset + casted.len())].copy_from_slice(casted);
}
realigned.as_slice()
} else {
bytemuck::cast_slice(self.data.as_slice())
};
queue.write_buffer(&self.buffer, 0, src_buf);
&self.buffer
}
pub fn buf_offset(&self, index: usize) -> usize {
if let Some(realign) = self.realign {
index * realign
} else {
index * std::mem::size_of::<T>()
}
}
}
impl<T: Pod> AsRef<wgpu::Buffer> for GpuVec<T> {
fn as_ref(&self) -> &wgpu::Buffer {
&self.buffer
}
}
impl<T: Pod> Deref for GpuVec<T> {
type Target = Vec<T>;
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl<T: Pod> DerefMut for GpuVec<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}

View File

@ -6,6 +6,7 @@ use std::sync::Arc;
use std::sync::Mutex;
pub mod camera;
pub mod gpu;
pub mod mesh;
pub mod pass;
pub mod phase;