Rewrite GpuFuture to avoid blocking and to use less space

Remove odd patching matching

Replace std::sync::Mutex with spin::Mutex in GpuFuture

Reduce GpuFuture usage to one explicit allocation instead of two

Fix examples to poll the device in the background when using map_read or map_write

Remove device.poll from GpuFuture::poll and document future invariants

Massively simplify examples

Use Arc::clone(...) instead of arc.clone()

Switch println to log::info
This commit is contained in:
Lachlan Sneff
2020-03-23 10:12:53 -04:00
parent 5f24202f7e
commit ea6bcd03e2
5 changed files with 138 additions and 87 deletions

View File

@@ -5,8 +5,6 @@ use std::fs::File;
use std::mem::size_of;
async fn run() {
env_logger::init();
let adapter = wgpu::Adapter::request(
&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::Default,
@@ -87,8 +85,16 @@ async fn run() {
queue.submit(&[command_buffer]);
// Note that we're not calling `.await` here.
let buffer_future = output_buffer.map_read(0, (size * size) as u64 * size_of::<u32>() as u64);
// Poll the device in a blocking manner so that our future resolves.
// In an actual application, `device.poll(...)` should
// be called in an event loop or on another thread.
device.poll(wgpu::Maintain::Wait);
// Write the buffer as a PNG
if let Ok(mapping) = output_buffer.map_read(0u64, (size * size) as u64 * size_of::<u32>() as u64).await {
if let Ok(mapping) = buffer_future.await {
let mut png_encoder = png::Encoder::new(File::create("red.png").unwrap(), size, size);
png_encoder.set_depth(png::BitDepth::Eight);
png_encoder.set_color(png::ColorType::RGBA);
@@ -98,11 +104,10 @@ async fn run() {
.write_image_data(mapping.as_slice())
.unwrap();
}
// The device will be polled when it is dropped but we can also poll it explicitly
device.poll(true);
}
fn main() {
env_logger::init();
futures::executor::block_on(run());
}

View File

@@ -13,6 +13,7 @@ async fn run() {
.collect()
};
// To see the output, run `RUST_LOG=info cargo run --example hello-compute`.
log::info!("Times: {:?}", execute_gpu(numbers).await);
}
@@ -98,7 +99,16 @@ async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
encoder.copy_buffer_to_buffer(&storage_buffer, 0, &staging_buffer, 0, size);
queue.submit(&[encoder.finish()]);
if let Ok(mapping) = staging_buffer.map_read(0u64, size).await {
// Note that we're not calling `.await` here.
let buffer_future = staging_buffer.map_read(0, size);
// Poll the device in a blocking manner so that our future resolves.
// In an actual application, `device.poll(...)` should
// be called in an event loop or on another thread.
device.poll(wgpu::Maintain::Wait);
if let Ok(mapping) = buffer_future.await {
mapping
.as_slice()
.chunks_exact(4)
@@ -111,6 +121,7 @@ async fn execute_gpu(numbers: Vec<u32>) -> Vec<u32> {
fn main() {
env_logger::init();
futures::executor::block_on(run());
}