aboutsummaryrefslogtreecommitdiff
path: root/src/command_buffer/validity/descriptor_sets.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/command_buffer/validity/descriptor_sets.rs')
-rw-r--r--src/command_buffer/validity/descriptor_sets.rs109
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