• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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