use std::{
marker::PhantomData,
ops::Deref,
};
use crate::wgpu;
#[macro_export]
macro_rules! bind_group {
{ $struct:ident [
$( $num:tt $name:ident @ $( $shaderstage:ident )|+ => $buffer:ty /* $( as $bufferinner:ty )? */ ),* $(,)?
] } => {
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct $struct {
bind_group: $crate::wgpu::BindGroup,
$( pub $name : $buffer , )*
}
impl ::std::ops::Deref for $struct {
type Target = $crate::wgpu::BindGroup;
fn deref(&self) -> &Self::Target {
&self.bind_group
}
}
impl $crate::bindgroup::MewBindGroup for $struct {
type BufferSet = ( $( $buffer , )* );
type BufferArray<T> = [T; $crate::len! { $( $num )* }];
fn new(bind_group: $crate::wgpu::BindGroup, buffers: Self::BufferSet) -> Self {
Self {
bind_group,
$( $name : buffers.$num , )*
}
}
fn layout_entries() -> &'static Self::BufferArray<$crate::wgpu::BindGroupLayoutEntry> {
use ::std::sync::LazyLock;
#[allow(unused_imports)]
use $crate::{
buffer::{ MewBuffer, MewBufferBinding, },
sampler::MewSampler,
texture::MewTexture,
};
static ARRAY: LazyLock<<$struct as $crate::bindgroup::MewBindGroup>::BufferArray<$crate::wgpu::BindGroupLayoutEntry>> = LazyLock::new(|| [ $(
$crate::wgpu::BindGroupLayoutEntry {
binding: $num,
visibility: $( $crate::wgpu::ShaderStages::$shaderstage )|+,
ty: <$buffer>::binding_type(),
count: None,
},
)* ]);
&*ARRAY
}
fn layout_desc() -> $crate::wgpu::BindGroupLayoutDescriptor<'static> {
$crate::wgpu::BindGroupLayoutDescriptor {
label: Some(concat!(stringify!($struct), " Layout Descriptor")),
entries: Self::layout_entries(),
}
}
fn bind_group_entries(buffers: &Self::BufferSet) -> Self::BufferArray<$crate::wgpu::BindGroupEntry<'_>> {
#[allow(unused_imports)]
use $crate::{
buffer::{ MewBuffer, MewBufferBinding, },
sampler::MewSampler,
texture::MewTexture,
};
[ $(
$crate::wgpu::BindGroupEntry {
binding: $num,
resource: buffers.$num.as_binding(),
},
)* ]
}
fn bind_group_desc<'a>(layout: &'a $crate::bindgroup::MewBindGroupLayout<Self>, entries: &'a Self::BufferArray<$crate::wgpu::BindGroupEntry>) -> $crate::wgpu::BindGroupDescriptor<'a> {
$crate::wgpu::BindGroupDescriptor {
label: Some(stringify!($struct)),
layout,
entries,
}
}
}
};
}
pub use bind_group;
pub trait MewBindGroup {
type BufferSet;
type BufferArray<T>;
fn new(bind_group: wgpu::BindGroup, buffers: Self::BufferSet) -> Self;
fn layout_entries() -> &'static Self::BufferArray<wgpu::BindGroupLayoutEntry>;
fn layout_desc() -> wgpu::BindGroupLayoutDescriptor<'static>;
fn bind_group_entries(buffers: &Self::BufferSet) -> Self::BufferArray<wgpu::BindGroupEntry<'_>>;
fn bind_group_desc<'a>(layout: &'a MewBindGroupLayout<Self>, entries: &'a Self::BufferArray<wgpu::BindGroupEntry<'_>>) -> wgpu::BindGroupDescriptor<'a>;
}
pub struct MewBindGroupLayout<BIND: ?Sized> {
layout: wgpu::BindGroupLayout,
_marker: PhantomData<BIND>,
}
impl<BIND: ?Sized> Deref for MewBindGroupLayout<BIND> {
type Target = wgpu::BindGroupLayout;
fn deref(&self) -> &Self::Target {
&self.layout
}
}
impl<BIND> MewBindGroupLayout<BIND> {
pub fn new(layout: wgpu::BindGroupLayout) -> Self {
Self {
layout,
_marker: PhantomData,
}
}
}