• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016 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 //! Description of a single descriptor.
11 //!
12 //! This module contains traits and structs related to describing a single descriptor. A descriptor
13 //! is a slot where you can bind a buffer or an image so that it can be accessed from your shaders.
14 //! In order to specify which buffer or image to bind to a descriptor, see the `descriptor_set`
15 //! module.
16 //!
17 //! There are four different kinds of descriptors that give access to buffers:
18 //!
19 //! - Uniform texel buffers. Gives read-only access to the content of a buffer. Only supports
20 //!   certain buffer formats.
21 //! - Storage texel buffers. Gives read and/or write access to the content of a buffer. Only
22 //!   supports certain buffer formats. Less restrictive but sometimes slower than uniform texel
23 //!   buffers.
24 //! - Uniform buffers. Gives read-only access to the content of a buffer. Less restrictive but
25 //!   sometimes slower than uniform texel buffers.
26 //! - Storage buffers. Gives read and/or write access to the content of a buffer. Less restrictive
27 //!   but sometimes slower than uniform buffers and storage texel buffers.
28 //!
29 //! There are five different kinds of descriptors related to images:
30 //!
31 //! - Storage images. Gives read and/or write access to individual pixels in an image. The image
32 //!   cannot be sampled. In other words, you have exactly specify which pixel to read or write.
33 //! - Sampled images. Gives read-only access to an image. Before you can use a sampled image in a
34 //!   a shader, you have to combine it with a sampler (see below). The sampler describes how
35 //!   reading the image will behave.
36 //! - Samplers. Doesn't contain an image but a sampler object that describes how an image will be
37 //!   accessed. This is meant to be combined with a sampled image (see above).
38 //! - Combined image and sampler. Similar to a sampled image, but also directly includes the
39 //!   sampler which indicates how the sampling is done.
40 //! - Input attachments. The fastest but also most restrictive access to images. Must be integrated
41 //!   in a render pass. Can only give access to the same pixel as the one you're processing.
42 //!
43 
44 use crate::format::Format;
45 use crate::image::view::ImageViewType;
46 use crate::pipeline::shader::ShaderStages;
47 use crate::pipeline::shader::ShaderStagesSupersetError;
48 use crate::sync::AccessFlags;
49 use crate::sync::PipelineStages;
50 use smallvec::SmallVec;
51 use std::cmp;
52 use std::error;
53 use std::fmt;
54 
55 #[derive(Clone, Debug, Default)]
56 pub struct DescriptorSetDesc {
57     descriptors: SmallVec<[Option<DescriptorDesc>; 32]>,
58 }
59 
60 impl DescriptorSetDesc {
61     /// Builds a new `DescriptorSetDesc` with the given descriptors.
62     ///
63     /// The descriptors must be passed in the order of the bindings. In order words, descriptor
64     /// at bind point 0 first, then descriptor at bind point 1, and so on. If a binding must remain
65     /// empty, you can make the iterator yield `None` for an element.
66     #[inline]
new<I>(descriptors: I) -> DescriptorSetDesc where I: IntoIterator<Item = Option<DescriptorDesc>>,67     pub fn new<I>(descriptors: I) -> DescriptorSetDesc
68     where
69         I: IntoIterator<Item = Option<DescriptorDesc>>,
70     {
71         DescriptorSetDesc {
72             descriptors: descriptors.into_iter().collect(),
73         }
74     }
75 
76     /// Builds a new empty `DescriptorSetDesc`.
77     #[inline]
empty() -> DescriptorSetDesc78     pub fn empty() -> DescriptorSetDesc {
79         DescriptorSetDesc {
80             descriptors: SmallVec::new(),
81         }
82     }
83 
84     /// Returns the descriptors in the set.
bindings(&self) -> &[Option<DescriptorDesc>]85     pub fn bindings(&self) -> &[Option<DescriptorDesc>] {
86         &self.descriptors
87     }
88 
89     /// Returns the descriptor with the given binding number, or `None` if the binding is empty.
90     #[inline]
descriptor(&self, num: usize) -> Option<&DescriptorDesc>91     pub fn descriptor(&self, num: usize) -> Option<&DescriptorDesc> {
92         self.descriptors.get(num).and_then(|b| b.as_ref())
93     }
94 
95     /// Builds the union of this layout description and another.
96     #[inline]
union( first: &DescriptorSetDesc, second: &DescriptorSetDesc, ) -> Result<DescriptorSetDesc, ()>97     pub fn union(
98         first: &DescriptorSetDesc,
99         second: &DescriptorSetDesc,
100     ) -> Result<DescriptorSetDesc, ()> {
101         let num_bindings = cmp::max(first.descriptors.len(), second.descriptors.len());
102         let descriptors = (0..num_bindings)
103             .map(|binding_num| {
104                 DescriptorDesc::union(
105                     first
106                         .descriptors
107                         .get(binding_num)
108                         .map(|desc| desc.as_ref())
109                         .flatten(),
110                     second
111                         .descriptors
112                         .get(binding_num)
113                         .map(|desc| desc.as_ref())
114                         .flatten(),
115                 )
116             })
117             .collect::<Result<_, ()>>()?;
118         Ok(DescriptorSetDesc { descriptors })
119     }
120 
121     /// Builds the union of multiple descriptor sets.
union_multiple( first: &[DescriptorSetDesc], second: &[DescriptorSetDesc], ) -> Result<Vec<DescriptorSetDesc>, ()>122     pub fn union_multiple(
123         first: &[DescriptorSetDesc],
124         second: &[DescriptorSetDesc],
125     ) -> Result<Vec<DescriptorSetDesc>, ()> {
126         // Ewwwwwww
127         let empty = DescriptorSetDesc::empty();
128         let num_sets = cmp::max(first.len(), second.len());
129 
130         (0..num_sets)
131             .map(|set_num| {
132                 Ok(DescriptorSetDesc::union(
133                     first.get(set_num).unwrap_or_else(|| &empty),
134                     second.get(set_num).unwrap_or_else(|| &empty),
135                 )?)
136             })
137             .collect()
138     }
139 
140     /// Transforms a `DescriptorSetDesc`.
141     ///
142     /// Used to adjust automatically inferred `DescriptorSetDesc`s with information that cannot be inferred.
tweak<I>(&mut self, dynamic_buffers: I) where I: IntoIterator<Item = usize>,143     pub fn tweak<I>(&mut self, dynamic_buffers: I)
144     where
145         I: IntoIterator<Item = usize>,
146     {
147         for binding_num in dynamic_buffers {
148             debug_assert!(
149                 self.descriptor(binding_num)
150                     .map_or(false, |desc| match desc.ty {
151                         DescriptorDescTy::Buffer(_) => true,
152                         _ => false,
153                     }),
154                 "tried to make the non-buffer descriptor at binding {} a dynamic buffer",
155                 binding_num
156             );
157 
158             let binding = self
159                 .descriptors
160                 .get_mut(binding_num)
161                 .and_then(|b| b.as_mut());
162 
163             if let Some(desc) = binding {
164                 if let DescriptorDescTy::Buffer(ref buffer_desc) = desc.ty {
165                     desc.ty = DescriptorDescTy::Buffer(DescriptorBufferDesc {
166                         dynamic: Some(true),
167                         ..*buffer_desc
168                     });
169                 }
170             }
171         }
172     }
173 
tweak_multiple<I>(sets: &mut [DescriptorSetDesc], dynamic_buffers: I) where I: IntoIterator<Item = (usize, usize)>,174     pub fn tweak_multiple<I>(sets: &mut [DescriptorSetDesc], dynamic_buffers: I)
175     where
176         I: IntoIterator<Item = (usize, usize)>,
177     {
178         for (set_num, binding_num) in dynamic_buffers {
179             debug_assert!(
180                 set_num < sets.len(),
181                 "tried to make a dynamic buffer in the nonexistent set {}",
182                 set_num,
183             );
184 
185             sets.get_mut(set_num).map(|set| set.tweak([binding_num]));
186         }
187     }
188 
189     /// Returns whether `self` is a superset of `other`.
ensure_superset_of( &self, other: &DescriptorSetDesc, ) -> Result<(), DescriptorSetDescSupersetError>190     pub fn ensure_superset_of(
191         &self,
192         other: &DescriptorSetDesc,
193     ) -> Result<(), DescriptorSetDescSupersetError> {
194         if self.descriptors.len() < other.descriptors.len() {
195             return Err(DescriptorSetDescSupersetError::DescriptorsCountMismatch {
196                 self_num: self.descriptors.len() as u32,
197                 other_num: other.descriptors.len() as u32,
198             });
199         }
200 
201         for binding_num in 0..other.descriptors.len() {
202             let self_desc = self.descriptor(binding_num);
203             let other_desc = self.descriptor(binding_num);
204 
205             match (self_desc, other_desc) {
206                 (Some(mine), Some(other)) => {
207                     if let Err(err) = mine.ensure_superset_of(&other) {
208                         return Err(DescriptorSetDescSupersetError::IncompatibleDescriptors {
209                             error: err,
210                             binding_num: binding_num as u32,
211                         });
212                     }
213                 }
214                 (None, Some(_)) => {
215                     return Err(DescriptorSetDescSupersetError::ExpectedEmptyDescriptor {
216                         binding_num: binding_num as u32,
217                     })
218                 }
219                 _ => (),
220             }
221         }
222 
223         Ok(())
224     }
225 }
226 
227 impl<I> From<I> for DescriptorSetDesc
228 where
229     I: IntoIterator<Item = Option<DescriptorDesc>>,
230 {
231     #[inline]
from(val: I) -> Self232     fn from(val: I) -> Self {
233         DescriptorSetDesc {
234             descriptors: val.into_iter().collect(),
235         }
236     }
237 }
238 
239 /// Contains the exact description of a single descriptor.
240 ///
241 /// > **Note**: You are free to fill a `DescriptorDesc` struct the way you want, but its validity
242 /// > will be checked when you create a pipeline layout, a descriptor set, or when you try to bind
243 /// > a descriptor set.
244 // TODO: add example
245 #[derive(Clone, Debug, PartialEq)]
246 pub struct DescriptorDesc {
247     /// Describes the content and layout of each array element of a descriptor.
248     pub ty: DescriptorDescTy,
249 
250     /// How many array elements this descriptor is made of. The value 0 is invalid and may trigger
251     /// a panic depending on the situation.
252     pub array_count: u32,
253 
254     /// Which shader stages are going to access this descriptor.
255     pub stages: ShaderStages,
256 
257     /// True if the attachment is only ever read by the shader. False if it is also written.
258     pub readonly: bool,
259 }
260 
261 impl DescriptorDesc {
262     /// Checks whether we are a superset of another descriptor.
263     ///
264     /// Returns true if `self` is the same descriptor as `other`, or if `self` is the same as
265     /// `other` but with a larger array elements count and/or more shader stages.
266     ///
267     ///# Example
268     ///```
269     ///use vulkano::descriptor_set::layout::DescriptorDesc;
270     ///use vulkano::descriptor_set::layout::DescriptorDescTy::*;
271     ///use vulkano::pipeline::shader::ShaderStages;
272     ///
273     ///let desc_super = DescriptorDesc{ ty: Sampler, array_count: 2, stages: ShaderStages{
274     ///  vertex: true,
275     ///  tessellation_control: true,
276     ///  tessellation_evaluation: true,
277     ///  geometry: true,
278     ///  fragment: true,
279     ///  compute: true
280     ///}, readonly: false };
281     ///let desc_sub = DescriptorDesc{ ty: Sampler, array_count: 1, stages: ShaderStages{
282     ///  vertex: true,
283     ///  tessellation_control: false,
284     ///  tessellation_evaluation: false,
285     ///  geometry: false,
286     ///  fragment: true,
287     ///  compute: false
288     ///}, readonly: true };
289     ///
290     ///assert_eq!(desc_super.ensure_superset_of(&desc_sub).unwrap(), ());
291     ///
292     ///```
293     #[inline]
ensure_superset_of( &self, other: &DescriptorDesc, ) -> Result<(), DescriptorDescSupersetError>294     pub fn ensure_superset_of(
295         &self,
296         other: &DescriptorDesc,
297     ) -> Result<(), DescriptorDescSupersetError> {
298         self.ty.ensure_superset_of(&other.ty)?;
299         self.stages.ensure_superset_of(&other.stages)?;
300 
301         if self.array_count < other.array_count {
302             return Err(DescriptorDescSupersetError::ArrayTooSmall {
303                 len: self.array_count,
304                 required: other.array_count,
305             });
306         }
307 
308         if self.readonly && !other.readonly {
309             return Err(DescriptorDescSupersetError::MutabilityRequired);
310         }
311 
312         Ok(())
313     }
314 
315     /// Builds a `DescriptorDesc` that is the union of `self` and `other`, if possible.
316     ///
317     /// The returned value will be a superset of both `self` and `other`, or `None` if both were
318     /// `None`.
319     ///
320     /// `Err` is returned if the descriptors are not compatible.
321     ///
322     ///# Example
323     ///```
324     ///use vulkano::descriptor_set::layout::DescriptorDesc;
325     ///use vulkano::descriptor_set::layout::DescriptorDescTy::*;
326     ///use vulkano::pipeline::shader::ShaderStages;
327     ///
328     ///let desc_part1 = DescriptorDesc{ ty: Sampler, array_count: 2, stages: ShaderStages{
329     ///  vertex: true,
330     ///  tessellation_control: true,
331     ///  tessellation_evaluation: false,
332     ///  geometry: true,
333     ///  fragment: false,
334     ///  compute: true
335     ///}, readonly: false };
336     ///
337     ///let desc_part2 = DescriptorDesc{ ty: Sampler, array_count: 1, stages: ShaderStages{
338     ///  vertex: true,
339     ///  tessellation_control: false,
340     ///  tessellation_evaluation: true,
341     ///  geometry: false,
342     ///  fragment: true,
343     ///  compute: true
344     ///}, readonly: true };
345     ///
346     ///let desc_union = DescriptorDesc{ ty: Sampler, array_count: 2, stages: ShaderStages{
347     ///  vertex: true,
348     ///  tessellation_control: true,
349     ///  tessellation_evaluation: true,
350     ///  geometry: true,
351     ///  fragment: true,
352     ///  compute: true
353     ///}, readonly: false };
354     ///
355     ///assert_eq!(DescriptorDesc::union(Some(&desc_part1), Some(&desc_part2)), Ok(Some(desc_union)));
356     ///```
357     #[inline]
union( first: Option<&DescriptorDesc>, second: Option<&DescriptorDesc>, ) -> Result<Option<DescriptorDesc>, ()>358     pub fn union(
359         first: Option<&DescriptorDesc>,
360         second: Option<&DescriptorDesc>,
361     ) -> Result<Option<DescriptorDesc>, ()> {
362         if let (Some(first), Some(second)) = (first, second) {
363             if first.ty != second.ty {
364                 return Err(());
365             }
366 
367             Ok(Some(DescriptorDesc {
368                 ty: first.ty.clone(),
369                 array_count: cmp::max(first.array_count, second.array_count),
370                 stages: first.stages | second.stages,
371                 readonly: first.readonly && second.readonly,
372             }))
373         } else {
374             Ok(first.or(second).cloned())
375         }
376     }
377 
378     /// Returns the pipeline stages and access flags corresponding to the usage of this descriptor.
379     ///
380     /// # Panic
381     ///
382     /// Panics if the type is `Sampler`.
383     ///
pipeline_stages_and_access(&self) -> (PipelineStages, AccessFlags)384     pub fn pipeline_stages_and_access(&self) -> (PipelineStages, AccessFlags) {
385         let stages: PipelineStages = self.stages.into();
386 
387         let access = match self.ty {
388             DescriptorDescTy::Sampler => panic!(),
389             DescriptorDescTy::CombinedImageSampler(_) | DescriptorDescTy::Image(_) => AccessFlags {
390                 shader_read: true,
391                 shader_write: !self.readonly,
392                 ..AccessFlags::none()
393             },
394             DescriptorDescTy::TexelBuffer { .. } => AccessFlags {
395                 shader_read: true,
396                 shader_write: !self.readonly,
397                 ..AccessFlags::none()
398             },
399             DescriptorDescTy::InputAttachment { .. } => AccessFlags {
400                 input_attachment_read: true,
401                 ..AccessFlags::none()
402             },
403             DescriptorDescTy::Buffer(ref buf) => {
404                 if buf.storage {
405                     AccessFlags {
406                         shader_read: true,
407                         shader_write: !self.readonly,
408                         ..AccessFlags::none()
409                     }
410                 } else {
411                     AccessFlags {
412                         uniform_read: true,
413                         ..AccessFlags::none()
414                     }
415                 }
416             }
417         };
418 
419         (stages, access)
420     }
421 }
422 
423 /// Describes the content and layout of each array element of a descriptor.
424 #[derive(Debug, Clone, PartialEq, Eq)]
425 pub enum DescriptorDescTy {
426     Sampler,                                   // TODO: the sampler has some restrictions as well
427     CombinedImageSampler(DescriptorImageDesc), // TODO: the sampler has some restrictions as well
428     Image(DescriptorImageDesc),
429     TexelBuffer {
430         /// If `true`, this describes a storage texel buffer.
431         storage: bool,
432 
433         /// The format of the content, or `None` if the format is unknown. Depending on the
434         /// context, it may be invalid to have a `None` value here. If the format is `Some`, only
435         /// buffer views that have this exact format can be attached to this descriptor.
436         format: Option<Format>,
437     },
438     InputAttachment {
439         /// If `true`, the input attachment is multisampled. Only multisampled images can be
440         /// attached to this descriptor. If `false`, only single-sampled images can be attached.
441         multisampled: bool,
442         array_layers: DescriptorImageDescArray,
443     },
444     Buffer(DescriptorBufferDesc),
445 }
446 
447 impl DescriptorDescTy {
448     /// Returns the type of descriptor.
449     // TODO: add example
ty(&self) -> DescriptorType450     pub fn ty(&self) -> DescriptorType {
451         match *self {
452             DescriptorDescTy::Sampler => DescriptorType::Sampler,
453             DescriptorDescTy::CombinedImageSampler(_) => DescriptorType::CombinedImageSampler,
454             DescriptorDescTy::Image(ref desc) => {
455                 if desc.sampled {
456                     DescriptorType::SampledImage
457                 } else {
458                     DescriptorType::StorageImage
459                 }
460             }
461             DescriptorDescTy::InputAttachment { .. } => DescriptorType::InputAttachment,
462             DescriptorDescTy::Buffer(ref desc) => {
463                 let dynamic = desc.dynamic.unwrap_or(false);
464                 match (desc.storage, dynamic) {
465                     (false, false) => DescriptorType::UniformBuffer,
466                     (true, false) => DescriptorType::StorageBuffer,
467                     (false, true) => DescriptorType::UniformBufferDynamic,
468                     (true, true) => DescriptorType::StorageBufferDynamic,
469                 }
470             }
471             DescriptorDescTy::TexelBuffer { storage, .. } => {
472                 if storage {
473                     DescriptorType::StorageTexelBuffer
474                 } else {
475                     DescriptorType::UniformTexelBuffer
476                 }
477             }
478         }
479     }
480 
481     /// Checks whether we are a superset of another descriptor type.
482     // TODO: add example
483     #[inline]
ensure_superset_of( &self, other: &DescriptorDescTy, ) -> Result<(), DescriptorDescSupersetError>484     pub fn ensure_superset_of(
485         &self,
486         other: &DescriptorDescTy,
487     ) -> Result<(), DescriptorDescSupersetError> {
488         match (self, other) {
489             (&DescriptorDescTy::Sampler, &DescriptorDescTy::Sampler) => Ok(()),
490 
491             (
492                 &DescriptorDescTy::CombinedImageSampler(ref me),
493                 &DescriptorDescTy::CombinedImageSampler(ref other),
494             ) => me.ensure_superset_of(other),
495 
496             (&DescriptorDescTy::Image(ref me), &DescriptorDescTy::Image(ref other)) => {
497                 me.ensure_superset_of(other)
498             }
499 
500             (
501                 &DescriptorDescTy::InputAttachment {
502                     multisampled: me_multisampled,
503                     array_layers: me_array_layers,
504                 },
505                 &DescriptorDescTy::InputAttachment {
506                     multisampled: other_multisampled,
507                     array_layers: other_array_layers,
508                 },
509             ) => {
510                 if me_multisampled != other_multisampled {
511                     return Err(DescriptorDescSupersetError::MultisampledMismatch {
512                         provided: me_multisampled,
513                         expected: other_multisampled,
514                     });
515                 }
516 
517                 if me_array_layers != other_array_layers {
518                     return Err(DescriptorDescSupersetError::IncompatibleArrayLayers {
519                         provided: me_array_layers,
520                         required: other_array_layers,
521                     });
522                 }
523 
524                 Ok(())
525             }
526 
527             (&DescriptorDescTy::Buffer(ref me), &DescriptorDescTy::Buffer(ref other)) => {
528                 if me.storage != other.storage {
529                     return Err(DescriptorDescSupersetError::TypeMismatch);
530                 }
531 
532                 match (me.dynamic, other.dynamic) {
533                     (Some(_), None) => Ok(()),
534                     (Some(m), Some(o)) => {
535                         if m == o {
536                             Ok(())
537                         } else {
538                             Err(DescriptorDescSupersetError::TypeMismatch)
539                         }
540                     }
541                     (None, None) => Ok(()),
542                     (None, Some(_)) => Err(DescriptorDescSupersetError::TypeMismatch),
543                 }
544             }
545 
546             (
547                 &DescriptorDescTy::TexelBuffer {
548                     storage: me_storage,
549                     format: me_format,
550                 },
551                 &DescriptorDescTy::TexelBuffer {
552                     storage: other_storage,
553                     format: other_format,
554                 },
555             ) => {
556                 if me_storage != other_storage {
557                     return Err(DescriptorDescSupersetError::TypeMismatch);
558                 }
559 
560                 match (me_format, other_format) {
561                     (Some(_), None) => Ok(()),
562                     (Some(m), Some(o)) => {
563                         if m == o {
564                             Ok(())
565                         } else {
566                             Err(DescriptorDescSupersetError::FormatMismatch {
567                                 provided: Some(m),
568                                 expected: o,
569                             })
570                         }
571                     }
572                     (None, None) => Ok(()),
573                     (None, Some(a)) => Err(DescriptorDescSupersetError::FormatMismatch {
574                         provided: Some(a),
575                         expected: a,
576                     }),
577                 }
578             }
579 
580             // Any other combination is invalid.
581             _ => Err(DescriptorDescSupersetError::TypeMismatch),
582         }
583     }
584 }
585 
586 /// Additional description for descriptors that contain images.
587 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
588 pub struct DescriptorImageDesc {
589     /// If `true`, the image can be sampled by the shader. Only images that were created with the
590     /// `sampled` usage can be attached to the descriptor.
591     pub sampled: bool,
592     /// The kind of image: one-dimensional, two-dimensional, three-dimensional, or cube.
593     pub dimensions: DescriptorImageDescDimensions,
594     /// The format of the image, or `None` if the format is unknown. If `Some`, only images with
595     /// exactly that format can be attached.
596     pub format: Option<Format>,
597     /// True if the image is multisampled.
598     pub multisampled: bool,
599     /// Whether the descriptor contains one or more array layers of an image.
600     pub array_layers: DescriptorImageDescArray,
601 }
602 
603 impl DescriptorImageDesc {
604     /// Checks whether we are a superset of another image.
605     // TODO: add example
606     #[inline]
ensure_superset_of( &self, other: &DescriptorImageDesc, ) -> Result<(), DescriptorDescSupersetError>607     pub fn ensure_superset_of(
608         &self,
609         other: &DescriptorImageDesc,
610     ) -> Result<(), DescriptorDescSupersetError> {
611         if self.dimensions != other.dimensions {
612             return Err(DescriptorDescSupersetError::DimensionsMismatch {
613                 provided: self.dimensions,
614                 expected: other.dimensions,
615             });
616         }
617 
618         if self.multisampled != other.multisampled {
619             return Err(DescriptorDescSupersetError::MultisampledMismatch {
620                 provided: self.multisampled,
621                 expected: other.multisampled,
622             });
623         }
624 
625         match (self.format, other.format) {
626             (Some(a), Some(b)) => {
627                 if a != b {
628                     return Err(DescriptorDescSupersetError::FormatMismatch {
629                         provided: Some(a),
630                         expected: b,
631                     });
632                 }
633             }
634             (Some(_), None) => (),
635             (None, None) => (),
636             (None, Some(a)) => {
637                 return Err(DescriptorDescSupersetError::FormatMismatch {
638                     provided: None,
639                     expected: a,
640                 });
641             }
642         };
643 
644         match (self.array_layers, other.array_layers) {
645             (DescriptorImageDescArray::NonArrayed, DescriptorImageDescArray::NonArrayed) => (),
646             (
647                 DescriptorImageDescArray::Arrayed { max_layers: my_max },
648                 DescriptorImageDescArray::Arrayed {
649                     max_layers: other_max,
650                 },
651             ) => {
652                 match (my_max, other_max) {
653                     (Some(m), Some(o)) => {
654                         if m < o {
655                             return Err(DescriptorDescSupersetError::IncompatibleArrayLayers {
656                                 provided: DescriptorImageDescArray::Arrayed { max_layers: my_max },
657                                 required: DescriptorImageDescArray::Arrayed {
658                                     max_layers: other_max,
659                                 },
660                             });
661                         }
662                     }
663                     (Some(_), None) => (),
664                     (None, Some(m)) => {
665                         return Err(DescriptorDescSupersetError::IncompatibleArrayLayers {
666                             provided: DescriptorImageDescArray::Arrayed { max_layers: my_max },
667                             required: DescriptorImageDescArray::Arrayed {
668                                 max_layers: other_max,
669                             },
670                         });
671                     }
672                     (None, None) => (), // TODO: is this correct?
673                 };
674             }
675             (a, b) => {
676                 return Err(DescriptorDescSupersetError::IncompatibleArrayLayers {
677                     provided: a,
678                     required: b,
679                 })
680             }
681         };
682 
683         Ok(())
684     }
685 }
686 
687 // TODO: documentation
688 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
689 pub enum DescriptorImageDescArray {
690     NonArrayed,
691     Arrayed { max_layers: Option<u32> },
692 }
693 
694 // TODO: documentation
695 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
696 pub enum DescriptorImageDescDimensions {
697     OneDimensional,
698     TwoDimensional,
699     ThreeDimensional,
700     Cube,
701 }
702 
703 impl DescriptorImageDescDimensions {
704     /// Builds the `DescriptorImageDescDimensions` that corresponds to the view type.
705     #[inline]
from_image_view_type(ty: ImageViewType) -> DescriptorImageDescDimensions706     pub fn from_image_view_type(ty: ImageViewType) -> DescriptorImageDescDimensions {
707         match ty {
708             ImageViewType::Dim1d => DescriptorImageDescDimensions::OneDimensional,
709             ImageViewType::Dim1dArray => DescriptorImageDescDimensions::OneDimensional,
710             ImageViewType::Dim2d => DescriptorImageDescDimensions::TwoDimensional,
711             ImageViewType::Dim2dArray => DescriptorImageDescDimensions::TwoDimensional,
712             ImageViewType::Dim3d => DescriptorImageDescDimensions::ThreeDimensional,
713             ImageViewType::Cubemap => DescriptorImageDescDimensions::Cube,
714             ImageViewType::CubemapArray => DescriptorImageDescDimensions::Cube,
715         }
716     }
717 }
718 
719 /// Additional description for descriptors that contain buffers.
720 #[derive(Debug, Clone, PartialEq, Eq)]
721 pub struct DescriptorBufferDesc {
722     /// If `true`, this buffer is a dynamic buffer. Assumes false if `None`.
723     pub dynamic: Option<bool>,
724     /// If `true`, this buffer is a storage buffer.
725     pub storage: bool,
726 }
727 
728 /// Describes what kind of resource may later be bound to a descriptor.
729 ///
730 /// This is mostly the same as a `DescriptorDescTy` but with less precise information.
731 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
732 #[repr(i32)]
733 pub enum DescriptorType {
734     Sampler = ash::vk::DescriptorType::SAMPLER.as_raw(),
735     CombinedImageSampler = ash::vk::DescriptorType::COMBINED_IMAGE_SAMPLER.as_raw(),
736     SampledImage = ash::vk::DescriptorType::SAMPLED_IMAGE.as_raw(),
737     StorageImage = ash::vk::DescriptorType::STORAGE_IMAGE.as_raw(),
738     UniformTexelBuffer = ash::vk::DescriptorType::UNIFORM_TEXEL_BUFFER.as_raw(),
739     StorageTexelBuffer = ash::vk::DescriptorType::STORAGE_TEXEL_BUFFER.as_raw(),
740     UniformBuffer = ash::vk::DescriptorType::UNIFORM_BUFFER.as_raw(),
741     StorageBuffer = ash::vk::DescriptorType::STORAGE_BUFFER.as_raw(),
742     UniformBufferDynamic = ash::vk::DescriptorType::UNIFORM_BUFFER_DYNAMIC.as_raw(),
743     StorageBufferDynamic = ash::vk::DescriptorType::STORAGE_BUFFER_DYNAMIC.as_raw(),
744     InputAttachment = ash::vk::DescriptorType::INPUT_ATTACHMENT.as_raw(),
745 }
746 
747 impl From<DescriptorType> for ash::vk::DescriptorType {
748     #[inline]
from(val: DescriptorType) -> Self749     fn from(val: DescriptorType) -> Self {
750         Self::from_raw(val as i32)
751     }
752 }
753 
754 /// Error when checking whether a descriptor set is a superset of another one.
755 #[derive(Debug, Clone, PartialEq, Eq)]
756 pub enum DescriptorSetDescSupersetError {
757     /// There are more descriptors in the child than in the parent layout.
758     DescriptorsCountMismatch { self_num: u32, other_num: u32 },
759 
760     /// Expected an empty descriptor, but got something instead.
761     ExpectedEmptyDescriptor { binding_num: u32 },
762 
763     /// Two descriptors are incompatible.
764     IncompatibleDescriptors {
765         error: DescriptorDescSupersetError,
766         binding_num: u32,
767     },
768 }
769 
770 impl error::Error for DescriptorSetDescSupersetError {
771     #[inline]
source(&self) -> Option<&(dyn error::Error + 'static)>772     fn source(&self) -> Option<&(dyn error::Error + 'static)> {
773         match *self {
774             DescriptorSetDescSupersetError::IncompatibleDescriptors { ref error, .. } => {
775                 Some(error)
776             }
777             _ => None,
778         }
779     }
780 }
781 
782 impl fmt::Display for DescriptorSetDescSupersetError {
783     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>784     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
785         write!(
786             fmt,
787             "{}",
788             match *self {
789                 DescriptorSetDescSupersetError::DescriptorsCountMismatch { .. } => {
790                     "there are more descriptors in the child than in the parent layout"
791                 }
792                 DescriptorSetDescSupersetError::ExpectedEmptyDescriptor { .. } => {
793                     "expected an empty descriptor, but got something instead"
794                 }
795                 DescriptorSetDescSupersetError::IncompatibleDescriptors { .. } => {
796                     "two descriptors are incompatible"
797                 }
798             }
799         )
800     }
801 }
802 
803 /// Error when checking whether a descriptor is a superset of another one.
804 #[derive(Debug, Clone, PartialEq, Eq)]
805 pub enum DescriptorDescSupersetError {
806     /// The number of array elements of the descriptor is smaller than expected.
807     ArrayTooSmall {
808         len: u32,
809         required: u32,
810     },
811 
812     DimensionsMismatch {
813         provided: DescriptorImageDescDimensions,
814         expected: DescriptorImageDescDimensions,
815     },
816 
817     FormatMismatch {
818         provided: Option<Format>,
819         expected: Format,
820     },
821 
822     IncompatibleArrayLayers {
823         provided: DescriptorImageDescArray,
824         required: DescriptorImageDescArray,
825     },
826 
827     MultisampledMismatch {
828         provided: bool,
829         expected: bool,
830     },
831 
832     /// The descriptor is marked as read-only, but the other is not.
833     MutabilityRequired,
834 
835     /// The shader stages are not a superset of one another.
836     ShaderStagesNotSuperset,
837 
838     /// The descriptor type doesn't match the type of the other descriptor.
839     TypeMismatch,
840 }
841 
842 impl error::Error for DescriptorDescSupersetError {}
843 
844 impl fmt::Display for DescriptorDescSupersetError {
845     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>846     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
847         write!(
848             fmt,
849             "{}",
850             match *self {
851                 DescriptorDescSupersetError::ArrayTooSmall { .. } => {
852                     "the number of array elements of the descriptor is smaller than expected"
853                 }
854                 DescriptorDescSupersetError::TypeMismatch => {
855                     "the descriptor type doesn't match the type of the other descriptor"
856                 }
857                 DescriptorDescSupersetError::MutabilityRequired => {
858                     "the descriptor is marked as read-only, but the other is not"
859                 }
860                 DescriptorDescSupersetError::ShaderStagesNotSuperset => {
861                     "the shader stages are not a superset of one another"
862                 }
863                 DescriptorDescSupersetError::DimensionsMismatch { .. } => {
864                     "mismatch between the dimensions of the two descriptors"
865                 }
866                 DescriptorDescSupersetError::FormatMismatch { .. } => {
867                     "mismatch between the format of the two descriptors"
868                 }
869                 DescriptorDescSupersetError::MultisampledMismatch { .. } => {
870                     "mismatch between whether the descriptors are multisampled"
871                 }
872                 DescriptorDescSupersetError::IncompatibleArrayLayers { .. } => {
873                     "the array layers of the descriptors aren't compatible"
874                 }
875             }
876         )
877     }
878 }
879 
880 impl From<ShaderStagesSupersetError> for DescriptorDescSupersetError {
881     #[inline]
from(err: ShaderStagesSupersetError) -> DescriptorDescSupersetError882     fn from(err: ShaderStagesSupersetError) -> DescriptorDescSupersetError {
883         match err {
884             ShaderStagesSupersetError::NotSuperset => {
885                 DescriptorDescSupersetError::ShaderStagesNotSuperset
886             }
887         }
888     }
889 }
890