use std::mem; use wgpu::util::{BufferInitDescriptor, DeviceExt}; pub trait ToRaw { type Output; fn to_raw(&self) -> Self::Output; } pub struct RawBuffer where R: Copy + bytemuck::Pod + bytemuck::Zeroable, { pub buffer: wgpu::Buffer, pub data: Vec, } impl RawBuffer { pub fn from_slice>( device: &wgpu::Device, data: &[T], usage: wgpu::BufferUsage, ) -> Self { let raw_data = data.iter().map(ToRaw::to_raw).collect::>(); Self::from_vec(device, raw_data, usage) } pub fn from_vec(device: &wgpu::Device, data: Vec, usage: wgpu::BufferUsage) -> Self { let buffer = device.create_buffer_init(&BufferInitDescriptor { contents: bytemuck::cast_slice(&data), usage, label: None, }); Self::from_parts(buffer, data, usage) } pub fn from_parts(buffer: wgpu::Buffer, data: Vec, _usage: wgpu::BufferUsage) -> Self { Self { buffer, data } } pub fn buffer_size(&self) -> wgpu::BufferAddress { (self.data.len() * mem::size_of::()) as wgpu::BufferAddress } } pub struct Buffer, R: Copy + bytemuck::Pod + bytemuck::Zeroable> { pub data: Vec, pub raw_buffer: RawBuffer, pub usage: wgpu::BufferUsage, } impl, R: Copy + bytemuck::Pod + bytemuck::Zeroable> Buffer { pub fn uniform(device: &wgpu::Device, datum: U) -> Self { let data = vec![datum]; let usage = wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST; Self::with_usage(device, data, usage) } pub fn storage(device: &wgpu::Device, data: Vec) -> Self { let usage = wgpu::BufferUsage::STORAGE | wgpu::BufferUsage::COPY_DST; Self::with_usage(device, data, usage) } pub fn staging(device: &wgpu::Device, other: &Self) -> Self { let buffer_size = other.raw_buffer.buffer_size(); let usage = wgpu::BufferUsage::COPY_SRC | wgpu::BufferUsage::MAP_READ | wgpu::BufferUsage::MAP_WRITE; let buffer = device.create_buffer(&wgpu::BufferDescriptor { size: buffer_size, usage, label: None, mapped_at_creation: false, }); let raw_buffer = RawBuffer::from_parts(buffer, Vec::new(), usage); Self::from_parts(Vec::new(), raw_buffer, usage) } pub fn with_usage(device: &wgpu::Device, data: Vec, usage: wgpu::BufferUsage) -> Self { let raw_buffer = RawBuffer::from_slice(device, &data, usage); Self::from_parts(data, raw_buffer, usage) } pub fn from_parts(data: Vec, raw_buffer: RawBuffer, usage: wgpu::BufferUsage) -> Self { Self { data, raw_buffer, usage, } } }