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 use std::error;
11 use std::fmt;
12
13 use crate::descriptor_set::layout::DescriptorDescSupersetError;
14 use crate::descriptor_set::DescriptorSetWithOffsets;
15 use crate::pipeline::layout::PipelineLayout;
16
17 /// Checks whether descriptor sets are compatible with the pipeline.
check_descriptor_sets_validity( pipeline_layout: &PipelineLayout, descriptor_sets: &[DescriptorSetWithOffsets], ) -> Result<(), CheckDescriptorSetsValidityError>18 pub fn check_descriptor_sets_validity(
19 pipeline_layout: &PipelineLayout,
20 descriptor_sets: &[DescriptorSetWithOffsets],
21 ) -> Result<(), CheckDescriptorSetsValidityError> {
22 // What's important is not that the pipeline layout and the descriptor sets *match*. Instead
23 // what's important is that the descriptor sets are a superset of the pipeline layout. It's not
24 // a problem if the descriptor sets provide more elements than expected.
25
26 for (set_num, set) in pipeline_layout.descriptor_set_layouts().iter().enumerate() {
27 for (binding_num, pipeline_desc) in
28 (0..set.num_bindings()).filter_map(|i| set.descriptor(i).map(|d| (i, d)))
29 {
30 let set_desc = descriptor_sets
31 .get(set_num)
32 .and_then(|so| so.as_ref().0.layout().descriptor(binding_num));
33
34 let set_desc = match set_desc {
35 Some(s) => s,
36 None => {
37 return Err(CheckDescriptorSetsValidityError::MissingDescriptor {
38 set_num: set_num,
39 binding_num: binding_num,
40 })
41 }
42 };
43
44 if let Err(err) = set_desc.ensure_superset_of(&pipeline_desc) {
45 return Err(CheckDescriptorSetsValidityError::IncompatibleDescriptor {
46 error: err,
47 set_num: set_num,
48 binding_num: binding_num,
49 });
50 }
51 }
52 }
53
54 Ok(())
55 }
56
57 /// Error that can happen when checking descriptor sets validity.
58 #[derive(Debug, Clone)]
59 pub enum CheckDescriptorSetsValidityError {
60 /// A descriptor is missing in the descriptor sets that were provided.
61 MissingDescriptor {
62 /// The index of the set of the descriptor.
63 set_num: usize,
64 /// The binding number of the descriptor.
65 binding_num: usize,
66 },
67
68 /// A descriptor in the provided sets is not compatible with what is expected.
69 IncompatibleDescriptor {
70 /// The reason why the two descriptors aren't compatible.
71 error: DescriptorDescSupersetError,
72 /// The index of the set of the descriptor.
73 set_num: usize,
74 /// The binding number of the descriptor.
75 binding_num: usize,
76 },
77 }
78
79 impl error::Error for CheckDescriptorSetsValidityError {
80 #[inline]
source(&self) -> Option<&(dyn error::Error + 'static)>81 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
82 match *self {
83 CheckDescriptorSetsValidityError::IncompatibleDescriptor { ref error, .. } => {
84 Some(error)
85 }
86 _ => None,
87 }
88 }
89 }
90
91 impl fmt::Display for CheckDescriptorSetsValidityError {
92 #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>93 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
94 write!(
95 fmt,
96 "{}",
97 match *self {
98 CheckDescriptorSetsValidityError::MissingDescriptor { .. } => {
99 "a descriptor is missing in the descriptor sets that were provided"
100 }
101 CheckDescriptorSetsValidityError::IncompatibleDescriptor { .. } => {
102 "a descriptor in the provided sets is not compatible with what is expected"
103 }
104 }
105 )
106 }
107 }
108
109 // TODO: tests
110