wgpu_async/
async_device.rs

1use crate::AsyncBuffer;
2use crate::WgpuFuture;
3use std::ops::Deref;
4use std::sync::Arc;
5use wgpu::util::{BufferInitDescriptor, DeviceExt};
6use wgpu::Device;
7
8/// A wrapper around a [`wgpu::Device`] which shadows some methods to allow for callback-and-poll
9/// methods to be made async.
10#[derive(Clone, Debug)]
11pub struct AsyncDevice {
12    // PollLoop must be dropped before device to ensure device is not dropped on poll thread
13    #[cfg(not(target_arch = "wasm32"))]
14    pub(crate) poll_loop: Arc<crate::wgpu_future::PollLoop>,
15
16    device: Arc<Device>,
17}
18
19impl AsyncDevice {
20    pub(crate) fn new(device: Arc<Device>) -> Self {
21        Self {
22            #[cfg(not(target_arch = "wasm32"))]
23            poll_loop: Arc::new(crate::wgpu_future::PollLoop::new(Arc::downgrade(&device))),
24            device,
25        }
26    }
27
28    /// Converts a callback-and-poll `wgpu` method pair into a future.
29    ///
30    /// The function given is called immediately, usually initiating work on the GPU immediately, however
31    /// the device is only polled once the future is awaited.
32    ///
33    /// # Example
34    ///
35    /// The `Buffer::map_async` method is made async using this method:
36    ///
37    /// ```
38    /// # let _ = stringify! {
39    /// let future = device.do_async(|callback|
40    ///     buffer_slice.map_async(mode, callback)
41    /// );
42    /// let result = future.await;
43    /// # };
44    /// ```
45    pub fn do_async<F, R>(&self, f: F) -> WgpuFuture<R>
46    where
47        F: FnOnce(Box<dyn FnOnce(R) + Send>),
48        R: Send + 'static,
49    {
50        let future = WgpuFuture::new(self.clone());
51        f(future.callback());
52        future
53    }
54
55    /// Creates an [`AsyncBuffer`].
56    pub fn create_buffer(&self, desc: &wgpu::BufferDescriptor) -> AsyncBuffer {
57        AsyncBuffer {
58            device: self.clone(),
59            buffer: self.device.create_buffer(desc),
60        }
61    }
62
63    /// Creates an [`AsyncBuffer`] with data to initialize it.
64    pub fn create_buffer_init(&self, desc: &BufferInitDescriptor) -> AsyncBuffer {
65        AsyncBuffer {
66            device: self.clone(),
67            buffer: self.device.create_buffer_init(desc),
68        }
69    }
70}
71impl Deref for AsyncDevice {
72    type Target = wgpu::Device;
73
74    fn deref(&self) -> &Self::Target {
75        &self.device
76    }
77}
78impl<T> AsRef<T> for AsyncDevice
79where
80    T: ?Sized,
81    <AsyncDevice as Deref>::Target: AsRef<T>,
82{
83    fn as_ref(&self) -> &T {
84        self.deref().as_ref()
85    }
86}