bevy_render/render_resource/
bind_group_entries.rs1use bevy_utils::all_tuples_with_size;
2use wgpu::{BindGroupEntry, BindingResource};
3
4use super::{Sampler, TextureView};
5
6pub struct BindGroupEntries<'b, const N: usize = 1> {
96 entries: [BindGroupEntry<'b>; N],
97}
98
99impl<'b, const N: usize> BindGroupEntries<'b, N> {
100 #[inline]
101 pub fn sequential(resources: impl IntoBindingArray<'b, N>) -> Self {
102 let mut i = 0;
103 Self {
104 entries: resources.into_array().map(|resource| {
105 let binding = i;
106 i += 1;
107 BindGroupEntry { binding, resource }
108 }),
109 }
110 }
111
112 #[inline]
113 pub fn with_indices(indexed_resources: impl IntoIndexedBindingArray<'b, N>) -> Self {
114 Self {
115 entries: indexed_resources
116 .into_array()
117 .map(|(binding, resource)| BindGroupEntry { binding, resource }),
118 }
119 }
120}
121
122impl<'b> BindGroupEntries<'b, 1> {
123 pub fn single(resource: impl IntoBinding<'b>) -> [BindGroupEntry<'b>; 1] {
124 [BindGroupEntry {
125 binding: 0,
126 resource: resource.into_binding(),
127 }]
128 }
129}
130
131impl<'b, const N: usize> core::ops::Deref for BindGroupEntries<'b, N> {
132 type Target = [BindGroupEntry<'b>];
133
134 fn deref(&self) -> &[BindGroupEntry<'b>] {
135 &self.entries
136 }
137}
138
139pub trait IntoBinding<'a> {
140 fn into_binding(self) -> BindingResource<'a>;
141}
142
143impl<'a> IntoBinding<'a> for &'a TextureView {
144 #[inline]
145 fn into_binding(self) -> BindingResource<'a> {
146 BindingResource::TextureView(self)
147 }
148}
149
150impl<'a> IntoBinding<'a> for &'a [&'a wgpu::TextureView] {
151 #[inline]
152 fn into_binding(self) -> BindingResource<'a> {
153 BindingResource::TextureViewArray(self)
154 }
155}
156
157impl<'a> IntoBinding<'a> for &'a Sampler {
158 #[inline]
159 fn into_binding(self) -> BindingResource<'a> {
160 BindingResource::Sampler(self)
161 }
162}
163
164impl<'a> IntoBinding<'a> for BindingResource<'a> {
165 #[inline]
166 fn into_binding(self) -> BindingResource<'a> {
167 self
168 }
169}
170
171impl<'a> IntoBinding<'a> for wgpu::BufferBinding<'a> {
172 #[inline]
173 fn into_binding(self) -> BindingResource<'a> {
174 BindingResource::Buffer(self)
175 }
176}
177
178pub trait IntoBindingArray<'b, const N: usize> {
179 fn into_array(self) -> [BindingResource<'b>; N];
180}
181
182macro_rules! impl_to_binding_slice {
183 ($N: expr, $(#[$meta:meta])* $(($T: ident, $I: ident)),*) => {
184 $(#[$meta])*
185 impl<'b, $($T: IntoBinding<'b>),*> IntoBindingArray<'b, $N> for ($($T,)*) {
186 #[inline]
187 fn into_array(self) -> [BindingResource<'b>; $N] {
188 let ($($I,)*) = self;
189 [$($I.into_binding(), )*]
190 }
191 }
192 }
193}
194
195all_tuples_with_size!(
196 #[doc(fake_variadic)]
197 impl_to_binding_slice,
198 1,
199 32,
200 T,
201 s
202);
203
204pub trait IntoIndexedBindingArray<'b, const N: usize> {
205 fn into_array(self) -> [(u32, BindingResource<'b>); N];
206}
207
208macro_rules! impl_to_indexed_binding_slice {
209 ($N: expr, $(($T: ident, $S: ident, $I: ident)),*) => {
210 impl<'b, $($T: IntoBinding<'b>),*> IntoIndexedBindingArray<'b, $N> for ($((u32, $T),)*) {
211 #[inline]
212 fn into_array(self) -> [(u32, BindingResource<'b>); $N] {
213 let ($(($S, $I),)*) = self;
214 [$(($S, $I.into_binding())), *]
215 }
216 }
217 }
218}
219
220all_tuples_with_size!(impl_to_indexed_binding_slice, 1, 32, T, n, s);
221
222pub struct DynamicBindGroupEntries<'b> {
223 entries: Vec<BindGroupEntry<'b>>,
224}
225
226impl<'b> DynamicBindGroupEntries<'b> {
227 pub fn sequential<const N: usize>(entries: impl IntoBindingArray<'b, N>) -> Self {
228 Self {
229 entries: entries
230 .into_array()
231 .into_iter()
232 .enumerate()
233 .map(|(ix, resource)| BindGroupEntry {
234 binding: ix as u32,
235 resource,
236 })
237 .collect(),
238 }
239 }
240
241 pub fn extend_sequential<const N: usize>(
242 mut self,
243 entries: impl IntoBindingArray<'b, N>,
244 ) -> Self {
245 let start = self.entries.last().unwrap().binding + 1;
246 self.entries.extend(
247 entries
248 .into_array()
249 .into_iter()
250 .enumerate()
251 .map(|(ix, resource)| BindGroupEntry {
252 binding: start + ix as u32,
253 resource,
254 }),
255 );
256 self
257 }
258
259 pub fn new_with_indices<const N: usize>(entries: impl IntoIndexedBindingArray<'b, N>) -> Self {
260 Self {
261 entries: entries
262 .into_array()
263 .into_iter()
264 .map(|(binding, resource)| BindGroupEntry { binding, resource })
265 .collect(),
266 }
267 }
268
269 pub fn extend_with_indices<const N: usize>(
270 mut self,
271 entries: impl IntoIndexedBindingArray<'b, N>,
272 ) -> Self {
273 self.entries.extend(
274 entries
275 .into_array()
276 .into_iter()
277 .map(|(binding, resource)| BindGroupEntry { binding, resource }),
278 );
279 self
280 }
281}
282
283impl<'b> core::ops::Deref for DynamicBindGroupEntries<'b> {
284 type Target = [BindGroupEntry<'b>];
285
286 fn deref(&self) -> &[BindGroupEntry<'b>] {
287 &self.entries
288 }
289}