// Copyright (c) 2017 The vulkano developers // Licensed under the Apache License, Version 2.0 // or the MIT // license , // 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