1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use super::{BufferId, RenderResourceBinding, SamplerId, TextureId};
use std::{
collections::hash_map::DefaultHasher,
hash::{Hash, Hasher},
ops::Range,
sync::Arc,
};
#[derive(Hash, Eq, PartialEq, Debug, Copy, Clone)]
pub struct BindGroupId(pub u64);
#[derive(Eq, PartialEq, Debug)]
pub struct IndexedBinding {
pub index: u32,
pub binding: RenderResourceBinding,
}
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct BindGroup {
pub id: BindGroupId,
pub indexed_bindings: Arc<Vec<IndexedBinding>>,
pub dynamic_uniform_indices: Option<Arc<Vec<u32>>>,
}
impl BindGroup {
pub fn build() -> BindGroupBuilder {
BindGroupBuilder::default()
}
}
#[derive(Default)]
pub struct BindGroupBuilder {
pub indexed_bindings: Vec<IndexedBinding>,
pub dynamic_uniform_indices: Vec<u32>,
pub hasher: DefaultHasher,
}
impl BindGroupBuilder {
pub fn add_binding(mut self, index: u32, binding: RenderResourceBinding) -> Self {
if let RenderResourceBinding::Buffer {
dynamic_index: Some(dynamic_index),
..
} = binding
{
self.dynamic_uniform_indices.push(dynamic_index);
}
binding.hash(&mut self.hasher);
self.indexed_bindings
.push(IndexedBinding { index, binding });
self
}
pub fn add_texture(self, index: u32, texture: TextureId) -> Self {
self.add_binding(index, RenderResourceBinding::Texture(texture))
}
pub fn add_sampler(self, index: u32, sampler: SamplerId) -> Self {
self.add_binding(index, RenderResourceBinding::Sampler(sampler))
}
pub fn add_buffer(self, index: u32, buffer: BufferId, range: Range<u64>) -> Self {
self.add_binding(
index,
RenderResourceBinding::Buffer {
buffer,
range,
dynamic_index: None,
},
)
}
pub fn add_dynamic_buffer(
self,
index: u32,
buffer: BufferId,
range: Range<u64>,
dynamic_index: u32,
) -> Self {
self.add_binding(
index,
RenderResourceBinding::Buffer {
buffer,
range,
dynamic_index: Some(dynamic_index),
},
)
}
pub fn finish(mut self) -> BindGroup {
self.indexed_bindings.sort_by_key(|i| i.index);
BindGroup {
id: BindGroupId(self.hasher.finish()),
indexed_bindings: Arc::new(self.indexed_bindings),
dynamic_uniform_indices: if self.dynamic_uniform_indices.is_empty() {
None
} else {
Some(Arc::new(self.dynamic_uniform_indices))
},
}
}
}