diff options
Diffstat (limited to 'src/command_buffer/validity/descriptor_sets.rs')
-rw-r--r-- | src/command_buffer/validity/descriptor_sets.rs | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/command_buffer/validity/descriptor_sets.rs b/src/command_buffer/validity/descriptor_sets.rs new file mode 100644 index 0000000..227101b --- /dev/null +++ b/src/command_buffer/validity/descriptor_sets.rs @@ -0,0 +1,109 @@ +// Copyright (c) 2017 The vulkano developers +// Licensed under the Apache License, Version 2.0 +// <LICENSE-APACHE or +// https://www.apache.org/licenses/LICENSE-2.0> or the MIT +// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, +// at your option. All files in the project carrying such +// notice may not be copied, modified, or distributed except +// according to those terms. + +use std::error; +use std::fmt; + +use crate::descriptor_set::layout::DescriptorDescSupersetError; +use crate::descriptor_set::DescriptorSetWithOffsets; +use crate::pipeline::layout::PipelineLayout; + +/// Checks whether descriptor sets are compatible with the pipeline. +pub fn check_descriptor_sets_validity( + pipeline_layout: &PipelineLayout, + descriptor_sets: &[DescriptorSetWithOffsets], +) -> Result<(), CheckDescriptorSetsValidityError> { + // What's important is not that the pipeline layout and the descriptor sets *match*. Instead + // what's important is that the descriptor sets are a superset of the pipeline layout. It's not + // a problem if the descriptor sets provide more elements than expected. + + for (set_num, set) in pipeline_layout.descriptor_set_layouts().iter().enumerate() { + for (binding_num, pipeline_desc) in + (0..set.num_bindings()).filter_map(|i| set.descriptor(i).map(|d| (i, d))) + { + let set_desc = descriptor_sets + .get(set_num) + .and_then(|so| so.as_ref().0.layout().descriptor(binding_num)); + + let set_desc = match set_desc { + Some(s) => s, + None => { + return Err(CheckDescriptorSetsValidityError::MissingDescriptor { + set_num: set_num, + binding_num: binding_num, + }) + } + }; + + if let Err(err) = set_desc.ensure_superset_of(&pipeline_desc) { + return Err(CheckDescriptorSetsValidityError::IncompatibleDescriptor { + error: err, + set_num: set_num, + binding_num: binding_num, + }); + } + } + } + + Ok(()) +} + +/// Error that can happen when checking descriptor sets validity. +#[derive(Debug, Clone)] +pub enum CheckDescriptorSetsValidityError { + /// A descriptor is missing in the descriptor sets that were provided. + MissingDescriptor { + /// The index of the set of the descriptor. + set_num: usize, + /// The binding number of the descriptor. + binding_num: usize, + }, + + /// A descriptor in the provided sets is not compatible with what is expected. + IncompatibleDescriptor { + /// The reason why the two descriptors aren't compatible. + error: DescriptorDescSupersetError, + /// The index of the set of the descriptor. + set_num: usize, + /// The binding number of the descriptor. + binding_num: usize, + }, +} + +impl error::Error for CheckDescriptorSetsValidityError { + #[inline] + fn source(&self) -> Option<&(dyn error::Error + 'static)> { + match *self { + CheckDescriptorSetsValidityError::IncompatibleDescriptor { ref error, .. } => { + Some(error) + } + _ => None, + } + } +} + +impl fmt::Display for CheckDescriptorSetsValidityError { + #[inline] + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + fmt, + "{}", + match *self { + CheckDescriptorSetsValidityError::MissingDescriptor { .. } => { + "a descriptor is missing in the descriptor sets that were provided" + } + CheckDescriptorSetsValidityError::IncompatibleDescriptor { .. } => { + "a descriptor in the provided sets is not compatible with what is expected" + } + } + ) + } +} + +// TODO: tests |