1use std::{
2 marker::PhantomData,
3 ops::Deref,
4};
5
6
7#[macro_export]
27macro_rules! bind_group {
28 { @bufferout $ty:ty } => {
29 $ty
30 };
31 { @bufferout $out:ty as $in:ty } => {
32 $out
33 };
34
35 { @bufferin $ty:ty } => {
36 $ty
37 };
38 { @bufferin $out:ty as $in:ty } => {
39 $in
40 };
41
42 { $struct:ident [
43 $( $num:tt $name:ident @ $( $shaderstage:ident )|+ => $buffer:ty $( as $bufferinner:ty )? ),* $(,)?
44 ] } => {
45 pub struct $struct {
46 bind_group: $crate::wgpu::BindGroup,
47 $( pub $name : $crate::bind_group! { @bufferout $buffer $( as $bufferinner )? } , )*
48 }
49
50 impl ::std::ops::Deref for $struct {
51 type Target = $crate::wgpu::BindGroup;
52 fn deref(&self) -> &Self::Target {
53 &self.bind_group
54 }
55 }
56
57 impl $crate::bindgroup::MewBindGroup for $struct {
58 type BufferSet = ( $( $crate::bind_group! { @bufferout $buffer $( as $bufferinner)? } , )* );
59 type BufferArray<T> = [T; $crate::len! { $( $num )* }];
60
61 fn new(bind_group: $crate::wgpu::BindGroup, buffers: Self::BufferSet) -> Self {
62 Self {
63 bind_group,
64 $( $name : buffers.$num , )*
65 }
66 }
67
68 fn layout_entries() -> &'static Self::BufferArray<$crate::wgpu::BindGroupLayoutEntry> {
69 use ::std::sync::LazyLock;
70 #[allow(unused_imports)]
71 use $crate::{
72 buffer::MewBuffer,
73 sampler::MewSampler,
74 texture::MewTexture,
75 };
76
77 static ARRAY: LazyLock<<$struct as $crate::bindgroup::MewBindGroup>::BufferArray<$crate::wgpu::BindGroupLayoutEntry>> = LazyLock::new(|| [ $(
78 $crate::wgpu::BindGroupLayoutEntry {
79 binding: $num,
80 visibility: $( $crate::wgpu::ShaderStages::$shaderstage )|+,
81 ty: <$crate::bind_group! { @bufferin $buffer $( as $bufferinner )? }>::binding_type(),
82 count: None,
83 },
84 )* ]);
85
86 &*ARRAY
87 }
88
89 fn layout_desc() -> $crate::wgpu::BindGroupLayoutDescriptor<'static> {
90 $crate::wgpu::BindGroupLayoutDescriptor {
91 label: Some(concat!(stringify!($struct), " Layout Descriptor")),
92 entries: Self::layout_entries(),
93 }
94 }
95
96 fn layout_desc_with(entries: &Self::BufferArray<$crate::wgpu::BindGroupLayoutEntry>) -> $crate::wgpu::BindGroupLayoutDescriptor {
97 $crate::wgpu::BindGroupLayoutDescriptor {
98 label: Some(concat!(stringify!($struct), " Layout Descriptor")),
99 entries,
100 }
101 }
102
103 fn bind_group_entries(buffers: &Self::BufferSet) -> Self::BufferArray<$crate::wgpu::BindGroupEntry> {
104 #[allow(unused_imports)]
105 use $crate::{
106 buffer::MewBuffer,
107 sampler::MewSampler,
108 texture::MewTexture,
109 };
110
111 [ $(
112 $crate::wgpu::BindGroupEntry {
113 binding: $num,
114 resource: buffers.$num.as_binding(),
115 },
116 )* ]
117 }
118
119 fn bind_group_desc<'a>(layout: &'a $crate::bindgroup::MewBindGroupLayout<Self>, entries: &'a Self::BufferArray<$crate::wgpu::BindGroupEntry>) -> $crate::wgpu::BindGroupDescriptor<'a> {
120 $crate::wgpu::BindGroupDescriptor {
121 label: Some(stringify!($struct)),
122 layout,
123 entries,
124 }
125 }
126 }
127 };
128}
129pub use bind_group;
130
131
132pub trait MewBindGroup {
141 type BufferSet;
143 type BufferArray<T>;
145
146 fn new(bind_group: wgpu::BindGroup, buffers: Self::BufferSet) -> Self;
148 fn layout_entries() -> &'static Self::BufferArray<wgpu::BindGroupLayoutEntry>;
151 fn layout_desc() -> wgpu::BindGroupLayoutDescriptor<'static>;
154 fn layout_desc_with<'a>(entries: &'a Self::BufferArray<wgpu::BindGroupLayoutEntry>) -> wgpu::BindGroupLayoutDescriptor<'a>;
158 fn bind_group_entries(buffers: &Self::BufferSet) -> Self::BufferArray<wgpu::BindGroupEntry>;
161 fn bind_group_desc<'a>(layout: &'a MewBindGroupLayout<Self>, entries: &'a Self::BufferArray<wgpu::BindGroupEntry>) -> wgpu::BindGroupDescriptor<'a>;
164
165 }
167
168pub struct MewBindGroupLayout<BIND: ?Sized> {
179 layout: wgpu::BindGroupLayout,
180 _marker: PhantomData<BIND>,
181}
182impl<BIND: ?Sized> Deref for MewBindGroupLayout<BIND> {
183 type Target = wgpu::BindGroupLayout;
184 fn deref(&self) -> &Self::Target {
185 &self.layout
186 }
187}
188impl<BIND> MewBindGroupLayout<BIND> {
189 pub fn new(layout: wgpu::BindGroupLayout) -> Self {
191 Self {
192 layout,
193 _marker: PhantomData,
194 }
195 }
196}