mewgpu 3.7.1-2

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


pub mod sample_type {
    //! Texture binding sample types. Enums exploded into `const`s because
    //! `Float` has a useless `filterable` property which is annoying to write out.

    use crate::wgpu;

    /// <code>[wgpu::TextureSampleType::Float](https://docs.rs/wgpu/latest/wgpu/enum.TextureSampleType.html#variant.Float) { filterable: true, ‌}</code>
    pub const FLOAT: wgpu::TextureSampleType = wgpu::TextureSampleType::Float { filterable: true, };
    /// <code>[wgpu::TextureSampleType::Float](https://docs.rs/wgpu/latest/wgpu/enum.TextureSampleType.html#variant.Float) { filterable: false, ‌}</code>
    pub const FLOAT_NON_FILTERABLE: wgpu::TextureSampleType = wgpu::TextureSampleType::Float { filterable: false, };
    /// [`wgpu::TextureSampleType::Depth`](https://docs.rs/wgpu/latest/wgpu/enum.TextureSampleType.html#variant.Depth)
    pub const DEPTH: wgpu::TextureSampleType = wgpu::TextureSampleType::Depth;
    /// [`wgpu::TextureSampleType::Sint`](https://docs.rs/wgpu/latest/wgpu/enum.TextureSampleType.html#variant.Sint)
    pub const SINT: wgpu::TextureSampleType = wgpu::TextureSampleType::Sint;
    /// [`wgpu::TextureSampleType::Uint`](https://docs.rs/wgpu/latest/wgpu/enum.TextureSampleType.html#variant.Uint)
    pub const UINT: wgpu::TextureSampleType = wgpu::TextureSampleType::Uint;
}


use crate::wgpu;


/// Define a type of texture - not its size or format, but a set of properties.
///
/// More specifically, its
/// [`wgpu::TextureUsages`](https://docs.rs/wgpu/latest/wgpu/struct.TextureUsages.html),
/// [`wgpu::TextureViewDimension`](https://docs.rs/wgpu/latest/wgpu/enum.TextureViewDimension.html),
/// & the binding's
/// [`wgpu::TextureSampleType`](https://docs.rs/wgpu/latest/wgpu/enum.TextureSampleType.html)
/// as simplified under [`sample_type`].  
/// The texture's size & format are defined on creation of the texture dynamically.
///
/// This struct also comes with a view of all layers, so you can bind to it
/// directly.
///
/// ```
/// // Default values
/// texture! { Texture {
///     usage: COPY_DST | TEXTURE_BINDING,
///     dimension: D2,
///     sample_type: FLOAT,
/// } }
///
/// let texture: Texture = context.new_texture((64, 64, 1), wgpu::TextureFormat::Rgba8Unorm);
/// ```
///
/// The texture is made with 1 mip level and sample count, this will probably
/// eventually be customizable but I haven't made anything complex enough yet to
/// figure out how that works.
#[macro_export]
macro_rules! texture {
    { $struct:ident { $($key:tt: $($vals:tt)|+),* $(,)? } } => {
        $crate::texture! { @collect $struct {
            usage: (COPY_DST | TEXTURE_BINDING),
            dimension: D2,
            sample_type: FLOAT,
        }; $({$key: $($vals)|+} )* }
    };

    { @collect $struct:ident {
            usage: $_:tt,
            dimension: $dimension:tt,
            sample_type: $sample:tt,
        }; {usage: $($usage:tt)|+} $($rest:tt)* } => {
            $crate::texture! { @collect $struct {
                usage: ($($usage)|+),
                dimension: $dimension,
                sample_type: $sample,
            }; $($rest)* }
    };
    { @collect $struct:ident {
            usage: $usage:tt,
            dimension: $_:tt,
            sample_type: $sample:tt,
        }; {dimension: $dimension:tt} $($rest:tt)* } => {
            $crate::texture! { @collect $struct {
                usage: $usage,
                dimension: $dimension,
                sample_type: $sample,
            }; $($rest)* }
    };
    { @collect $struct:ident {
            usage: $usage:tt,
            dimension: $dimension:tt,
            sample_type: $_:tt,
        }; {sample_type: $sample:tt} $($rest:tt)* } => {
            $crate::texture! { @collect $struct {
                usage: $usage,
                dimension: $dimension,
                sample_type: $sample,
            }; $($rest)* }
    };

    { @collect $struct:ident {
        usage: ($( $usage:ident )|+) ,
        dimension: $dimension:ident,
        sample_type: $sample:ident,
    }; } => {
        #[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
        pub struct $struct {
            pub texture: $crate::wgpu::Texture,
            pub view: $crate::wgpu::TextureView,
        }

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

        impl $crate::texture::MewTexture for $struct {
            fn new(texture: $crate::wgpu::Texture) -> Self {
                let view = texture.create_view(&$crate::wgpu::TextureViewDescriptor {
                    label: Some(concat!(stringify!($struct), " Texture View")),
                    format: Some(texture.format()),
                    dimension: Some($crate::wgpu::TextureViewDimension::$dimension),
                    usage: Some($( $crate::wgpu::TextureUsages::$usage )|+),
                    aspect: $crate::wgpu::TextureAspect::All,
                    base_mip_level: 0,
                    mip_level_count: None,
                    base_array_layer: 0,
                    array_layer_count: None,
                });
                Self {
                    texture,
                    view,
                }
            }

            fn binding_type() -> $crate::wgpu::BindingType {
                $crate::wgpu::BindingType::Texture {
                    sample_type: $crate::texture::sample_type::$sample,
                    view_dimension: $crate::wgpu::TextureViewDimension::$dimension,
                    multisampled: false,
                }
            }

            fn buffer_desc(inner_size: (u32, u32, u32), format: $crate::wgpu::TextureFormat) -> $crate::wgpu::TextureDescriptor<'static> {
                $crate::wgpu::TextureDescriptor {
                    label: Some(concat!(stringify!($struct), " Texture")),
                    size: $crate::wgpu::Extent3d {
                        width: inner_size.0,
                        height: inner_size.1,
                        depth_or_array_layers: inner_size.2,
                    },
                    mip_level_count: 1,
                    sample_count: 1,
                    dimension: $crate::wgpu::TextureViewDimension::$dimension.compatible_texture_dimension(),
                    format,
                    usage: $( $crate::wgpu::TextureUsages::$usage )|+,
                    view_formats: &[],
                }
            }

            fn as_binding(&self) -> $crate::wgpu::BindingResource<'_> {
                $crate::wgpu::BindingResource::TextureView(&self.view)
            }

            fn as_colour_attachment(&self, clear: Option<$crate::wgpu::Color>, depth_slice: Option<u32>) -> $crate::wgpu::RenderPassColorAttachment<'_> {
                $crate::wgpu::RenderPassColorAttachment {
                    view: &self.view,
                    depth_slice,
                    resolve_target: None,  // ???
                    ops: $crate::wgpu::Operations {
                        load: clear.map(|colour| $crate::wgpu::LoadOp::Clear(colour)).unwrap_or($crate::wgpu::LoadOp::Load),
                        store: $crate::wgpu::StoreOp::Store,
                    },
                }
            }

            fn as_depth_attachment(&self) -> $crate::wgpu::RenderPassDepthStencilAttachment<'_> {
                $crate::wgpu::RenderPassDepthStencilAttachment {
                    view: &self.view,
                    depth_ops: Some($crate::wgpu::Operations {
                        load: $crate::wgpu::LoadOp::Clear(1.0),
                        store: $crate::wgpu::StoreOp::Store,
                    }),
                    stencil_ops: None,
                }
            }

            fn memory_estimate(&self) -> u64 {
                self.texture.format().theoretical_memory_footprint($crate::wgpu::Extent3d {
                    width: self.texture.width(),
                    height: self.texture.height(),
                    depth_or_array_layers: self.texture.depth_or_array_layers(),
                })
            }

            fn texel_layout(&self) -> $crate::wgpu::TexelCopyBufferLayout {
                $crate::wgpu::TexelCopyBufferLayout {
                    offset: 0,
                    bytes_per_row: Some(self.texture.format().components() as u32 * self.texture.width()),
                    rows_per_image: Some(self.texture.height())
                }
            }
        }
    }
}
pub use texture;


/// Trait for internal use to work with texture bindings.
pub trait MewTexture {
    /// Build this texture type from a
    /// [`wgpu::Texture`](https://docs.rs/wgpu/latest/wgpu/struct.Texture.html).
    fn new(buffer: wgpu::Texture) -> Self;
    /// Get a [`wgpu::BindingType`](https://docs.rs/wgpu/latest/wgpu/enum.BindingType.html)
    /// to use for this type of texture.
    fn binding_type() -> wgpu::BindingType;
    /// Get a [`wgpu::TextureDescriptor`](https://docs.rs/wgpu/latest/wgpu/type.TextureDescriptor.html)
    /// to build this type of texture with the given size &
    /// [`wgpu::TextureFormat`](https://docs.rs/wgpu/latest/wgpu/enum.TextureFormat.html).
    fn buffer_desc(inner_size: (u32, u32, u32), format: wgpu::TextureFormat) -> wgpu::TextureDescriptor<'static>;
    /// Get this texture'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<'_>;
    /// Get a [`wgpu::RenderPassColorAttachment`](https://docs.rs/wgpu/latest/wgpu/struct.RenderPassColorAttachment.html)
    /// to attach this texture to a render pass, to draw to it using a specified clear
    /// colour on a 2D depth slice (set to `None` if it's a regular 2D texture).
    fn as_colour_attachment(&self, clear: Option<wgpu::Color>, depth_slice: Option<u32>) -> wgpu::RenderPassColorAttachment<'_>;
    /// Get a [`wgpu::RenderPassDepthStencilAttachment`](https://docs.rs/wgpu/latest/wgpu/struct.RenderPassDepthStencilAttachment.html)
    /// to attach this texture to a render pass, to use as a depth stencil.
    fn as_depth_attachment(&self) -> wgpu::RenderPassDepthStencilAttachment<'_>;
    /// Get the estimated size of this texture. Default implementation just uses
    /// [wgpu::TextureFormat::theoretical_memory_footprint](https://docs.rs/wgpu/latest/wgpu/enum.TextureFormat.html#method.theoretical_memory_footprint).
    fn memory_estimate(&self) -> u64;
    /// Get the [`wgpu::TexelCopyBufferLayout`](https://docs.rs/wgpu/latest/wgpu/struct.TexelCopyBufferLayout.html)
    /// for this texture. Required by the queue to write any data to the texture.
    fn texel_layout(&self) -> wgpu::TexelCopyBufferLayout;
}