# WGPU-Async
[![crates.io](https://img.shields.io/crates/v/wgpu-async.svg)](https://crates.io/crates/wgpu-async)
[![docs.rs](https://img.shields.io/docsrs/wgpu-async)](https://docs.rs/wgpu-async/latest/wgpu_async/)
[![crates.io](https://img.shields.io/crates/l/wgpu-async.svg)](https://github.com/LucentFlux/wgpu-async/blob/main/LICENSE)
This crate adds a global poll loop thread on non-WASM platforms that can be used to create a `WgpuFuture` holding the completion of a task. The poll loop is conservative, parking itself when no futures are waiting on it, meaning that this crate adds as little overhead as possible in changing paradigms.
Note that this crate does not aim to improve the performance of anything, and fast applications should reduce CPU-GPU communication and synchronisation as much as possible, irrespective of the paradigm used and platform targetted. In fact, when used incorrectly, this crate can drastically decrease performance, as shown under the [Common Pitfall](#Common-Pitfall) section. This crate is intended for use when prototyping or testing, when parity between native and web targets is more important than speed.
## Motivation
[WGPU](https://github.com/gfx-rs/wgpu) offers some `async` methods when initialising adapters and devices, but during program execution much of the timing between the CPU and GPU is managed through callbacks and polling. A common pattern is to do something like the following:
```rust ignore
wgpu.do_something();
```rust ignore
wgpu.do_something().then(|result| { /* Handle results */ }).await;
```
Also, on Web targets we find that the call to `poll` is entirely unnecessary, increasing conceptual complexity in programs which target both Native and Web. This crate unifies the two under a common `async/await` API.
## Common Pitfall
Due to the polling thread running both intermittently and globaly, independently from other parts of your code, it is possible that using this library may mask errors when performing operations that must be awaited. For example, the following code *should* deadlock:
```rust compile_fail
// BAD CODE - DON'T DO THIS
let (sender, receiver) = flume::bounded(1);
```rust ignore
queue.submit(&[/* commands */]).await; // An awaitable `Queue::submit`!
```
Just like their base `wgpu` counterparts, these methods begin their work on the GPU immediately. However the device won't begin to be polled until the future is awaited.
You can also convert any non-shadowed callback-and-poll method to an async one using `AsyncDevice::do_async`:
```rust ignore
wgpu.do_something();
let future = device.do_async(move |callback| {
wgpu.on_something_done(|result| callback(result));
});
let result = future.await;
```