1use std::{
2 marker::PhantomData,
3 ops::Deref,
4};
5
6
7#[macro_export]
24macro_rules! bind_group {
25 { @len } => {
26 0
27 };
28 { @len $last:tt } => {
29 $last + 1
30 };
31 { @len $first:tt $( $rest:tt )+ } => {
32 $crate::bind_group!{ @len $( $rest )+ }
33 };
34
35 { @bufferout $ty:ty } => {
36 $ty
37 };
38 { @bufferout $out:ty as $in:ty } => {
39 $out
40 };
41
42 { @bufferin $ty:ty } => {
43 $ty
44 };
45 { @bufferin $out:ty as $in:ty } => {
46 $in
47 };
48
49 { $struct:ident [
50 $( $num:tt $name:ident @ $( $shaderstage:ident )|+ => $buffer:ty $( as $bufferinner:ty )? ),* $(,)?
51 ] } => {
52 pub struct $struct {
53 bind_group: $crate::wgpu::BindGroup,
54 $( pub $name : $crate::bind_group!{ @bufferout $buffer $( as $bufferinner )? } , )*
55 }
56
57 impl ::std::ops::Deref for $struct {
58 type Target = $crate::wgpu::BindGroup;
59 fn deref(&self) -> &Self::Target {
60 &self.bind_group
61 }
62 }
63
64 impl $crate::MewBindGroup for $struct {
65 type BufferSet = ( $( $crate::bind_group!{ @bufferout $buffer $( as $bufferinner)? } , )* );
66 type BufferArray<T> = [T; $crate::bind_group!{ @len $( $num )* }];
67
68 fn new(bind_group: $crate::wgpu::BindGroup, buffers: Self::BufferSet) -> Self {
69 Self {
70 bind_group,
71 $( $name : buffers.$num , )*
72 }
73 }
74
75 fn layout_entries() -> &'static Self::BufferArray<$crate::wgpu::BindGroupLayoutEntry> {
76 use ::std::sync::LazyLock;
77
78 static ARRAY: LazyLock<<$struct as $crate::MewBindGroup>::BufferArray<$crate::wgpu::BindGroupLayoutEntry>> = LazyLock::new(|| [ $(
79 $crate::wgpu::BindGroupLayoutEntry {
80 binding: $num,
81 visibility: $( $crate::wgpu::ShaderStages::$shaderstage )|+,
82 ty: <$crate::bind_group!{ @bufferin $buffer $( as $bufferinner )? }>::binding_type(),
83 count: None,
84 },
85 )* ]);
86
87 &*ARRAY
88 }
89
90 fn layout_desc() -> $crate::wgpu::BindGroupLayoutDescriptor<'static> {
91 $crate::wgpu::BindGroupLayoutDescriptor {
92 label: Some(concat!(stringify!($struct), " Layout Descriptor")),
93 entries: Self::layout_entries(),
94 }
95 }
96
97 fn layout_desc_with(entries: &Self::BufferArray<$crate::wgpu::BindGroupLayoutEntry>) -> $crate::wgpu::BindGroupLayoutDescriptor {
98 $crate::wgpu::BindGroupLayoutDescriptor {
99 label: Some(concat!(stringify!($struct), " Layout Descriptor")),
100 entries,
101 }
102 }
103
104 fn bind_group_entries(buffers: &Self::BufferSet) -> Self::BufferArray<$crate::wgpu::BindGroupEntry> {
105 [ $(
106 $crate::wgpu::BindGroupEntry {
107 binding: $num,
108 resource: buffers.$num.as_binding(),
109 },
110 )* ]
111 }
112
113 fn bind_group_desc<'a>(layout: &'a $crate::MewBindGroupLayout<Self>, entries: &'a Self::BufferArray<$crate::wgpu::BindGroupEntry>) -> $crate::wgpu::BindGroupDescriptor<'a> {
114 $crate::wgpu::BindGroupDescriptor {
115 label: Some(stringify!($struct)),
116 layout,
117 entries,
118 }
119 }
120 }
121 };
122}
123
124
125pub trait MewBindGroup {
134 type BufferSet;
136 type BufferArray<T>;
137
138 fn new(bind_group: wgpu::BindGroup, buffers: Self::BufferSet) -> Self;
139 fn layout_entries() -> &'static Self::BufferArray<wgpu::BindGroupLayoutEntry>;
140 fn layout_desc_with<'a>(entries: &'a Self::BufferArray<wgpu::BindGroupLayoutEntry>) -> wgpu::BindGroupLayoutDescriptor<'a>;
141 fn layout_desc() -> wgpu::BindGroupLayoutDescriptor<'static>;
142 fn bind_group_entries(buffers: &Self::BufferSet) -> Self::BufferArray<wgpu::BindGroupEntry>;
143 fn bind_group_desc<'a>(layout: &'a MewBindGroupLayout<Self>, entries: &'a Self::BufferArray<wgpu::BindGroupEntry>) -> wgpu::BindGroupDescriptor<'a>;
144}
145
146
147pub struct MewBindGroupLayout<BIND: ?Sized> {
150 layout: wgpu::BindGroupLayout,
151 _marker: PhantomData<BIND>,
152}
153impl<BIND: ?Sized> Deref for MewBindGroupLayout<BIND> {
154 type Target = wgpu::BindGroupLayout;
155 fn deref(&self) -> &Self::Target {
156 &self.layout
157 }
158}
159impl<BIND> MewBindGroupLayout<BIND> {
160 pub fn new(layout: wgpu::BindGroupLayout) -> Self {
162 Self {
163 layout,
164 _marker: PhantomData,
165 }
166 }
167}