mewgpu 3.7.1-1

Maybe Easier Wgpu (mew), a thin abstraction over wgpu's chaos
Documentation
//! Wrapper over a
//! [`wgpu::Buffer`](https://docs.rs/wgpu/latest/wgpu/struct.Buffer.html).
//!
//! See [`buffer`] for details.


use crate::wgpu;


/// Define a storage buffer, with an optional internal type/struct to align its
/// length with.
///
/// For example, if the buffer stores an array of `f32` matrices, you could set
/// the internal type to `[f32; 16]`, and the buffer descriptor will initialize
/// a multiple of the internal type's size. This doesn't validate the data
/// written in any way.  
/// If omitted, the internal type will default to `u8`, so you can initialize
/// the buffer using a number of bytes manually.
///
/// Not all buffers need to be used in bind groups, for example vertex/index
/// buffers. If you don't specify either `STORAGE` or `UNIFORM` as one of the
/// [`wgpu::BufferUsages`](https://docs.rs/wgpu/latest/wgpu/struct.BufferUsages.html),
/// you won't be able to put it in a bind group. Also note only one of those is
/// allowed at a time, can't have a uniform that's also a storage.
///
/// ```
/// buffer! { MatrixBuffer <SomeMatrixStructYouDefinedBefore> as VERTEX | COPY_DST }
///
/// let buffer: MatrixBuffer = render_context.new_buffer(16);
///
/// queue.write_buffer(&buffer, 0, &[1, 2, 3, ..]);
/// ```
#[macro_export]
macro_rules! buffer {
    { @searchbinding $struct:ident ; } => {};
    { @searchbinding $struct:ident ; $first:ident $( $rest:ident )* } => {
        $crate::buffer! { @trybinding $struct ; $first }
        $crate::buffer! { @searchbinding $struct ; $( $rest )* }
    };
    { @trybinding $struct:ident ; STORAGE } => {
        impl $crate::buffer::MewBufferBinding for $struct {
            fn binding_type() -> $crate::wgpu::BindingType {
                $crate::wgpu::BindingType::Buffer {
                    ty: $crate::wgpu::BufferBindingType::Storage { read_only: true, },
                    has_dynamic_offset: false,
                    min_binding_size: None,
                }
            }

            fn as_binding(&self) -> $crate::wgpu::BindingResource<'_> {
                self.buffer.as_entire_binding()
            }
        }
    };
    { @trybinding $struct:ident ; UNIFORM } => {
        impl $crate::buffer::MewBufferBinding for $struct {
            fn binding_type() -> $crate::wgpu::BindingType {
                $crate::wgpu::BindingType::Buffer {
                    ty: $crate::wgpu::BufferBindingType::Uniform,
                    has_dynamic_offset: false,
                    min_binding_size: None,
                }
            }

            fn as_binding<'a>(&'a self) -> $crate::wgpu::BindingResource<'a> {
                self.buffer.as_entire_binding()
            }
        }
    };
    { @trybinding $struct:ident ; $other:ident } => {};

    { $struct:ident as $($usage:ident)|+ } => {
        $crate::buffer! { $struct <u8> as $($usage)|+ }
    };
    { $struct:ident <$inner:ty> as $($usage:ident)|+ } => {
        #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
        pub struct $struct {
            buffer: $crate::wgpu::Buffer,
        }

        impl ::std::ops::Deref for $struct {
            type Target = $crate::wgpu::Buffer;
            fn deref(&self) -> &Self::Target {
                &self.buffer
            }
        }

        impl $crate::buffer::MewBuffer for $struct {
            type Inner = $inner;

            fn new(buffer: $crate::wgpu::Buffer) -> Self {
                Self {
                    buffer,
                }
            }

            fn buffer_desc(inner_size: u64) -> $crate::wgpu::BufferDescriptor<'static> {
                $crate::wgpu::BufferDescriptor {
                    label: Some(concat!(stringify!($struct), "<", stringify!($inner), "> Buffer")),
                    size: inner_size * ::std::mem::size_of::<Self::Inner>() as u64,
                    usage: $( $crate::wgpu::BufferUsages::$usage )|+,
                    mapped_at_creation: false,
                }
            }
        }

        $crate::buffer! { @searchbinding $struct ; $( $usage )+ }
    }
}
pub use buffer;


/// Trait for internal use to work with buffers.
pub trait MewBuffer {
    /// The "inner" type - what the buffer is supposed to hold. When creating buffers
    /// their capacity in bytes will be the input size times the size of this struct.
    type Inner;
    /// Build this buffer type from a
    /// [`wgpu::Buffer`](https://docs.rs/wgpu/latest/wgpu/struct.Buffer.html).
    fn new(buffer: wgpu::Buffer) -> Self;
    /// Get a [`wgpu::BufferDescriptor`](https://docs.rs/wgpu/latest/wgpu/type.BufferDescriptor.html)
    /// to build this type of buffer, with the capacity to fit some number of [`Self::Inner`]s.
    fn buffer_desc(inner_size: u64) -> wgpu::BufferDescriptor<'static>;
}

/// Trait for internal use to work specifically with buffers that can be put in
/// a bind group.
pub trait MewBufferBinding: MewBuffer {
    /// Get a [`wgpu::BindingType`](https://docs.rs/wgpu/latest/wgpu/enum.BindingType.html)
    /// to use for this type of buffer.
    fn binding_type() -> wgpu::BindingType;
    /// Get this buffer's [`wgpu::BindingResource`](https://docs.rs/wgpu/latest/wgpu/enum.BindingResource.html)
    /// to bind it in a bind group.
    fn as_binding(&self) -> wgpu::BindingResource<'_>;
}