mewgpu 3.7.3

Maybe Easier Wgpu (mew), a thin abstraction over wgpu's chaos
//! A struct that may be written to a vertex
//! [`wgpu::Buffer`](https://docs.rs/wgpu/latest/wgpu/struct.Buffer.html).
//!
//! See [`vertex_struct`] for details.
#[allow(unused_imports)]


use crate::vertexformat;

/// Define a vertex struct (to use in a **vertex** buffer).
///
/// Give each field a name and a standard vertex type from [`vertexformat`].
/// Also, you can optionally specify the
/// [`wgpu::VertexStepMode`](https://docs.rs/wgpu/latest/wgpu/enum.VertexStepMode.html),
/// or omit the `step ...` part to default to `Vertex`.
///
/// If you use index buffers you may need to offset all the shader locations by
/// a set value, if you have another active vertex buffer already taking some
/// up. After the step you may specify a shader `@location` offset with `+ N`,
/// or omit it for no change (`+ 0`).
///
/// Note that fields **must** be numbered correctly, starting from 0 (even when
/// the `@location` is offset). This is because I don't know how to teach macros
/// how to count and still be able to index tuples.  
/// Also, the fields are _not_ rearranged to be optimized to their alignment
/// rules, though they should be padded correctly for vertex structs.
///
/// ```
/// vertex_struct! { VertexStruct [
///     0 pos => Float32x3,  // @location(0)
///     1 uv => Float32x2,  // @location(1)
/// ] }
///
/// // Continue off from vertex, offset shader location by 2 elements
/// vertex_struct! { InstanceStruct step Instance + 2 [
///     0 int => Uint8,  // @location(2)
///     1 vec => Sint16x4,  // @location(3)
///     2 float => Float32,  // @location(4)
/// ] }
///
/// buffer! { VertexBuffer <VertexStruct> as VERTEX | COPY_DST }
///
/// // Big enough to store 10 VertexStructs, including padding if any
/// let buffer: VertexBuffer = context.new_buffer(10);
/// ```
///
/// When you create a shader struct on the Rust side, its memory layout should
/// match exactly as it is shader-side. You can write directly to each field
/// (though everything's in arrays) and then safely-ish transmute it to a byte
/// slice to write to the buffer.
///
/// ```
/// let single_struct: VertexStruct = (
///     [5_i32],
///     [0.0, 1.0, 2.0, 3.0],
///     [4.0],
/// ).into();
/// let mut lotsa_structs = [single_struct; 10];
/// *lotsa_structs[7].float = [5.0];
///
/// context.queue.write_buffer(
///     &buffer,
///     some_offset * size_of::<VertexStruct>() as u64,
///     lotsa_structs.as_byte_slice(),
/// );
/// ```
#[macro_export]
macro_rules! vertex_struct {
    { @step } => { $crate::wgpu::VertexStepMode::Vertex };
    { @step $attr:ident } => { $crate::wgpu::VertexStepMode::$attr };

    { $struct:ident $( step $step:ident )? $( + $location:literal )? [
        $( $num:tt $field:ident => $attr:ident ),* $(,)?
    ] } => {
        #[derive(Clone, Debug, PartialEq, PartialOrd)]
        #[repr(C, packed(2))]
        pub struct $struct {
            $( pub $field: $crate::vertexformat::$attr, )*
            _padding: [u8; Self::PADDING],
        }

        impl $struct {
            //pub const SUM_SIZE: usize = ::std::mem::size_of::<( $( $attr, )* )>();
            //pub const SUM_SIZE: usize = sum_size! { $( $attr )* };
            const SUM_SIZE: usize = {
                #[repr(C, packed(2))]
                struct SizeTest {
                    $( $field: $crate::vertexformat::$attr, )*
                }
                ::std::mem::size_of::<SizeTest>()
            };
            /// The total size of the struct, including padding for alignment.
            pub const BYTES: usize = Self::SUM_SIZE.next_multiple_of(4);
            /// The unused padding bytes necessary to bring the alignment up to a multiple of 4.
            /// Aim to minimize this by rearranging members.
            pub const PADDING: usize = Self::BYTES - Self::SUM_SIZE;
        }

        impl $crate::vertexstruct::MewVertexStruct for $struct {
            type Bytes = [u8; Self::BYTES];
            type Inners = ( $( <$crate::vertexformat::$attr as $crate::vertexformat::MewVertexFormat>::Inner , )* );
            /*
            type InnerRefs<'i> = ( $( &'i <$crate::vertexformat::$attr as $crate::vertexformat::MewVertexFormat>::Inner , )* );
            type InnerMuts<'i> = ( $( &'i mut <$crate::vertexformat::$attr as $crate::vertexformat::MewVertexFormat>::Inner , )* );
            */

            fn from_inners(inners: Self::Inners) -> Self {
                #[allow(unused_imports)]
                use $crate::vertexformat::MewVertexFormat;
                Self {
                    $( $field: $crate::vertexformat::$attr::from_inner(inners.$num), )*
                    _padding: [0; Self::PADDING],
                }
            }

            fn from_bytes(bytes: Self::Bytes) -> Self {
                unsafe { ::std::mem::transmute(bytes) }
            }

            fn zeroed() -> Self {
                unsafe {
                    Self {
                        $( $field: ::std::mem::zeroed(), )*
                        _padding: [0; Self::PADDING],
                    }
                }
            }

            // Probably not necessary...?
            /*
            fn get_refs(&self) -> Self::InnerRefs<'_> {
                unsafe {
                    ( $( &*&raw const self.$field, )* )
                }
            }

            fn get_muts(&mut self) -> Self::InnerMuts<'_> {
                unsafe {
                    ( $( &mut *&raw mut self.$field, )* )
                }
            }
            */

            fn vertex_layout() -> $crate::wgpu::VertexBufferLayout<'static> {
                static ATTRIBUTES: [$crate::wgpu::VertexAttribute; $crate::len! { $( $num )* }] = {
                    #[allow(unused_mut)]
                    let mut attrs = $crate::wgpu::vertex_attr_array![ $( $num => $attr , )* ];
                    $(
                        let mut i = 0;
                        while i < attrs.len() {
                            attrs[i].shader_location += $location;
                            i += 1;
                        }
                    )?
                    attrs
                };

                $crate::wgpu::VertexBufferLayout {
                    //array_stride: ::std::mem::size_of::<Self>() as u64,
                    array_stride: Self::BYTES as u64,
                    step_mode: $crate::vertex_struct! {@step $( $step )? },
                    attributes: &ATTRIBUTES,
                }
            }
        }


        impl From<[u8; Self::BYTES]> for $struct {
            fn from(bytes: [u8; Self::BYTES]) -> Self {
                use $crate::vertexstruct::MewVertexStruct;
                Self::from_bytes(bytes)
            }
        }

        impl From<( $( <$crate::vertexformat::$attr as $crate::vertexformat::MewVertexFormat>::Inner , )* )> for $struct {
            fn from(inners: ( $( <$crate::vertexformat::$attr as $crate::vertexformat::MewVertexFormat>::Inner , )* )) -> Self {
                use $crate::vertexstruct::MewVertexStruct;
                Self::from_inners(inners)
            }
        }

        impl AsRef<[u8; Self::BYTES]> for $struct {
            fn as_ref(&self) -> &[u8; Self::BYTES] {
                unsafe { &*::std::ptr::from_ref(self).cast() }
            }
        }
        impl AsMut<[u8; Self::BYTES]> for $struct {
            fn as_mut(&mut self) -> &mut [u8; Self::BYTES] {
                unsafe { &mut *::std::ptr::from_mut(self).cast() }
            }
        }

        // Why I manually did this, idk
        /*
        impl Clone for $struct {
            fn clone(&self) -> Self {
                unsafe {
                    Self {
                        $( $field: *&raw const self.$field, )*
                        _padding: [0; Self::PADDING],
                    }
                }
            }
        }
        */

        impl Default for $struct {
            fn default() -> Self {
                use $crate::vertexstruct::MewVertexStruct;
                Self::zeroed()
            }
        }
    }
}
pub use vertex_struct;


/// Trait for internal use to work with vertex structs.
pub trait MewVertexStruct {
    /// A byte array (`[u8; N]`) the same size as the struct.
    type Bytes;
    /// A tuple of all internal types.
    type Inners;
    /*
    type InnerRefs<'i> where Self: 'i;
    type InnerMuts<'i> where Self: 'i;
    */
    /// Build the struct using its internal types.
    fn from_inners(inners: Self::Inners) -> Self;
    /// Build the struct out of a byte array.
    fn from_bytes(bytes: Self::Bytes) -> Self;
    /// Build a struct with all fields zeroed.
    fn zeroed() -> Self;
    /*
    fn get_refs<'i>(&'i self) -> Self::InnerRefs<'i>;
    fn get_muts<'i>(&'i mut self) -> Self::InnerMuts<'i>;
    */
    /// Get this vertex struct's
    /// [`wgpu::VertexBufferLayout`](https://docs.rs/wgpu/latest/wgpu/struct.VertexBufferLayout.html).
    fn vertex_layout() -> crate::wgpu::VertexBufferLayout<'static>;
}


/// Convenience trait to convert vertex struct slices directly to byte slices.
///
/// Automatically implemented on `&[S]` where `S` is any vertex struct.
pub trait MewVertexStructByteSlice {
    /// Get a byte slice to write directly to a buffer.
    fn as_byte_slice(&self) -> &[u8];
}

impl<S: MewVertexStruct> MewVertexStructByteSlice for [S] {
    fn as_byte_slice(&self) -> &[u8] {
        unsafe {
            std::slice::from_raw_parts(
                //self as *const [S] as *const u8,
                (&raw const *self).cast(),
                //size_of::<S>() * self.len(),
                size_of_val(self),
            )
        }
    }
}