use super::context::GpuContext;
use std::sync::Arc;
pub struct GpuBufferFactory {
device: Arc<wgpu::Device>,
}
impl GpuBufferFactory {
pub fn new(ctx: &GpuContext) -> Self {
Self {
device: ctx.device.clone(),
}
}
pub fn create_storage_buffer(&self, label: &str, size: u64) -> wgpu::Buffer {
self.device.create_buffer(&wgpu::BufferDescriptor {
label: Some(label),
size,
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
})
}
pub fn create_storage_buffer_init(&self, label: &str, data: &[u8]) -> wgpu::Buffer {
use wgpu::util::DeviceExt;
self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(label),
contents: data,
usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
})
}
pub fn create_read_buffer(&self, label: &str, size: u64) -> wgpu::Buffer {
self.device.create_buffer(&wgpu::BufferDescriptor {
label: Some(label),
size,
usage: wgpu::BufferUsages::STORAGE
| wgpu::BufferUsages::COPY_SRC
| wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
})
}
pub fn create_staging_buffer(&self, label: &str, size: u64) -> wgpu::Buffer {
self.device.create_buffer(&wgpu::BufferDescriptor {
label: Some(label),
size,
usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
})
}
pub fn create_uniform_buffer(&self, label: &str, size: u64) -> wgpu::Buffer {
self.device.create_buffer(&wgpu::BufferDescriptor {
label: Some(label),
size,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
})
}
pub fn create_uniform_buffer_init(&self, label: &str, data: &[u8]) -> wgpu::Buffer {
use wgpu::util::DeviceExt;
self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(label),
contents: data,
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
})
}
}
pub async fn read_buffer(
device: &wgpu::Device,
queue: &wgpu::Queue,
buffer: &wgpu::Buffer,
size: u64,
) -> Vec<u8> {
let staging = device.create_buffer(&wgpu::BufferDescriptor {
label: Some("staging-read"),
size,
usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("read-encoder"),
});
encoder.copy_buffer_to_buffer(buffer, 0, &staging, 0, size);
queue.submit(Some(encoder.finish()));
let slice = staging.slice(..);
let (tx, rx) = std::sync::mpsc::channel();
slice.map_async(wgpu::MapMode::Read, move |result| {
tx.send(result).unwrap();
});
device.poll(wgpu::Maintain::Wait);
rx.recv().unwrap().unwrap();
let data = slice.get_mapped_range().to_vec();
staging.unmap();
data
}
pub fn read_buffer_sync(
device: &wgpu::Device,
queue: &wgpu::Queue,
buffer: &wgpu::Buffer,
size: u64,
) -> Vec<u8> {
pollster::block_on(read_buffer(device, queue, buffer, size))
}