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