1 // Copyright (c) 2017 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9
10 //! A simple, immutable descriptor set that is expected to be long-lived.
11 //!
12 //! Creating a persistent descriptor set allocates from a pool, and can't be modified once created.
13 //! You are therefore encouraged to create them at initialization and not the during
14 //! performance-critical paths.
15 //!
16 //! > **Note**: You can control of the pool that is used to create the descriptor set, if you wish
17 //! > so. By creating a implementation of the `DescriptorPool` trait that doesn't perform any
18 //! > actual allocation, you can skip this allocation and make it acceptable to use a persistent
19 //! > descriptor set in performance-critical paths..
20 //!
21 //! The template parameter of the `PersistentDescriptorSet` is complex, and you shouldn't try to
22 //! express it explicitly. If you want to store your descriptor set in a struct or in a `Vec` for
23 //! example, you are encouraged to turn the `PersistentDescriptorSet` into a `Box<DescriptorSet>`
24 //! or a `Arc<DescriptorSet>`.
25 //!
26 //! # Example
27 //! TODO:
28
29 use crate::buffer::BufferAccess;
30 use crate::buffer::BufferViewRef;
31 use crate::descriptor_set::layout::DescriptorDesc;
32 use crate::descriptor_set::layout::DescriptorDescTy;
33 use crate::descriptor_set::layout::DescriptorImageDesc;
34 use crate::descriptor_set::layout::DescriptorImageDescArray;
35 use crate::descriptor_set::layout::DescriptorImageDescDimensions;
36 use crate::descriptor_set::layout::DescriptorSetLayout;
37 use crate::descriptor_set::layout::DescriptorType;
38 use crate::descriptor_set::pool::standard::StdDescriptorPoolAlloc;
39 use crate::descriptor_set::pool::DescriptorPool;
40 use crate::descriptor_set::pool::DescriptorPoolAlloc;
41 use crate::descriptor_set::sys::DescriptorWrite;
42 use crate::descriptor_set::DescriptorSet;
43 use crate::descriptor_set::UnsafeDescriptorSet;
44 use crate::device::Device;
45 use crate::device::DeviceOwned;
46 use crate::format::Format;
47 use crate::image::view::ImageViewAbstract;
48 use crate::image::SampleCount;
49 use crate::sampler::Sampler;
50 use crate::OomError;
51 use crate::VulkanObject;
52 use std::error;
53 use std::fmt;
54 use std::hash::Hash;
55 use std::hash::Hasher;
56 use std::sync::Arc;
57
58 /// A simple, immutable descriptor set that is expected to be long-lived.
59 pub struct PersistentDescriptorSet<R, P = StdDescriptorPoolAlloc> {
60 inner: P,
61 resources: R,
62 layout: Arc<DescriptorSetLayout>,
63 }
64
65 impl PersistentDescriptorSet<()> {
66 /// Starts the process of building a `PersistentDescriptorSet`. Returns a builder.
67 ///
68 /// # Panic
69 ///
70 /// - Panics if the set id is out of range.
71 ///
start(layout: Arc<DescriptorSetLayout>) -> PersistentDescriptorSetBuilder<()>72 pub fn start(layout: Arc<DescriptorSetLayout>) -> PersistentDescriptorSetBuilder<()> {
73 let cap = layout.num_bindings();
74
75 PersistentDescriptorSetBuilder {
76 layout,
77 binding_id: 0,
78 writes: Vec::with_capacity(cap),
79 resources: (),
80 }
81 }
82 }
83
84 unsafe impl<R, P> DescriptorSet for PersistentDescriptorSet<R, P>
85 where
86 P: DescriptorPoolAlloc,
87 R: PersistentDescriptorSetResources,
88 {
89 #[inline]
inner(&self) -> &UnsafeDescriptorSet90 fn inner(&self) -> &UnsafeDescriptorSet {
91 self.inner.inner()
92 }
93
94 #[inline]
layout(&self) -> &Arc<DescriptorSetLayout>95 fn layout(&self) -> &Arc<DescriptorSetLayout> {
96 &self.layout
97 }
98
99 #[inline]
num_buffers(&self) -> usize100 fn num_buffers(&self) -> usize {
101 self.resources.num_buffers()
102 }
103
104 #[inline]
buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)>105 fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> {
106 self.resources.buffer(index)
107 }
108
109 #[inline]
num_images(&self) -> usize110 fn num_images(&self) -> usize {
111 self.resources.num_images()
112 }
113
114 #[inline]
image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)>115 fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> {
116 self.resources.image(index)
117 }
118 }
119
120 unsafe impl<R, P> DeviceOwned for PersistentDescriptorSet<R, P> {
121 #[inline]
device(&self) -> &Arc<Device>122 fn device(&self) -> &Arc<Device> {
123 self.layout.device()
124 }
125 }
126
127 impl<R, P> PartialEq for PersistentDescriptorSet<R, P>
128 where
129 P: DescriptorPoolAlloc,
130 R: PersistentDescriptorSetResources,
131 {
132 #[inline]
eq(&self, other: &Self) -> bool133 fn eq(&self, other: &Self) -> bool {
134 self.inner().internal_object() == other.inner().internal_object()
135 && self.device() == other.device()
136 }
137 }
138
139 impl<R, P> Eq for PersistentDescriptorSet<R, P>
140 where
141 P: DescriptorPoolAlloc,
142 R: PersistentDescriptorSetResources,
143 {
144 }
145
146 impl<R, P> Hash for PersistentDescriptorSet<R, P>
147 where
148 P: DescriptorPoolAlloc,
149 R: PersistentDescriptorSetResources,
150 {
151 #[inline]
hash<H: Hasher>(&self, state: &mut H)152 fn hash<H: Hasher>(&self, state: &mut H) {
153 self.inner().internal_object().hash(state);
154 self.device().hash(state);
155 }
156 }
157
158 /// Prototype of a `PersistentDescriptorSet`.
159 ///
160 /// The template parameter `R` is an unspecified type that represents the list of resources.
161 ///
162 /// See the docs of `PersistentDescriptorSet` for an example.
163 pub struct PersistentDescriptorSetBuilder<R> {
164 // The descriptor set layout.
165 layout: Arc<DescriptorSetLayout>,
166 // Binding currently being filled.
167 binding_id: usize,
168 // The writes to perform on a descriptor set in order to put the resources in it.
169 writes: Vec<DescriptorWrite>,
170 // Holds the resources alive.
171 resources: R,
172 }
173
174 // TODO: lots of checks are still missing, see the docs of
175 // VkDescriptorImageInfo and VkWriteDescriptorSet
176
177 impl<R> PersistentDescriptorSetBuilder<R> {
178 /// Builds a `PersistentDescriptorSet` from the builder.
179 #[inline]
build( self, ) -> Result<PersistentDescriptorSet<R, StdDescriptorPoolAlloc>, PersistentDescriptorSetBuildError>180 pub fn build(
181 self,
182 ) -> Result<PersistentDescriptorSet<R, StdDescriptorPoolAlloc>, PersistentDescriptorSetBuildError>
183 {
184 let mut pool = Device::standard_descriptor_pool(self.layout.device());
185 self.build_with_pool(&mut pool)
186 }
187
188 /// Builds a `PersistentDescriptorSet` from the builder.
189 ///
190 /// # Panic
191 ///
192 /// Panics if the pool doesn't have the same device as the descriptor set layout.
193 ///
build_with_pool<P>( self, pool: &mut P, ) -> Result<PersistentDescriptorSet<R, P::Alloc>, PersistentDescriptorSetBuildError> where P: ?Sized + DescriptorPool,194 pub fn build_with_pool<P>(
195 self,
196 pool: &mut P,
197 ) -> Result<PersistentDescriptorSet<R, P::Alloc>, PersistentDescriptorSetBuildError>
198 where
199 P: ?Sized + DescriptorPool,
200 {
201 assert_eq!(
202 self.layout.device().internal_object(),
203 pool.device().internal_object()
204 );
205
206 let expected_desc = self.layout.num_bindings();
207
208 if expected_desc > self.binding_id {
209 return Err(PersistentDescriptorSetBuildError::MissingDescriptors {
210 expected: expected_desc as u32,
211 obtained: self.binding_id as u32,
212 });
213 }
214
215 debug_assert_eq!(expected_desc, self.binding_id);
216
217 let set = unsafe {
218 let mut set = pool.alloc(&self.layout)?;
219 set.inner_mut()
220 .write(pool.device(), self.writes.into_iter());
221 set
222 };
223
224 Ok(PersistentDescriptorSet {
225 inner: set,
226 resources: self.resources,
227 layout: self.layout,
228 })
229 }
230
231 /// Call this function if the next element of the set is an array in order to set the value of
232 /// each element.
233 ///
234 /// Returns an error if the descriptor is empty.
235 ///
236 /// This function can be called even if the descriptor isn't an array, and it is valid to enter
237 /// the "array", add one element, then leave.
238 #[inline]
enter_array( self, ) -> Result<PersistentDescriptorSetBuilderArray<R>, PersistentDescriptorSetError>239 pub fn enter_array(
240 self,
241 ) -> Result<PersistentDescriptorSetBuilderArray<R>, PersistentDescriptorSetError> {
242 let desc = match self.layout.descriptor(self.binding_id) {
243 Some(d) => d,
244 None => return Err(PersistentDescriptorSetError::EmptyExpected),
245 };
246
247 Ok(PersistentDescriptorSetBuilderArray {
248 builder: self,
249 desc,
250 array_element: 0,
251 })
252 }
253
254 /// Skips the current descriptor if it is empty.
255 #[inline]
add_empty( mut self, ) -> Result<PersistentDescriptorSetBuilder<R>, PersistentDescriptorSetError>256 pub fn add_empty(
257 mut self,
258 ) -> Result<PersistentDescriptorSetBuilder<R>, PersistentDescriptorSetError> {
259 match self.layout.descriptor(self.binding_id) {
260 None => (),
261 Some(desc) => {
262 return Err(PersistentDescriptorSetError::WrongDescriptorTy {
263 expected: desc.ty.ty(),
264 })
265 }
266 }
267
268 self.binding_id += 1;
269 Ok(self)
270 }
271
272 /// Binds a buffer as the next descriptor.
273 ///
274 /// An error is returned if the buffer isn't compatible with the descriptor.
275 ///
276 /// # Panic
277 ///
278 /// Panics if the buffer doesn't have the same device as the descriptor set layout.
279 ///
280 #[inline]
add_buffer<T>( self, buffer: T, ) -> Result< PersistentDescriptorSetBuilder<(R, PersistentDescriptorSetBuf<T>)>, PersistentDescriptorSetError, > where T: BufferAccess,281 pub fn add_buffer<T>(
282 self,
283 buffer: T,
284 ) -> Result<
285 PersistentDescriptorSetBuilder<(R, PersistentDescriptorSetBuf<T>)>,
286 PersistentDescriptorSetError,
287 >
288 where
289 T: BufferAccess,
290 {
291 self.enter_array()?.add_buffer(buffer)?.leave_array()
292 }
293
294 /// Binds a buffer view as the next descriptor.
295 ///
296 /// An error is returned if the buffer isn't compatible with the descriptor.
297 ///
298 /// # Panic
299 ///
300 /// Panics if the buffer view doesn't have the same device as the descriptor set layout.
301 ///
add_buffer_view<T>( self, view: T, ) -> Result< PersistentDescriptorSetBuilder<(R, PersistentDescriptorSetBufView<T>)>, PersistentDescriptorSetError, > where T: BufferViewRef,302 pub fn add_buffer_view<T>(
303 self,
304 view: T,
305 ) -> Result<
306 PersistentDescriptorSetBuilder<(R, PersistentDescriptorSetBufView<T>)>,
307 PersistentDescriptorSetError,
308 >
309 where
310 T: BufferViewRef,
311 {
312 self.enter_array()?.add_buffer_view(view)?.leave_array()
313 }
314
315 /// Binds an image view as the next descriptor.
316 ///
317 /// An error is returned if the image view isn't compatible with the descriptor.
318 ///
319 /// # Panic
320 ///
321 /// Panics if the image view doesn't have the same device as the descriptor set layout.
322 ///
323 #[inline]
add_image<T>( self, image_view: T, ) -> Result< PersistentDescriptorSetBuilder<(R, PersistentDescriptorSetImg<T>)>, PersistentDescriptorSetError, > where T: ImageViewAbstract,324 pub fn add_image<T>(
325 self,
326 image_view: T,
327 ) -> Result<
328 PersistentDescriptorSetBuilder<(R, PersistentDescriptorSetImg<T>)>,
329 PersistentDescriptorSetError,
330 >
331 where
332 T: ImageViewAbstract,
333 {
334 self.enter_array()?.add_image(image_view)?.leave_array()
335 }
336
337 /// Binds an image view with a sampler as the next descriptor.
338 ///
339 /// An error is returned if the image view isn't compatible with the descriptor.
340 ///
341 /// # Panic
342 ///
343 /// Panics if the image view or the sampler doesn't have the same device as the descriptor set
344 /// layout.
345 ///
346 #[inline]
add_sampled_image<T>( self, image_view: T, sampler: Arc<Sampler>, ) -> Result< PersistentDescriptorSetBuilder<( (R, PersistentDescriptorSetImg<T>), PersistentDescriptorSetSampler, )>, PersistentDescriptorSetError, > where T: ImageViewAbstract,347 pub fn add_sampled_image<T>(
348 self,
349 image_view: T,
350 sampler: Arc<Sampler>,
351 ) -> Result<
352 PersistentDescriptorSetBuilder<(
353 (R, PersistentDescriptorSetImg<T>),
354 PersistentDescriptorSetSampler,
355 )>,
356 PersistentDescriptorSetError,
357 >
358 where
359 T: ImageViewAbstract,
360 {
361 self.enter_array()?
362 .add_sampled_image(image_view, sampler)?
363 .leave_array()
364 }
365
366 /// Binds a sampler as the next descriptor.
367 ///
368 /// An error is returned if the sampler isn't compatible with the descriptor.
369 ///
370 /// # Panic
371 ///
372 /// Panics if the sampler doesn't have the same device as the descriptor set layout.
373 ///
374 #[inline]
add_sampler( self, sampler: Arc<Sampler>, ) -> Result< PersistentDescriptorSetBuilder<(R, PersistentDescriptorSetSampler)>, PersistentDescriptorSetError, >375 pub fn add_sampler(
376 self,
377 sampler: Arc<Sampler>,
378 ) -> Result<
379 PersistentDescriptorSetBuilder<(R, PersistentDescriptorSetSampler)>,
380 PersistentDescriptorSetError,
381 > {
382 self.enter_array()?.add_sampler(sampler)?.leave_array()
383 }
384 }
385
386 /// Same as `PersistentDescriptorSetBuilder`, but we're in an array.
387 pub struct PersistentDescriptorSetBuilderArray<R> {
388 // The original builder.
389 builder: PersistentDescriptorSetBuilder<R>,
390 // Current array elements.
391 array_element: usize,
392 // Description of the descriptor.
393 desc: DescriptorDesc,
394 }
395
396 impl<R> PersistentDescriptorSetBuilderArray<R> {
397 /// Leaves the array. Call this once you added all the elements of the array.
leave_array( mut self, ) -> Result<PersistentDescriptorSetBuilder<R>, PersistentDescriptorSetError>398 pub fn leave_array(
399 mut self,
400 ) -> Result<PersistentDescriptorSetBuilder<R>, PersistentDescriptorSetError> {
401 if self.desc.array_count > self.array_element as u32 {
402 return Err(PersistentDescriptorSetError::MissingArrayElements {
403 expected: self.desc.array_count,
404 obtained: self.array_element as u32,
405 });
406 }
407
408 debug_assert_eq!(self.desc.array_count, self.array_element as u32);
409
410 self.builder.binding_id += 1;
411 Ok(self.builder)
412 }
413
414 /// Binds a buffer as the next element in the array.
415 ///
416 /// An error is returned if the buffer isn't compatible with the descriptor.
417 ///
418 /// # Panic
419 ///
420 /// Panics if the buffer doesn't have the same device as the descriptor set layout.
421 ///
add_buffer<T>( mut self, buffer: T, ) -> Result< PersistentDescriptorSetBuilderArray<(R, PersistentDescriptorSetBuf<T>)>, PersistentDescriptorSetError, > where T: BufferAccess,422 pub fn add_buffer<T>(
423 mut self,
424 buffer: T,
425 ) -> Result<
426 PersistentDescriptorSetBuilderArray<(R, PersistentDescriptorSetBuf<T>)>,
427 PersistentDescriptorSetError,
428 >
429 where
430 T: BufferAccess,
431 {
432 assert_eq!(
433 self.builder.layout.device().internal_object(),
434 buffer.inner().buffer.device().internal_object()
435 );
436
437 if self.array_element as u32 >= self.desc.array_count {
438 return Err(PersistentDescriptorSetError::ArrayOutOfBounds);
439 }
440
441 self.builder.writes.push(match self.desc.ty {
442 DescriptorDescTy::Buffer(ref buffer_desc) => {
443 // Note that the buffer content is not checked. This is technically not unsafe as
444 // long as the data in the buffer has no invalid memory representation (ie. no
445 // bool, no enum, no pointer, no str) and as long as the robust buffer access
446 // feature is enabled.
447 // TODO: this is not checked ^
448
449 // TODO: eventually shouldn't be an assert ; for now robust_buffer_access is always
450 // enabled so this assert should never fail in practice, but we put it anyway
451 // in case we forget to adjust this code
452 assert!(
453 self.builder
454 .layout
455 .device()
456 .enabled_features()
457 .robust_buffer_access
458 );
459
460 if buffer_desc.storage {
461 if !buffer.inner().buffer.usage().storage_buffer {
462 return Err(PersistentDescriptorSetError::MissingBufferUsage(
463 MissingBufferUsage::StorageBuffer,
464 ));
465 }
466
467 unsafe {
468 DescriptorWrite::storage_buffer(
469 self.builder.binding_id as u32,
470 self.array_element as u32,
471 &buffer,
472 )
473 }
474 } else {
475 if !buffer.inner().buffer.usage().uniform_buffer {
476 return Err(PersistentDescriptorSetError::MissingBufferUsage(
477 MissingBufferUsage::UniformBuffer,
478 ));
479 }
480
481 if buffer_desc.dynamic.unwrap_or(false) {
482 unsafe {
483 DescriptorWrite::dynamic_uniform_buffer(
484 self.builder.binding_id as u32,
485 self.array_element as u32,
486 &buffer,
487 )
488 }
489 } else {
490 unsafe {
491 DescriptorWrite::uniform_buffer(
492 self.builder.binding_id as u32,
493 self.array_element as u32,
494 &buffer,
495 )
496 }
497 }
498 }
499 }
500 ref d => {
501 return Err(PersistentDescriptorSetError::WrongDescriptorTy { expected: d.ty() });
502 }
503 });
504
505 Ok(PersistentDescriptorSetBuilderArray {
506 builder: PersistentDescriptorSetBuilder {
507 layout: self.builder.layout,
508 binding_id: self.builder.binding_id,
509 writes: self.builder.writes,
510 resources: (
511 self.builder.resources,
512 PersistentDescriptorSetBuf {
513 buffer,
514 descriptor_num: self.builder.binding_id as u32,
515 },
516 ),
517 },
518 desc: self.desc,
519 array_element: self.array_element + 1,
520 })
521 }
522
523 /// Binds a buffer view as the next element in the array.
524 ///
525 /// An error is returned if the buffer isn't compatible with the descriptor.
526 ///
527 /// # Panic
528 ///
529 /// Panics if the buffer view doesn't have the same device as the descriptor set layout.
530 ///
add_buffer_view<T>( mut self, view: T, ) -> Result< PersistentDescriptorSetBuilderArray<(R, PersistentDescriptorSetBufView<T>)>, PersistentDescriptorSetError, > where T: BufferViewRef,531 pub fn add_buffer_view<T>(
532 mut self,
533 view: T,
534 ) -> Result<
535 PersistentDescriptorSetBuilderArray<(R, PersistentDescriptorSetBufView<T>)>,
536 PersistentDescriptorSetError,
537 >
538 where
539 T: BufferViewRef,
540 {
541 assert_eq!(
542 self.builder.layout.device().internal_object(),
543 view.view().device().internal_object()
544 );
545
546 if self.array_element as u32 >= self.desc.array_count {
547 return Err(PersistentDescriptorSetError::ArrayOutOfBounds);
548 }
549
550 self.builder.writes.push(match self.desc.ty {
551 DescriptorDescTy::TexelBuffer { storage, .. } => {
552 if storage {
553 // TODO: storage_texel_buffer_atomic
554
555 if !view.view().storage_texel_buffer() {
556 return Err(PersistentDescriptorSetError::MissingBufferUsage(
557 MissingBufferUsage::StorageTexelBuffer,
558 ));
559 }
560
561 DescriptorWrite::storage_texel_buffer(
562 self.builder.binding_id as u32,
563 self.array_element as u32,
564 view.view(),
565 )
566 } else {
567 if !view.view().uniform_texel_buffer() {
568 return Err(PersistentDescriptorSetError::MissingBufferUsage(
569 MissingBufferUsage::UniformTexelBuffer,
570 ));
571 }
572
573 DescriptorWrite::uniform_texel_buffer(
574 self.builder.binding_id as u32,
575 self.array_element as u32,
576 view.view(),
577 )
578 }
579 }
580 ref d => {
581 return Err(PersistentDescriptorSetError::WrongDescriptorTy { expected: d.ty() });
582 }
583 });
584
585 Ok(PersistentDescriptorSetBuilderArray {
586 builder: PersistentDescriptorSetBuilder {
587 layout: self.builder.layout,
588 binding_id: self.builder.binding_id,
589 writes: self.builder.writes,
590 resources: (
591 self.builder.resources,
592 PersistentDescriptorSetBufView {
593 view,
594 descriptor_num: self.builder.binding_id as u32,
595 },
596 ),
597 },
598 desc: self.desc,
599 array_element: self.array_element + 1,
600 })
601 }
602
603 /// Binds an image view as the next element in the array.
604 ///
605 /// An error is returned if the image view isn't compatible with the descriptor.
606 ///
607 /// # Panic
608 ///
609 /// Panics if the image view doesn't have the same device as the descriptor set layout.
610 ///
add_image<T>( mut self, image_view: T, ) -> Result< PersistentDescriptorSetBuilderArray<(R, PersistentDescriptorSetImg<T>)>, PersistentDescriptorSetError, > where T: ImageViewAbstract,611 pub fn add_image<T>(
612 mut self,
613 image_view: T,
614 ) -> Result<
615 PersistentDescriptorSetBuilderArray<(R, PersistentDescriptorSetImg<T>)>,
616 PersistentDescriptorSetError,
617 >
618 where
619 T: ImageViewAbstract,
620 {
621 assert_eq!(
622 self.builder.layout.device().internal_object(),
623 image_view.image().inner().image.device().internal_object()
624 );
625
626 if self.array_element as u32 >= self.desc.array_count {
627 return Err(PersistentDescriptorSetError::ArrayOutOfBounds);
628 }
629
630 let desc = match self.builder.layout.descriptor(self.builder.binding_id) {
631 Some(d) => d,
632 None => return Err(PersistentDescriptorSetError::EmptyExpected),
633 };
634
635 self.builder.writes.push(match desc.ty {
636 DescriptorDescTy::Image(ref desc) => {
637 image_match_desc(&image_view, &desc)?;
638
639 if desc.sampled {
640 DescriptorWrite::sampled_image(
641 self.builder.binding_id as u32,
642 self.array_element as u32,
643 &image_view,
644 )
645 } else {
646 if !image_view.component_mapping().is_identity() {
647 return Err(PersistentDescriptorSetError::NotIdentitySwizzled);
648 }
649
650 DescriptorWrite::storage_image(
651 self.builder.binding_id as u32,
652 self.array_element as u32,
653 &image_view,
654 )
655 }
656 }
657 DescriptorDescTy::InputAttachment {
658 multisampled,
659 array_layers,
660 } => {
661 if !image_view.image().inner().image.usage().input_attachment {
662 return Err(PersistentDescriptorSetError::MissingImageUsage(
663 MissingImageUsage::InputAttachment,
664 ));
665 }
666
667 if !image_view.component_mapping().is_identity() {
668 return Err(PersistentDescriptorSetError::NotIdentitySwizzled);
669 }
670
671 if multisampled && image_view.image().samples() == SampleCount::Sample1 {
672 return Err(PersistentDescriptorSetError::ExpectedMultisampled);
673 } else if !multisampled && image_view.image().samples() != SampleCount::Sample1 {
674 return Err(PersistentDescriptorSetError::UnexpectedMultisampled);
675 }
676
677 let image_layers = image_view.array_layers();
678 let num_layers = image_layers.end - image_layers.start;
679
680 match array_layers {
681 DescriptorImageDescArray::NonArrayed => {
682 if num_layers != 1 {
683 return Err(PersistentDescriptorSetError::ArrayLayersMismatch {
684 expected: 1,
685 obtained: num_layers,
686 });
687 }
688 }
689 DescriptorImageDescArray::Arrayed {
690 max_layers: Some(max_layers),
691 } => {
692 if num_layers > max_layers {
693 // TODO: is this correct? "max" layers? or is it in fact min layers?
694 return Err(PersistentDescriptorSetError::ArrayLayersMismatch {
695 expected: max_layers,
696 obtained: num_layers,
697 });
698 }
699 }
700 DescriptorImageDescArray::Arrayed { max_layers: None } => {}
701 };
702
703 DescriptorWrite::input_attachment(
704 self.builder.binding_id as u32,
705 self.array_element as u32,
706 &image_view,
707 )
708 }
709 ty => {
710 return Err(PersistentDescriptorSetError::WrongDescriptorTy { expected: ty.ty() });
711 }
712 });
713
714 Ok(PersistentDescriptorSetBuilderArray {
715 builder: PersistentDescriptorSetBuilder {
716 layout: self.builder.layout,
717 binding_id: self.builder.binding_id,
718 writes: self.builder.writes,
719 resources: (
720 self.builder.resources,
721 PersistentDescriptorSetImg {
722 image: image_view,
723 descriptor_num: self.builder.binding_id as u32,
724 },
725 ),
726 },
727 desc: self.desc,
728 array_element: self.array_element + 1,
729 })
730 }
731
732 /// Binds an image view with a sampler as the next element in the array.
733 ///
734 /// An error is returned if the image view isn't compatible with the descriptor.
735 ///
736 /// # Panic
737 ///
738 /// Panics if the image or the sampler doesn't have the same device as the descriptor set layout.
739 ///
add_sampled_image<T>( mut self, image_view: T, sampler: Arc<Sampler>, ) -> Result< PersistentDescriptorSetBuilderArray<( (R, PersistentDescriptorSetImg<T>), PersistentDescriptorSetSampler, )>, PersistentDescriptorSetError, > where T: ImageViewAbstract,740 pub fn add_sampled_image<T>(
741 mut self,
742 image_view: T,
743 sampler: Arc<Sampler>,
744 ) -> Result<
745 PersistentDescriptorSetBuilderArray<(
746 (R, PersistentDescriptorSetImg<T>),
747 PersistentDescriptorSetSampler,
748 )>,
749 PersistentDescriptorSetError,
750 >
751 where
752 T: ImageViewAbstract,
753 {
754 assert_eq!(
755 self.builder.layout.device().internal_object(),
756 image_view.image().inner().image.device().internal_object()
757 );
758 assert_eq!(
759 self.builder.layout.device().internal_object(),
760 sampler.device().internal_object()
761 );
762
763 if self.array_element as u32 >= self.desc.array_count {
764 return Err(PersistentDescriptorSetError::ArrayOutOfBounds);
765 }
766
767 let desc = match self.builder.layout.descriptor(self.builder.binding_id) {
768 Some(d) => d,
769 None => return Err(PersistentDescriptorSetError::EmptyExpected),
770 };
771
772 if !image_view.can_be_sampled(&sampler) {
773 return Err(PersistentDescriptorSetError::IncompatibleImageViewSampler);
774 }
775
776 self.builder.writes.push(match desc.ty {
777 DescriptorDescTy::CombinedImageSampler(ref desc) => {
778 image_match_desc(&image_view, &desc)?;
779 DescriptorWrite::combined_image_sampler(
780 self.builder.binding_id as u32,
781 self.array_element as u32,
782 &sampler,
783 &image_view,
784 )
785 }
786 ty => {
787 return Err(PersistentDescriptorSetError::WrongDescriptorTy { expected: ty.ty() });
788 }
789 });
790
791 Ok(PersistentDescriptorSetBuilderArray {
792 builder: PersistentDescriptorSetBuilder {
793 layout: self.builder.layout,
794 binding_id: self.builder.binding_id,
795 writes: self.builder.writes,
796 resources: (
797 (
798 self.builder.resources,
799 PersistentDescriptorSetImg {
800 image: image_view,
801 descriptor_num: self.builder.binding_id as u32,
802 },
803 ),
804 PersistentDescriptorSetSampler { sampler },
805 ),
806 },
807 desc: self.desc,
808 array_element: self.array_element + 1,
809 })
810 }
811
812 /// Binds a sampler as the next element in the array.
813 ///
814 /// An error is returned if the sampler isn't compatible with the descriptor.
815 ///
816 /// # Panic
817 ///
818 /// Panics if the sampler doesn't have the same device as the descriptor set layout.
819 ///
add_sampler( mut self, sampler: Arc<Sampler>, ) -> Result< PersistentDescriptorSetBuilderArray<(R, PersistentDescriptorSetSampler)>, PersistentDescriptorSetError, >820 pub fn add_sampler(
821 mut self,
822 sampler: Arc<Sampler>,
823 ) -> Result<
824 PersistentDescriptorSetBuilderArray<(R, PersistentDescriptorSetSampler)>,
825 PersistentDescriptorSetError,
826 > {
827 assert_eq!(
828 self.builder.layout.device().internal_object(),
829 sampler.device().internal_object()
830 );
831
832 if self.array_element as u32 >= self.desc.array_count {
833 return Err(PersistentDescriptorSetError::ArrayOutOfBounds);
834 }
835
836 let desc = match self.builder.layout.descriptor(self.builder.binding_id) {
837 Some(d) => d,
838 None => return Err(PersistentDescriptorSetError::EmptyExpected),
839 };
840
841 self.builder.writes.push(match desc.ty {
842 DescriptorDescTy::Sampler => DescriptorWrite::sampler(
843 self.builder.binding_id as u32,
844 self.array_element as u32,
845 &sampler,
846 ),
847 ty => {
848 return Err(PersistentDescriptorSetError::WrongDescriptorTy { expected: ty.ty() });
849 }
850 });
851
852 Ok(PersistentDescriptorSetBuilderArray {
853 builder: PersistentDescriptorSetBuilder {
854 layout: self.builder.layout,
855 binding_id: self.builder.binding_id,
856 writes: self.builder.writes,
857 resources: (
858 self.builder.resources,
859 PersistentDescriptorSetSampler { sampler },
860 ),
861 },
862 desc: self.desc,
863 array_element: self.array_element + 1,
864 })
865 }
866 }
867
868 // Checks whether an image view matches the descriptor.
image_match_desc<I>( image_view: &I, desc: &DescriptorImageDesc, ) -> Result<(), PersistentDescriptorSetError> where I: ?Sized + ImageViewAbstract,869 fn image_match_desc<I>(
870 image_view: &I,
871 desc: &DescriptorImageDesc,
872 ) -> Result<(), PersistentDescriptorSetError>
873 where
874 I: ?Sized + ImageViewAbstract,
875 {
876 if desc.sampled && !image_view.image().inner().image.usage().sampled {
877 return Err(PersistentDescriptorSetError::MissingImageUsage(
878 MissingImageUsage::Sampled,
879 ));
880 } else if !desc.sampled && !image_view.image().inner().image.usage().storage {
881 return Err(PersistentDescriptorSetError::MissingImageUsage(
882 MissingImageUsage::Storage,
883 ));
884 }
885
886 let image_view_ty = DescriptorImageDescDimensions::from_image_view_type(image_view.ty());
887 if image_view_ty != desc.dimensions {
888 return Err(PersistentDescriptorSetError::ImageViewTypeMismatch {
889 expected: desc.dimensions,
890 obtained: image_view_ty,
891 });
892 }
893
894 if let Some(format) = desc.format {
895 if image_view.format() != format {
896 return Err(PersistentDescriptorSetError::ImageViewFormatMismatch {
897 expected: format,
898 obtained: image_view.format(),
899 });
900 }
901 }
902
903 if desc.multisampled && image_view.image().samples() == SampleCount::Sample1 {
904 return Err(PersistentDescriptorSetError::ExpectedMultisampled);
905 } else if !desc.multisampled && image_view.image().samples() != SampleCount::Sample1 {
906 return Err(PersistentDescriptorSetError::UnexpectedMultisampled);
907 }
908
909 let image_layers = image_view.array_layers();
910 let num_layers = image_layers.end - image_layers.start;
911
912 match desc.array_layers {
913 DescriptorImageDescArray::NonArrayed => {
914 // TODO: when a non-array is expected, can we pass an image view that is in fact an
915 // array with one layer? need to check
916 let required_layers = if desc.dimensions == DescriptorImageDescDimensions::Cube {
917 6
918 } else {
919 1
920 };
921
922 if num_layers != required_layers {
923 return Err(PersistentDescriptorSetError::ArrayLayersMismatch {
924 expected: 1,
925 obtained: num_layers,
926 });
927 }
928 }
929 DescriptorImageDescArray::Arrayed {
930 max_layers: Some(max_layers),
931 } => {
932 let required_layers = if desc.dimensions == DescriptorImageDescDimensions::Cube {
933 max_layers * 6
934 } else {
935 max_layers
936 };
937
938 // TODO: is this correct? "max" layers? or is it in fact min layers?
939 if num_layers > required_layers {
940 return Err(PersistentDescriptorSetError::ArrayLayersMismatch {
941 expected: max_layers,
942 obtained: num_layers,
943 });
944 }
945 }
946 DescriptorImageDescArray::Arrayed { max_layers: None } => {}
947 };
948
949 Ok(())
950 }
951
952 pub unsafe trait PersistentDescriptorSetResources {
num_buffers(&self) -> usize953 fn num_buffers(&self) -> usize;
buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)>954 fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)>;
num_images(&self) -> usize955 fn num_images(&self) -> usize;
image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)>956 fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)>;
957 }
958
959 unsafe impl PersistentDescriptorSetResources for () {
960 #[inline]
num_buffers(&self) -> usize961 fn num_buffers(&self) -> usize {
962 0
963 }
964
965 #[inline]
buffer(&self, _: usize) -> Option<(&dyn BufferAccess, u32)>966 fn buffer(&self, _: usize) -> Option<(&dyn BufferAccess, u32)> {
967 None
968 }
969
970 #[inline]
num_images(&self) -> usize971 fn num_images(&self) -> usize {
972 0
973 }
974
975 #[inline]
image(&self, _: usize) -> Option<(&dyn ImageViewAbstract, u32)>976 fn image(&self, _: usize) -> Option<(&dyn ImageViewAbstract, u32)> {
977 None
978 }
979 }
980
981 /// Internal object related to the `PersistentDescriptorSet` system.
982 pub struct PersistentDescriptorSetBuf<B> {
983 buffer: B,
984 descriptor_num: u32,
985 }
986
987 unsafe impl<R, B> PersistentDescriptorSetResources for (R, PersistentDescriptorSetBuf<B>)
988 where
989 R: PersistentDescriptorSetResources,
990 B: BufferAccess,
991 {
992 #[inline]
num_buffers(&self) -> usize993 fn num_buffers(&self) -> usize {
994 self.0.num_buffers() + 1
995 }
996
997 #[inline]
buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)>998 fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> {
999 if let Some(buf) = self.0.buffer(index) {
1000 Some(buf)
1001 } else if index == self.0.num_buffers() {
1002 Some((&self.1.buffer, self.1.descriptor_num))
1003 } else {
1004 None
1005 }
1006 }
1007
1008 #[inline]
num_images(&self) -> usize1009 fn num_images(&self) -> usize {
1010 self.0.num_images()
1011 }
1012
1013 #[inline]
image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)>1014 fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> {
1015 self.0.image(index)
1016 }
1017 }
1018
1019 /// Internal object related to the `PersistentDescriptorSet` system.
1020 pub struct PersistentDescriptorSetBufView<V>
1021 where
1022 V: BufferViewRef,
1023 {
1024 view: V,
1025 descriptor_num: u32,
1026 }
1027
1028 unsafe impl<R, V> PersistentDescriptorSetResources for (R, PersistentDescriptorSetBufView<V>)
1029 where
1030 R: PersistentDescriptorSetResources,
1031 V: BufferViewRef,
1032 {
1033 #[inline]
num_buffers(&self) -> usize1034 fn num_buffers(&self) -> usize {
1035 self.0.num_buffers() + 1
1036 }
1037
1038 #[inline]
buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)>1039 fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> {
1040 if let Some(buf) = self.0.buffer(index) {
1041 Some(buf)
1042 } else if index == self.0.num_buffers() {
1043 Some((self.1.view.view().buffer(), self.1.descriptor_num))
1044 } else {
1045 None
1046 }
1047 }
1048
1049 #[inline]
num_images(&self) -> usize1050 fn num_images(&self) -> usize {
1051 self.0.num_images()
1052 }
1053
1054 #[inline]
image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)>1055 fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> {
1056 self.0.image(index)
1057 }
1058 }
1059
1060 /// Internal object related to the `PersistentDescriptorSet` system.
1061 pub struct PersistentDescriptorSetImg<I> {
1062 image: I,
1063 descriptor_num: u32,
1064 }
1065
1066 unsafe impl<R, I> PersistentDescriptorSetResources for (R, PersistentDescriptorSetImg<I>)
1067 where
1068 R: PersistentDescriptorSetResources,
1069 I: ImageViewAbstract,
1070 {
1071 #[inline]
num_buffers(&self) -> usize1072 fn num_buffers(&self) -> usize {
1073 self.0.num_buffers()
1074 }
1075
1076 #[inline]
buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)>1077 fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> {
1078 self.0.buffer(index)
1079 }
1080
1081 #[inline]
num_images(&self) -> usize1082 fn num_images(&self) -> usize {
1083 self.0.num_images() + 1
1084 }
1085
1086 #[inline]
image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)>1087 fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> {
1088 if let Some(img) = self.0.image(index) {
1089 Some(img)
1090 } else if index == self.0.num_images() {
1091 Some((&self.1.image, self.1.descriptor_num))
1092 } else {
1093 None
1094 }
1095 }
1096 }
1097
1098 /// Internal object related to the `PersistentDescriptorSet` system.
1099 pub struct PersistentDescriptorSetSampler {
1100 sampler: Arc<Sampler>,
1101 }
1102
1103 unsafe impl<R> PersistentDescriptorSetResources for (R, PersistentDescriptorSetSampler)
1104 where
1105 R: PersistentDescriptorSetResources,
1106 {
1107 #[inline]
num_buffers(&self) -> usize1108 fn num_buffers(&self) -> usize {
1109 self.0.num_buffers()
1110 }
1111
1112 #[inline]
buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)>1113 fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> {
1114 self.0.buffer(index)
1115 }
1116
1117 #[inline]
num_images(&self) -> usize1118 fn num_images(&self) -> usize {
1119 self.0.num_images()
1120 }
1121
1122 #[inline]
image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)>1123 fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> {
1124 self.0.image(index)
1125 }
1126 }
1127
1128 // Part of the PersistentDescriptorSetError for the case
1129 // of missing usage on a buffer.
1130 #[derive(Debug, Clone)]
1131 pub enum MissingBufferUsage {
1132 StorageBuffer,
1133 UniformBuffer,
1134 StorageTexelBuffer,
1135 UniformTexelBuffer,
1136 }
1137
1138 // Part of the PersistentDescriptorSetError for the case
1139 // of missing usage on an image.
1140 #[derive(Debug, Clone)]
1141 pub enum MissingImageUsage {
1142 InputAttachment,
1143 Sampled,
1144 Storage,
1145 }
1146
1147 /// Error related to the persistent descriptor set.
1148 #[derive(Debug, Clone)]
1149 pub enum PersistentDescriptorSetError {
1150 /// The number of array layers of an image doesn't match what was expected.
1151 ArrayLayersMismatch {
1152 /// Number of expected array layers for the image.
1153 expected: u32,
1154 /// Number of array layers of the image that was added.
1155 obtained: u32,
1156 },
1157
1158 /// Tried to add too many elements to an array.
1159 ArrayOutOfBounds,
1160
1161 /// Expected nothing.
1162 EmptyExpected,
1163
1164 /// Expected a multisampled image, but got a single-sampled image.
1165 ExpectedMultisampled,
1166
1167 /// The format of an image view doesn't match what was expected.
1168 ImageViewFormatMismatch {
1169 /// Expected format.
1170 expected: Format,
1171 /// Format of the image view that was passed.
1172 obtained: Format,
1173 },
1174
1175 /// The type of an image view doesn't match what was expected.
1176 ImageViewTypeMismatch {
1177 /// Expected type.
1178 expected: DescriptorImageDescDimensions,
1179 /// Type of the image view that was passed.
1180 obtained: DescriptorImageDescDimensions,
1181 },
1182
1183 /// The image view isn't compatible with the sampler.
1184 IncompatibleImageViewSampler,
1185
1186 /// Didn't fill all the elements of an array before leaving.
1187 MissingArrayElements {
1188 /// Number of expected elements.
1189 expected: u32,
1190 /// Number of elements that were added.
1191 obtained: u32,
1192 },
1193
1194 /// The buffer is missing the correct usage.
1195 MissingBufferUsage(MissingBufferUsage),
1196
1197 /// The image is missing the correct usage.
1198 MissingImageUsage(MissingImageUsage),
1199
1200 /// The image view has a component swizzle that is different from identity.
1201 NotIdentitySwizzled,
1202
1203 /// Expected a single-sampled image, but got a multisampled image.
1204 UnexpectedMultisampled,
1205
1206 /// Expected one type of resource but got another.
1207 WrongDescriptorTy {
1208 /// The expected descriptor type.
1209 expected: DescriptorType,
1210 },
1211 }
1212
1213 impl error::Error for PersistentDescriptorSetError {}
1214
1215 impl fmt::Display for PersistentDescriptorSetError {
1216 #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>1217 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
1218 write!(
1219 fmt,
1220 "{}",
1221 match *self {
1222 PersistentDescriptorSetError::ArrayLayersMismatch { .. } => {
1223 "the number of array layers of an image doesn't match what was expected"
1224 }
1225 PersistentDescriptorSetError::ArrayOutOfBounds => {
1226 "tried to add too many elements to an array"
1227 }
1228 PersistentDescriptorSetError::EmptyExpected => {
1229 "expected an empty descriptor but got something"
1230 }
1231 PersistentDescriptorSetError::ExpectedMultisampled => {
1232 "expected a multisampled image, but got a single-sampled image"
1233 }
1234 PersistentDescriptorSetError::ImageViewFormatMismatch { .. } => {
1235 "the format of an image view doesn't match what was expected"
1236 }
1237 PersistentDescriptorSetError::ImageViewTypeMismatch { .. } => {
1238 "the type of an image view doesn't match what was expected"
1239 }
1240 PersistentDescriptorSetError::IncompatibleImageViewSampler => {
1241 "the image view isn't compatible with the sampler"
1242 }
1243 PersistentDescriptorSetError::MissingArrayElements { .. } => {
1244 "didn't fill all the elements of an array before leaving"
1245 }
1246 PersistentDescriptorSetError::MissingBufferUsage { .. } => {
1247 "the buffer is missing the correct usage"
1248 }
1249 PersistentDescriptorSetError::MissingImageUsage { .. } => {
1250 "the image is missing the correct usage"
1251 }
1252 PersistentDescriptorSetError::NotIdentitySwizzled => {
1253 "the image view's component mapping is not identity swizzled"
1254 }
1255 PersistentDescriptorSetError::UnexpectedMultisampled => {
1256 "expected a single-sampled image, but got a multisampled image"
1257 }
1258 PersistentDescriptorSetError::WrongDescriptorTy { .. } => {
1259 "expected one type of resource but got another"
1260 }
1261 }
1262 )
1263 }
1264 }
1265
1266 /// Error when building a persistent descriptor set.
1267 #[derive(Debug, Clone)]
1268 pub enum PersistentDescriptorSetBuildError {
1269 /// Out of memory.
1270 OomError(OomError),
1271
1272 /// Didn't fill all the descriptors before building.
1273 MissingDescriptors {
1274 /// Number of expected descriptors.
1275 expected: u32,
1276 /// Number of descriptors that were added.
1277 obtained: u32,
1278 },
1279 }
1280
1281 impl error::Error for PersistentDescriptorSetBuildError {}
1282
1283 impl From<OomError> for PersistentDescriptorSetBuildError {
1284 #[inline]
from(err: OomError) -> PersistentDescriptorSetBuildError1285 fn from(err: OomError) -> PersistentDescriptorSetBuildError {
1286 PersistentDescriptorSetBuildError::OomError(err)
1287 }
1288 }
1289
1290 impl fmt::Display for PersistentDescriptorSetBuildError {
1291 #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>1292 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
1293 write!(
1294 fmt,
1295 "{}",
1296 match *self {
1297 PersistentDescriptorSetBuildError::MissingDescriptors { .. } => {
1298 "didn't fill all the descriptors before building"
1299 }
1300 PersistentDescriptorSetBuildError::OomError(_) => "not enough memory available",
1301 }
1302 )
1303 }
1304 }
1305