use super::GpuContext;
use wgpu::util::DeviceExt;
impl GpuContext {
pub fn create_buffer_init(&self, label: &str, data: &[u32]) -> wgpu::Buffer {
self.device
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(label),
contents: bytemuck::cast_slice(data),
usage: wgpu::BufferUsages::STORAGE
| wgpu::BufferUsages::COPY_SRC
| wgpu::BufferUsages::COPY_DST,
})
}
pub fn create_buffer_empty(&self, label: &str, count: u32) -> wgpu::Buffer {
self.device.create_buffer(&wgpu::BufferDescriptor {
label: Some(label),
size: count as u64 * 4,
usage: wgpu::BufferUsages::STORAGE
| wgpu::BufferUsages::COPY_SRC
| wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
})
}
pub fn create_uniform_buffer<T: bytemuck::Pod>(&self, label: &str, data: &T) -> wgpu::Buffer {
self.device
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some(label),
contents: bytemuck::bytes_of(data),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
})
}
pub async fn download_buffer(&self, buffer: &wgpu::Buffer, count: u32) -> Vec<u32> {
let size = count as u64 * 4;
let staging = self.device.create_buffer(&wgpu::BufferDescriptor {
label: Some("staging_readback"),
size,
usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
});
let mut encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("download_encoder"),
});
encoder.copy_buffer_to_buffer(buffer, 0, &staging, 0, size);
self.queue.submit(std::iter::once(encoder.finish()));
let slice = staging.slice(..);
let (tx, rx) = futures_channel::oneshot::channel();
slice.map_async(wgpu::MapMode::Read, move |result| {
tx.send(result).ok();
});
self.device.poll(wgpu::Maintain::Wait);
rx.await.unwrap().unwrap();
let data = slice.get_mapped_range();
let result: Vec<u32> = bytemuck::cast_slice(&data).to_vec();
drop(data);
staging.unmap();
result
}
pub fn upload_to_buffer(&self, buffer: &wgpu::Buffer, data: &[u32]) {
self.queue
.write_buffer(buffer, 0, bytemuck::cast_slice(data));
}
pub async fn download_single(&self, buffer: &wgpu::Buffer) -> u32 {
let result = self.download_buffer(buffer, 1).await;
result[0]
}
}