      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109

    // Copyright (c) 2017 The vulkano developers
    // Licensed under the Apache License, Version 2.0
    // <LICENSE-APACHE or
    // http://www.apache.org/licenses/LICENSE-2.0> or the MIT
    // license <LICENSE-MIT or http://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 descriptor::descriptor::DescriptorDescSupersetError;
    use descriptor::descriptor_set::DescriptorSetsCollection;
    use descriptor::pipeline_layout::PipelineLayoutDesc;

    /// Checks whether descriptor sets are compatible with the pipeline.
    pub fn check_descriptor_sets_validity<Pl, D>(pipeline: &Pl, descriptor_sets: &D)
                                                 -> Result<(), CheckDescriptorSetsValidityError>
        where Pl: ?Sized + PipelineLayoutDesc,
              D: ?Sized + DescriptorSetsCollection
    {
        // 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 in 0 .. pipeline.num_sets() {
            for binding_num in 0 .. pipeline.num_bindings_in_set(set_num).unwrap_or(0) {
                let set_desc = descriptor_sets.descriptor(set_num, binding_num);
                let pipeline_desc = pipeline.descriptor(set_num, binding_num);

                let (set_desc, pipeline_desc) = match (set_desc, pipeline_desc) {
                    (Some(s), Some(p)) => (s, p),
                    (None, Some(_)) =>
                        return Err(CheckDescriptorSetsValidityError::MissingDescriptor {
                                       set_num: set_num,
                                       binding_num: binding_num,
                                   }),
                    (Some(_), None) => continue,
                    (None, None) => continue,
                };

                if let Err(err) = set_desc.is_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 description(&self) -> &str {
            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"
                },
            }
        }

        #[inline]
        fn cause(&self) -> Option<&dyn error::Error> {
            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, "{}", error::Error::description(self))
        }
    }

    // TODO: tests

# Help

## Keyboard Shortcuts

`?`
  Show this help dialog
`S`
  Focus the search field
`↑`
  Move up in search results
`↓`
  Move down in search results
`↹`
  Switch tab
`⏎`
  Go to active search result
`+`
  Expand all sections
`-`
  Collapse all sections

## Search Tricks

Prefix searches with a type followed by a colon (e.g., `fn:`) to restrict the search to a given type.

Accepted types are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`.

Search functions by type signature (e.g., `vec -> usize` or `* -> vec`)

Search multiple things at once by splitting your query with comma (e.g., `str,u8` or `String,struct:Vec,test`)