Files
fractal/src/client/render/util/storage.rs
T
2026-05-02 15:26:20 -04:00

80 lines
2.5 KiB
Rust

use std::marker::PhantomData;
use wgpu::util::DeviceExt;
pub struct Storage {
buffer: wgpu::Buffer,
old_len: usize,
}
impl Storage {
pub fn init<T: Default + bytemuck::Pod>(device: &wgpu::Device, name: &str) -> Self {
let def = [T::default()];
let default = bytemuck::cast_slice(&def);
Self {
buffer: device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&(name.to_owned() + " Uniform Buf")),
contents: default,
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
}),
old_len: default.len(),
}
}
pub fn init_with(device: &wgpu::Device, name: &str, data: &[u8]) -> Self {
Self {
buffer: Self::init_buf(device, name, data),
old_len: data.len(),
}
}
pub fn init_buf(device: &wgpu::Device, name: &str, data: &[u8]) -> wgpu::Buffer {
device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(&(name.to_owned() + " Uniform Buf")),
contents: data,
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
})
}
pub fn update(
&mut self,
device: &wgpu::Device,
encoder: &mut wgpu::CommandEncoder,
belt: &mut wgpu::util::StagingBelt,
data: &[u8],
) -> bool {
if data.len() != self.old_len {
self.buffer = Self::init_buf(device, "too lazy", data);
self.old_len = data.len();
true
} else {
let mut view = belt.write_buffer(encoder, &self.buffer, 0, unsafe {
std::num::NonZeroU64::new_unchecked(std::mem::size_of_val(data) as u64)
});
view.copy_from_slice(data);
false
}
}
pub fn bind_group_layout_entry(
&self,
binding: u32,
read_only: bool,
visibility: wgpu::ShaderStages,
) -> wgpu::BindGroupLayoutEntry {
wgpu::BindGroupLayoutEntry {
binding,
visibility,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Storage { read_only },
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
}
}
pub fn bind_group_entry(&self, binding: u32) -> wgpu::BindGroupEntry<'_> {
wgpu::BindGroupEntry {
binding,
resource: self.buffer.as_entire_binding(),
}
}
}