mew/
buffer.rs

1/// Define a storage buffer, with an optional internal type/struct to align its
2/// length with.
3///
4/// For example, if the buffer stores an array of `f32` matrices, you could set
5/// the internal type to `[f32; 16]`, and the buffer descriptor will initialize
6/// a multiple of the internal type's size.  
7/// If omitted, the internal type will default to `u8`, so you can initialize
8/// the buffer using a number of bytes manually.
9///
10/// You also need to specify the
11/// [`wgpu::BufferUsages`](https://docs.rs/wgpu/latest/wgpu/struct.BufferUsages.html),
12/// but note that it requires either `STORAGE` or `UNIFORM` as the *first* usage.
13///
14/// ```
15/// buffer! { MatrixBuffer <SomeMatrixStructYouDefinedBefore> as UNIFORM | COPY_DST }
16///
17/// let buffer: MatrixBuffer = render_context.new_buffer(1);
18///
19/// queue.write_buffer(&buffer, 0, &[1, 2, 3, ..]);
20/// ```
21#[macro_export]
22macro_rules! buffer {
23    { @buffertype STORAGE } => {
24        $crate::wgpu::BufferBindingType::Storage { read_only: true, }
25    };
26    { @buffertype UNIFORM } => {
27        $crate::wgpu::BufferBindingType::Uniform
28    };
29
30    { $struct:ident as $( $usage:ident )|+ } => {
31        $crate::buffer! { $struct <u8> as $( $usage )|+ }
32    };
33    { $struct:ident < $inner:ty > as $storageuniform:ident $( | $usage:ident )* } => {
34        #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
35        pub struct $struct {
36            buffer: $crate::wgpu::Buffer,
37        }
38
39        impl ::std::ops::Deref for $struct {
40            type Target = $crate::wgpu::Buffer;
41            fn deref(&self) -> &Self::Target {
42                &self.buffer
43            }
44        }
45
46        impl $crate::buffer::MewBuffer for $struct {
47            fn new(buffer: $crate::wgpu::Buffer) -> Self {
48                Self {
49                    buffer,
50                }
51            }
52
53            fn binding_type() -> $crate::wgpu::BindingType {
54                $crate::wgpu::BindingType::Buffer {
55                    ty: $crate::buffer! { @buffertype $storageuniform },
56                    has_dynamic_offset: false,
57                    min_binding_size: None,
58                }
59            }
60
61            fn buffer_desc(inner_size: u64) -> $crate::wgpu::BufferDescriptor<'static> {
62                $crate::wgpu::BufferDescriptor {
63                    label: Some(concat!(stringify!($struct), "<", stringify!($inner), "> Buffer")),
64                    size: inner_size * ::std::mem::size_of::<$inner>() as u64,
65                    usage: $crate::wgpu::BufferUsages::$storageuniform $( | $crate::wgpu::BufferUsages::$usage )*,
66                    mapped_at_creation: false,
67                }
68            }
69
70            fn as_binding<'a>(&'a self) -> $crate::wgpu::BindingResource<'a> {
71                self.buffer.as_entire_binding()
72            }
73        }
74    }
75}
76pub use buffer;
77
78
79/// Trait for buffer wrapper types, to get layouts and descriptors about the
80/// inner buffer.
81pub trait MewBuffer {
82    /// Wrap a buffer.
83    fn new(buffer: wgpu::Buffer) -> Self;
84    /// Get the `BindingType` for the buffer.
85    fn binding_type() -> wgpu::BindingType;
86    /// Get the 'BufferDescriptor' for the buffer, with some count of its internal
87    /// type as the size.
88    fn buffer_desc(inner_size: u64) -> wgpu::BufferDescriptor<'static>;
89    fn as_binding<'a>(&'a self) -> wgpu::BindingResource<'a>;
90}