oximedia_gpu/
descriptor_set.rs1#![allow(dead_code)]
2#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub enum BindingType {
7 UniformBuffer,
9 StorageBuffer,
11 SampledTexture,
13 StorageTexture,
15 CombinedImageSampler,
17}
18
19impl BindingType {
20 #[must_use]
22 pub fn is_buffer(&self) -> bool {
23 matches!(self, Self::UniformBuffer | Self::StorageBuffer)
24 }
25
26 #[must_use]
28 pub fn is_texture(&self) -> bool {
29 matches!(
30 self,
31 Self::SampledTexture | Self::StorageTexture | Self::CombinedImageSampler
32 )
33 }
34
35 #[must_use]
37 pub fn is_writable(&self) -> bool {
38 matches!(self, Self::StorageBuffer | Self::StorageTexture)
39 }
40}
41
42#[derive(Debug, Clone)]
44pub struct DescriptorBinding {
45 pub slot: u32,
47 pub binding_type: BindingType,
49 pub count: u32,
51 pub label: Option<String>,
53}
54
55impl DescriptorBinding {
56 #[must_use]
58 pub fn new(slot: u32, binding_type: BindingType) -> Self {
59 Self {
60 slot,
61 binding_type,
62 count: 1,
63 label: None,
64 }
65 }
66
67 #[must_use]
69 pub fn array(slot: u32, binding_type: BindingType, count: u32) -> Self {
70 Self {
71 slot,
72 binding_type,
73 count,
74 label: None,
75 }
76 }
77
78 #[must_use]
80 pub fn with_label(mut self, label: impl Into<String>) -> Self {
81 self.label = Some(label.into());
82 self
83 }
84
85 #[must_use]
87 pub fn is_valid(&self) -> bool {
88 self.count >= 1
89 }
90}
91
92#[derive(Debug, Default)]
94pub struct DescriptorSet {
95 bindings: Vec<DescriptorBinding>,
96}
97
98impl DescriptorSet {
99 #[must_use]
101 pub fn new() -> Self {
102 Self::default()
103 }
104
105 pub fn add_binding(&mut self, binding: DescriptorBinding) {
107 if let Some(existing) = self.bindings.iter_mut().find(|b| b.slot == binding.slot) {
108 *existing = binding;
109 } else {
110 self.bindings.push(binding);
111 }
112 }
113
114 #[must_use]
116 pub fn binding_count(&self) -> usize {
117 self.bindings.len()
118 }
119
120 #[must_use]
122 pub fn get_binding(&self, slot: u32) -> Option<&DescriptorBinding> {
123 self.bindings.iter().find(|b| b.slot == slot)
124 }
125
126 #[must_use]
128 pub fn buffer_bindings(&self) -> Vec<&DescriptorBinding> {
129 self.bindings
130 .iter()
131 .filter(|b| b.binding_type.is_buffer())
132 .collect()
133 }
134
135 #[must_use]
137 pub fn texture_bindings(&self) -> Vec<&DescriptorBinding> {
138 self.bindings
139 .iter()
140 .filter(|b| b.binding_type.is_texture())
141 .collect()
142 }
143}
144
145#[derive(Debug, Default)]
148pub struct DescriptorLayout {
149 entries: Vec<DescriptorBinding>,
150}
151
152impl DescriptorLayout {
153 #[must_use]
155 pub fn new() -> Self {
156 Self::default()
157 }
158
159 pub fn add_entry(&mut self, entry: DescriptorBinding) {
161 self.entries.push(entry);
162 }
163
164 #[must_use]
166 pub fn bindings(&self) -> &[DescriptorBinding] {
167 &self.entries
168 }
169
170 #[must_use]
172 pub fn len(&self) -> usize {
173 self.entries.len()
174 }
175
176 #[must_use]
178 pub fn is_empty(&self) -> bool {
179 self.entries.is_empty()
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use super::*;
186
187 #[test]
188 fn test_binding_type_is_buffer_uniform() {
189 assert!(BindingType::UniformBuffer.is_buffer());
190 }
191
192 #[test]
193 fn test_binding_type_is_buffer_storage() {
194 assert!(BindingType::StorageBuffer.is_buffer());
195 }
196
197 #[test]
198 fn test_binding_type_is_buffer_texture_false() {
199 assert!(!BindingType::SampledTexture.is_buffer());
200 }
201
202 #[test]
203 fn test_binding_type_is_texture() {
204 assert!(BindingType::SampledTexture.is_texture());
205 assert!(BindingType::StorageTexture.is_texture());
206 assert!(BindingType::CombinedImageSampler.is_texture());
207 }
208
209 #[test]
210 fn test_binding_type_is_writable() {
211 assert!(BindingType::StorageBuffer.is_writable());
212 assert!(BindingType::StorageTexture.is_writable());
213 assert!(!BindingType::UniformBuffer.is_writable());
214 assert!(!BindingType::SampledTexture.is_writable());
215 }
216
217 #[test]
218 fn test_descriptor_binding_is_valid() {
219 let b = DescriptorBinding::new(0, BindingType::UniformBuffer);
220 assert!(b.is_valid());
221 }
222
223 #[test]
224 fn test_descriptor_binding_array_count() {
225 let b = DescriptorBinding::array(1, BindingType::SampledTexture, 4);
226 assert_eq!(b.count, 4);
227 assert!(b.is_valid());
228 }
229
230 #[test]
231 fn test_descriptor_binding_with_label() {
232 let b = DescriptorBinding::new(2, BindingType::StorageBuffer).with_label("my_buf");
233 assert_eq!(b.label.as_deref(), Some("my_buf"));
234 }
235
236 #[test]
237 fn test_descriptor_set_add_binding_count() {
238 let mut set = DescriptorSet::new();
239 set.add_binding(DescriptorBinding::new(0, BindingType::UniformBuffer));
240 set.add_binding(DescriptorBinding::new(1, BindingType::SampledTexture));
241 assert_eq!(set.binding_count(), 2);
242 }
243
244 #[test]
245 fn test_descriptor_set_replace_binding() {
246 let mut set = DescriptorSet::new();
247 set.add_binding(DescriptorBinding::new(0, BindingType::UniformBuffer));
248 set.add_binding(DescriptorBinding::new(0, BindingType::StorageBuffer));
249 assert_eq!(set.binding_count(), 1);
250 assert_eq!(
251 set.get_binding(0)
252 .expect("binding should exist")
253 .binding_type,
254 BindingType::StorageBuffer
255 );
256 }
257
258 #[test]
259 fn test_descriptor_set_buffer_bindings() {
260 let mut set = DescriptorSet::new();
261 set.add_binding(DescriptorBinding::new(0, BindingType::UniformBuffer));
262 set.add_binding(DescriptorBinding::new(1, BindingType::SampledTexture));
263 set.add_binding(DescriptorBinding::new(2, BindingType::StorageBuffer));
264 assert_eq!(set.buffer_bindings().len(), 2);
265 }
266
267 #[test]
268 fn test_descriptor_layout_bindings() {
269 let mut layout = DescriptorLayout::new();
270 layout.add_entry(DescriptorBinding::new(0, BindingType::UniformBuffer));
271 layout.add_entry(DescriptorBinding::new(1, BindingType::StorageTexture));
272 assert_eq!(layout.bindings().len(), 2);
273 assert!(!layout.is_empty());
274 }
275
276 #[test]
277 fn test_descriptor_layout_empty() {
278 let layout = DescriptorLayout::new();
279 assert!(layout.is_empty());
280 assert_eq!(layout.len(), 0);
281 }
282}