1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use crate::{async_device::AsyncDevice, WgpuFuture};
use std::ops::{Deref, DerefMut, RangeBounds};
use wgpu::{BufferAddress, BufferAsyncError};

/// A wrapper around a [`wgpu::Buffer`] which shadows some methods to allow for async
/// mapping using Rust's `async` API.
#[derive(Debug)]
pub struct AsyncBuffer
where
    Self: wgpu::WasmNotSend,
{
    pub(crate) device: AsyncDevice,
    pub(crate) buffer: wgpu::Buffer,
}

impl AsyncBuffer {
    /// Takes a slice of this buffer, in the same way a call to [`wgpu::Buffer::slice`] would,
    /// except wraps the result in an [`AsyncBufferSlice`] so that the `map_async` method can be
    /// awaited.
    pub fn slice<'a, S: RangeBounds<BufferAddress>>(&'a self, bounds: S) -> AsyncBufferSlice<'a> {
        let buffer_slice = self.buffer.slice(bounds);
        AsyncBufferSlice {
            device: self.device.clone(),
            buffer_slice,
        }
    }
}
impl Deref for AsyncBuffer {
    type Target = wgpu::Buffer;

    fn deref(&self) -> &Self::Target {
        &self.buffer
    }
}
impl DerefMut for AsyncBuffer {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.buffer
    }
}
impl<T> AsRef<T> for AsyncBuffer
where
    T: ?Sized,
    <AsyncBuffer as Deref>::Target: AsRef<T>,
{
    fn as_ref(&self) -> &T {
        self.deref().as_ref()
    }
}
impl<T> AsMut<T> for AsyncBuffer
where
    <AsyncBuffer as Deref>::Target: AsMut<T>,
{
    fn as_mut(&mut self) -> &mut T {
        self.deref_mut().as_mut()
    }
}

/// A smart-pointer wrapper around a [`wgpu::BufferSlice`], offering a `map_async` method than can be `await`ed.
#[derive(Debug)]
pub struct AsyncBufferSlice<'a>
where
    Self: wgpu::WasmNotSend,
{
    device: AsyncDevice,
    buffer_slice: wgpu::BufferSlice<'a>,
}
impl<'a> AsyncBufferSlice<'a> {
    /// An awaitable version of [`wgpu::Buffer::map_async`].
    pub fn map_async(&self, mode: wgpu::MapMode) -> WgpuFuture<Result<(), BufferAsyncError>> {
        self.device
            .do_async(|callback| self.buffer_slice.map_async(mode, callback))
    }
}
impl<'a> Deref for AsyncBufferSlice<'a> {
    type Target = wgpu::BufferSlice<'a>;

    fn deref(&self) -> &Self::Target {
        &self.buffer_slice
    }
}
impl<'a> DerefMut for AsyncBufferSlice<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.buffer_slice
    }
}
impl<'a, T> AsRef<T> for AsyncBufferSlice<'a>
where
    T: ?Sized,
    <AsyncBufferSlice<'a> as Deref>::Target: AsRef<T>,
{
    fn as_ref(&self) -> &T {
        self.deref().as_ref()
    }
}
impl<'a, T> AsMut<T> for AsyncBufferSlice<'a>
where
    <AsyncBufferSlice<'a> as Deref>::Target: AsMut<T>,
{
    fn as_mut(&mut self) -> &mut T {
        self.deref_mut().as_mut()
    }
}