Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_render/src/render_resource/bind_group_entries.rs
6596 views
1
use variadics_please::all_tuples_with_size;
2
use wgpu::{BindGroupEntry, BindingResource};
3
4
use super::{Sampler, TextureView};
5
6
/// Helper for constructing bindgroups.
7
///
8
/// Allows constructing the descriptor's entries as:
9
/// ```ignore (render_device cannot be easily accessed)
10
/// render_device.create_bind_group(
11
/// "my_bind_group",
12
/// &my_layout,
13
/// &BindGroupEntries::with_indices((
14
/// (2, &my_sampler),
15
/// (3, my_uniform),
16
/// )),
17
/// );
18
/// ```
19
///
20
/// instead of
21
///
22
/// ```ignore (render_device cannot be easily accessed)
23
/// render_device.create_bind_group(
24
/// "my_bind_group",
25
/// &my_layout,
26
/// &[
27
/// BindGroupEntry {
28
/// binding: 2,
29
/// resource: BindingResource::Sampler(&my_sampler),
30
/// },
31
/// BindGroupEntry {
32
/// binding: 3,
33
/// resource: my_uniform,
34
/// },
35
/// ],
36
/// );
37
/// ```
38
///
39
/// or
40
///
41
/// ```ignore (render_device cannot be easily accessed)
42
/// render_device.create_bind_group(
43
/// "my_bind_group",
44
/// &my_layout,
45
/// &BindGroupEntries::sequential((
46
/// &my_sampler,
47
/// my_uniform,
48
/// )),
49
/// );
50
/// ```
51
///
52
/// instead of
53
///
54
/// ```ignore (render_device cannot be easily accessed)
55
/// render_device.create_bind_group(
56
/// "my_bind_group",
57
/// &my_layout,
58
/// &[
59
/// BindGroupEntry {
60
/// binding: 0,
61
/// resource: BindingResource::Sampler(&my_sampler),
62
/// },
63
/// BindGroupEntry {
64
/// binding: 1,
65
/// resource: my_uniform,
66
/// },
67
/// ],
68
/// );
69
/// ```
70
///
71
/// or
72
///
73
/// ```ignore (render_device cannot be easily accessed)
74
/// render_device.create_bind_group(
75
/// "my_bind_group",
76
/// &my_layout,
77
/// &BindGroupEntries::single(my_uniform),
78
/// );
79
/// ```
80
///
81
/// instead of
82
///
83
/// ```ignore (render_device cannot be easily accessed)
84
/// render_device.create_bind_group(
85
/// "my_bind_group",
86
/// &my_layout,
87
/// &[
88
/// BindGroupEntry {
89
/// binding: 0,
90
/// resource: my_uniform,
91
/// },
92
/// ],
93
/// );
94
/// ```
95
pub struct BindGroupEntries<'b, const N: usize = 1> {
96
entries: [BindGroupEntry<'b>; N],
97
}
98
99
impl<'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
122
impl<'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
131
impl<'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
139
pub trait IntoBinding<'a> {
140
fn into_binding(self) -> BindingResource<'a>;
141
}
142
143
impl<'a> IntoBinding<'a> for &'a TextureView {
144
#[inline]
145
fn into_binding(self) -> BindingResource<'a> {
146
BindingResource::TextureView(self)
147
}
148
}
149
150
impl<'a> IntoBinding<'a> for &'a wgpu::TextureView {
151
#[inline]
152
fn into_binding(self) -> BindingResource<'a> {
153
BindingResource::TextureView(self)
154
}
155
}
156
157
impl<'a> IntoBinding<'a> for &'a [&'a wgpu::TextureView] {
158
#[inline]
159
fn into_binding(self) -> BindingResource<'a> {
160
BindingResource::TextureViewArray(self)
161
}
162
}
163
164
impl<'a> IntoBinding<'a> for &'a Sampler {
165
#[inline]
166
fn into_binding(self) -> BindingResource<'a> {
167
BindingResource::Sampler(self)
168
}
169
}
170
171
impl<'a> IntoBinding<'a> for &'a [&'a wgpu::Sampler] {
172
#[inline]
173
fn into_binding(self) -> BindingResource<'a> {
174
BindingResource::SamplerArray(self)
175
}
176
}
177
178
impl<'a> IntoBinding<'a> for BindingResource<'a> {
179
#[inline]
180
fn into_binding(self) -> BindingResource<'a> {
181
self
182
}
183
}
184
185
impl<'a> IntoBinding<'a> for wgpu::BufferBinding<'a> {
186
#[inline]
187
fn into_binding(self) -> BindingResource<'a> {
188
BindingResource::Buffer(self)
189
}
190
}
191
192
impl<'a> IntoBinding<'a> for &'a [wgpu::BufferBinding<'a>] {
193
#[inline]
194
fn into_binding(self) -> BindingResource<'a> {
195
BindingResource::BufferArray(self)
196
}
197
}
198
199
pub trait IntoBindingArray<'b, const N: usize> {
200
fn into_array(self) -> [BindingResource<'b>; N];
201
}
202
203
macro_rules! impl_to_binding_slice {
204
($N: expr, $(#[$meta:meta])* $(($T: ident, $I: ident)),*) => {
205
$(#[$meta])*
206
impl<'b, $($T: IntoBinding<'b>),*> IntoBindingArray<'b, $N> for ($($T,)*) {
207
#[inline]
208
fn into_array(self) -> [BindingResource<'b>; $N] {
209
let ($($I,)*) = self;
210
[$($I.into_binding(), )*]
211
}
212
}
213
}
214
}
215
216
all_tuples_with_size!(
217
#[doc(fake_variadic)]
218
impl_to_binding_slice,
219
1,
220
32,
221
T,
222
s
223
);
224
225
pub trait IntoIndexedBindingArray<'b, const N: usize> {
226
fn into_array(self) -> [(u32, BindingResource<'b>); N];
227
}
228
229
macro_rules! impl_to_indexed_binding_slice {
230
($N: expr, $(($T: ident, $S: ident, $I: ident)),*) => {
231
impl<'b, $($T: IntoBinding<'b>),*> IntoIndexedBindingArray<'b, $N> for ($((u32, $T),)*) {
232
#[inline]
233
fn into_array(self) -> [(u32, BindingResource<'b>); $N] {
234
let ($(($S, $I),)*) = self;
235
[$(($S, $I.into_binding())), *]
236
}
237
}
238
}
239
}
240
241
all_tuples_with_size!(impl_to_indexed_binding_slice, 1, 32, T, n, s);
242
243
pub struct DynamicBindGroupEntries<'b> {
244
entries: Vec<BindGroupEntry<'b>>,
245
}
246
247
impl<'b> Default for DynamicBindGroupEntries<'b> {
248
fn default() -> Self {
249
Self::new()
250
}
251
}
252
253
impl<'b> DynamicBindGroupEntries<'b> {
254
pub fn sequential<const N: usize>(entries: impl IntoBindingArray<'b, N>) -> Self {
255
Self {
256
entries: entries
257
.into_array()
258
.into_iter()
259
.enumerate()
260
.map(|(ix, resource)| BindGroupEntry {
261
binding: ix as u32,
262
resource,
263
})
264
.collect(),
265
}
266
}
267
268
pub fn extend_sequential<const N: usize>(
269
mut self,
270
entries: impl IntoBindingArray<'b, N>,
271
) -> Self {
272
let start = self.entries.last().unwrap().binding + 1;
273
self.entries.extend(
274
entries
275
.into_array()
276
.into_iter()
277
.enumerate()
278
.map(|(ix, resource)| BindGroupEntry {
279
binding: start + ix as u32,
280
resource,
281
}),
282
);
283
self
284
}
285
286
pub fn new_with_indices<const N: usize>(entries: impl IntoIndexedBindingArray<'b, N>) -> Self {
287
Self {
288
entries: entries
289
.into_array()
290
.into_iter()
291
.map(|(binding, resource)| BindGroupEntry { binding, resource })
292
.collect(),
293
}
294
}
295
296
pub fn new() -> Self {
297
Self {
298
entries: Vec::new(),
299
}
300
}
301
302
pub fn extend_with_indices<const N: usize>(
303
mut self,
304
entries: impl IntoIndexedBindingArray<'b, N>,
305
) -> Self {
306
self.entries.extend(
307
entries
308
.into_array()
309
.into_iter()
310
.map(|(binding, resource)| BindGroupEntry { binding, resource }),
311
);
312
self
313
}
314
}
315
316
impl<'b> core::ops::Deref for DynamicBindGroupEntries<'b> {
317
type Target = [BindGroupEntry<'b>];
318
319
fn deref(&self) -> &[BindGroupEntry<'b>] {
320
&self.entries
321
}
322
}
323
324