Home | History | Annotate | Download | only in layers
      1 /* Copyright (c) 2015-2016 The Khronos Group Inc.
      2  * Copyright (c) 2015-2016 Valve Corporation
      3  * Copyright (c) 2015-2016 LunarG, Inc.
      4  * Copyright (C) 2015-2016 Google Inc.
      5  *
      6  * Licensed under the Apache License, Version 2.0 (the "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  *
     18  * Author: Tobin Ehlis <tobine (at) google.com>
     19  */
     20 #ifndef CORE_VALIDATION_DESCRIPTOR_SETS_H_
     21 #define CORE_VALIDATION_DESCRIPTOR_SETS_H_
     22 
     23 // Check for noexcept support
     24 #ifndef NOEXCEPT
     25 #if defined(__clang__)
     26 #if __has_feature(cxx_noexcept)
     27 #define HAS_NOEXCEPT
     28 #endif
     29 #else
     30 #if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46
     31 #define HAS_NOEXCEPT
     32 #else
     33 #if defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026 && defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS
     34 #define HAS_NOEXCEPT
     35 #endif
     36 #endif
     37 #endif
     38 
     39 #ifdef HAS_NOEXCEPT
     40 #define NOEXCEPT noexcept
     41 #else
     42 #define NOEXCEPT
     43 #endif
     44 #endif
     45 
     46 #include "core_validation_error_enums.h"
     47 #include "vk_validation_error_messages.h"
     48 #include "core_validation_types.h"
     49 #include "vk_layer_logging.h"
     50 #include "vk_layer_utils.h"
     51 #include "vk_safe_struct.h"
     52 #include "vulkan/vk_layer.h"
     53 #include <map>
     54 #include <memory>
     55 #include <unordered_map>
     56 #include <unordered_set>
     57 #include <vector>
     58 
     59 // Descriptor Data structures
     60 
     61 /*
     62  * DescriptorSetLayout class
     63  *
     64  * Overview - This class encapsulates the Vulkan VkDescriptorSetLayout data (layout).
     65  *   A layout consists of some number of bindings, each of which has a binding#, a
     66  *   type, descriptor count, stage flags, and pImmutableSamplers.
     67  *
     68  * Index vs Binding - A layout is created with an array of VkDescriptorSetLayoutBinding
     69  *  where each array index will have a corresponding binding# that is defined in that struct.
     70  *  This class, therefore, provides utility functions where you can retrieve data for
     71  *  layout bindings based on either the original index into the pBindings array, or based
     72  *  on the binding#.
     73  *  Typically if you want to cover all of the bindings in a layout, you can do that by
     74  *   iterating over GetBindingCount() bindings and using the Get*FromIndex() functions.
     75  *  Otherwise, you can use the Get*FromBinding() functions to just grab binding info
     76  *   for a particular binding#.
     77  *
     78  * Global Index - The "Index" referenced above is the index into the original pBindings
     79  *  array. So there are as many indices as there are bindings.
     80  *  This class also has the concept of a Global Index. For the global index functions,
     81  *  there are as many global indices as there are descriptors in the layout.
     82  *  For the global index, consider all of the bindings to be a flat array where
     83  *  descriptor 0 of pBinding[0] is index 0 and each descriptor in the layout increments
     84  *  from there. So if pBinding[0] in this example had descriptorCount of 10, then
     85  *  the GlobalStartIndex of pBinding[1] will be 10 where 0-9 are the global indices
     86  *  for pBinding[0].
     87  */
     88 namespace cvdescriptorset {
     89 class DescriptorSetLayout {
     90   public:
     91     // Constructors and destructor
     92     DescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo *p_create_info, const VkDescriptorSetLayout layout);
     93     // Validate create info - should be called prior to creation
     94     static bool ValidateCreateInfo(debug_report_data *, const VkDescriptorSetLayoutCreateInfo *);
     95     // Straightforward Get functions
     96     VkDescriptorSetLayout GetDescriptorSetLayout() const { return layout_; };
     97     uint32_t GetTotalDescriptorCount() const { return descriptor_count_; };
     98     uint32_t GetDynamicDescriptorCount() const { return dynamic_descriptor_count_; };
     99     uint32_t GetBindingCount() const { return binding_count_; };
    100     // Fill passed-in set with bindings
    101     void FillBindingSet(std::unordered_set<uint32_t> *) const;
    102     // Return true if given binding is present in this layout
    103     bool HasBinding(const uint32_t binding) const { return binding_to_index_map_.count(binding) > 0; };
    104     // Return true if this layout is compatible with passed in layout,
    105     //   else return false and update error_msg with description of incompatibility
    106     bool IsCompatible(const DescriptorSetLayout *, std::string *) const;
    107     // Return true if binding 1 beyond given exists and has same type, stageFlags & immutable sampler use
    108     bool IsNextBindingConsistent(const uint32_t) const;
    109     // Various Get functions that can either be passed a binding#, which will
    110     //  be automatically translated into the appropriate index from the original
    111     //  pBindings array, or the index# can be passed in directly
    112     VkDescriptorSetLayoutBinding const *GetDescriptorSetLayoutBindingPtrFromBinding(const uint32_t) const;
    113     VkDescriptorSetLayoutBinding const *GetDescriptorSetLayoutBindingPtrFromIndex(const uint32_t) const;
    114     uint32_t GetDescriptorCountFromBinding(const uint32_t) const;
    115     uint32_t GetDescriptorCountFromIndex(const uint32_t) const;
    116     VkDescriptorType GetTypeFromBinding(const uint32_t) const;
    117     VkDescriptorType GetTypeFromIndex(const uint32_t) const;
    118     VkDescriptorType GetTypeFromGlobalIndex(const uint32_t) const;
    119     VkShaderStageFlags GetStageFlagsFromBinding(const uint32_t) const;
    120     VkSampler const *GetImmutableSamplerPtrFromBinding(const uint32_t) const;
    121     VkSampler const *GetImmutableSamplerPtrFromIndex(const uint32_t) const;
    122     // For a particular binding, get the global index
    123     //  These calls should be guarded by a call to "HasBinding(binding)" to verify that the given binding exists
    124     uint32_t GetGlobalStartIndexFromBinding(const uint32_t) const;
    125     uint32_t GetGlobalEndIndexFromBinding(const uint32_t) const;
    126     // For a particular binding starting at offset and having update_count descriptors
    127     //  updated, verify that for any binding boundaries crossed, the update is consistent
    128     bool VerifyUpdateConsistency(uint32_t, uint32_t, uint32_t, const char *, const VkDescriptorSet, std::string *) const;
    129 
    130   private:
    131     VkDescriptorSetLayout layout_;
    132     std::unordered_map<uint32_t, uint32_t> binding_to_index_map_;
    133     std::unordered_map<uint32_t, uint32_t> binding_to_global_start_index_map_;
    134     std::unordered_map<uint32_t, uint32_t> binding_to_global_end_index_map_;
    135     // VkDescriptorSetLayoutCreateFlags flags_;
    136     uint32_t binding_count_; // # of bindings in this layout
    137     std::vector<safe_VkDescriptorSetLayoutBinding> bindings_;
    138     uint32_t descriptor_count_; // total # descriptors in this layout
    139     uint32_t dynamic_descriptor_count_;
    140 };
    141 
    142 /*
    143  * Descriptor classes
    144  *  Descriptor is an abstract base class from which 5 separate descriptor types are derived.
    145  *   This allows the WriteUpdate() and CopyUpdate() operations to be specialized per
    146  *   descriptor type, but all descriptors in a set can be accessed via the common Descriptor*.
    147  */
    148 
    149 // Slightly broader than type, each c++ "class" will has a corresponding "DescriptorClass"
    150 enum DescriptorClass { PlainSampler, ImageSampler, Image, TexelBuffer, GeneralBuffer };
    151 
    152 class Descriptor {
    153   public:
    154     virtual ~Descriptor(){};
    155     virtual void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) = 0;
    156     virtual void CopyUpdate(const Descriptor *) = 0;
    157     // Create binding between resources of this descriptor and given cb_node
    158     virtual void BindCommandBuffer(const core_validation::layer_data *, GLOBAL_CB_NODE *) = 0;
    159     virtual DescriptorClass GetClass() const { return descriptor_class; };
    160     // Special fast-path check for SamplerDescriptors that are immutable
    161     virtual bool IsImmutableSampler() const { return false; };
    162     // Check for dynamic descriptor type
    163     virtual bool IsDynamic() const { return false; };
    164     // Check for storage descriptor type
    165     virtual bool IsStorage() const { return false; };
    166     bool updated; // Has descriptor been updated?
    167     DescriptorClass descriptor_class;
    168 };
    169 // Shared helper functions - These are useful because the shared sampler image descriptor type
    170 //  performs common functions with both sampler and image descriptors so they can share their common functions
    171 bool ValidateSampler(const VkSampler, const core_validation::layer_data *);
    172 bool ValidateImageUpdate(VkImageView, VkImageLayout, VkDescriptorType, const core_validation::layer_data *,
    173                          UNIQUE_VALIDATION_ERROR_CODE *, std::string *);
    174 
    175 class SamplerDescriptor : public Descriptor {
    176   public:
    177     SamplerDescriptor();
    178     SamplerDescriptor(const VkSampler *);
    179     void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
    180     void CopyUpdate(const Descriptor *) override;
    181     void BindCommandBuffer(const core_validation::layer_data *, GLOBAL_CB_NODE *) override;
    182     virtual bool IsImmutableSampler() const override { return immutable_; };
    183     VkSampler GetSampler() const { return sampler_; }
    184 
    185   private:
    186     // bool ValidateSampler(const VkSampler) const;
    187     VkSampler sampler_;
    188     bool immutable_;
    189 };
    190 
    191 class ImageSamplerDescriptor : public Descriptor {
    192   public:
    193     ImageSamplerDescriptor();
    194     ImageSamplerDescriptor(const VkSampler *);
    195     void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
    196     void CopyUpdate(const Descriptor *) override;
    197     void BindCommandBuffer(const core_validation::layer_data *, GLOBAL_CB_NODE *) override;
    198     virtual bool IsImmutableSampler() const override { return immutable_; };
    199     VkSampler GetSampler() const { return sampler_; }
    200     VkImageView GetImageView() const { return image_view_; }
    201     VkImageLayout GetImageLayout() const { return image_layout_; }
    202 
    203   private:
    204     VkSampler sampler_;
    205     bool immutable_;
    206     VkImageView image_view_;
    207     VkImageLayout image_layout_;
    208 };
    209 
    210 class ImageDescriptor : public Descriptor {
    211   public:
    212     ImageDescriptor(const VkDescriptorType);
    213     void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
    214     void CopyUpdate(const Descriptor *) override;
    215     void BindCommandBuffer(const core_validation::layer_data *, GLOBAL_CB_NODE *) override;
    216     virtual bool IsStorage() const override { return storage_; }
    217     VkImageView GetImageView() const { return image_view_; }
    218     VkImageLayout GetImageLayout() const { return image_layout_; }
    219 
    220   private:
    221     bool storage_;
    222     VkImageView image_view_;
    223     VkImageLayout image_layout_;
    224 };
    225 
    226 class TexelDescriptor : public Descriptor {
    227   public:
    228     TexelDescriptor(const VkDescriptorType);
    229     void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
    230     void CopyUpdate(const Descriptor *) override;
    231     void BindCommandBuffer(const core_validation::layer_data *, GLOBAL_CB_NODE *) override;
    232     virtual bool IsStorage() const override { return storage_; }
    233     VkBufferView GetBufferView() const { return buffer_view_; }
    234 
    235   private:
    236     VkBufferView buffer_view_;
    237     bool storage_;
    238 };
    239 
    240 class BufferDescriptor : public Descriptor {
    241   public:
    242     BufferDescriptor(const VkDescriptorType);
    243     void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
    244     void CopyUpdate(const Descriptor *) override;
    245     void BindCommandBuffer(const core_validation::layer_data *, GLOBAL_CB_NODE *) override;
    246     virtual bool IsDynamic() const override { return dynamic_; }
    247     virtual bool IsStorage() const override { return storage_; }
    248     VkBuffer GetBuffer() const { return buffer_; }
    249     VkDeviceSize GetOffset() const { return offset_; }
    250     VkDeviceSize GetRange() const { return range_; }
    251 
    252   private:
    253     bool storage_;
    254     bool dynamic_;
    255     VkBuffer buffer_;
    256     VkDeviceSize offset_;
    257     VkDeviceSize range_;
    258 };
    259 // Structs to contain common elements that need to be shared between Validate* and Perform* calls below
    260 struct AllocateDescriptorSetsData {
    261     uint32_t required_descriptors_by_type[VK_DESCRIPTOR_TYPE_RANGE_SIZE];
    262     std::vector<cvdescriptorset::DescriptorSetLayout const *> layout_nodes;
    263     AllocateDescriptorSetsData(uint32_t);
    264 };
    265 // Helper functions for descriptor set functions that cross multiple sets
    266 // "Validate" will make sure an update is ok without actually performing it
    267 bool ValidateUpdateDescriptorSets(const debug_report_data *, const core_validation::layer_data *, uint32_t,
    268                                   const VkWriteDescriptorSet *, uint32_t, const VkCopyDescriptorSet *);
    269 // "Perform" does the update with the assumption that ValidateUpdateDescriptorSets() has passed for the given update
    270 void PerformUpdateDescriptorSets(const core_validation::layer_data *, uint32_t, const VkWriteDescriptorSet *, uint32_t,
    271                                  const VkCopyDescriptorSet *);
    272 // Validate that Allocation state is ok
    273 bool ValidateAllocateDescriptorSets(const debug_report_data *, const VkDescriptorSetAllocateInfo *,
    274                                     const core_validation::layer_data *, AllocateDescriptorSetsData *);
    275 // Update state based on allocating new descriptorsets
    276 void PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *, const VkDescriptorSet *, const AllocateDescriptorSetsData *,
    277                                    std::unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_STATE *> *,
    278                                    std::unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> *,
    279                                    const core_validation::layer_data *);
    280 
    281 /*
    282  * DescriptorSet class
    283  *
    284  * Overview - This class encapsulates the Vulkan VkDescriptorSet data (set).
    285  *   A set has an underlying layout which defines the bindings in the set and the
    286  *   types and numbers of descriptors in each descriptor slot. Most of the layout
    287  *   interfaces are exposed through identically-named functions in the set class.
    288  *   Please refer to the DescriptorSetLayout comment above for a description of
    289  *   index, binding, and global index.
    290  *
    291  * At construction a vector of Descriptor* is created with types corresponding to the
    292  *   layout. The primary operation performed on the descriptors is to update them
    293  *   via write or copy updates, and validate that the update contents are correct.
    294  *   In order to validate update contents, the DescriptorSet stores a bunch of ptrs
    295  *   to data maps where various Vulkan objects can be looked up. The management of
    296  *   those maps is performed externally. The set class relies on their contents to
    297  *   be correct at the time of update.
    298  */
    299 class DescriptorSet : public BASE_NODE {
    300   public:
    301     DescriptorSet(const VkDescriptorSet, const VkDescriptorPool, const DescriptorSetLayout *, const core_validation::layer_data *);
    302     ~DescriptorSet();
    303     // A number of common Get* functions that return data based on layout from which this set was created
    304     uint32_t GetTotalDescriptorCount() const { return p_layout_ ? p_layout_->GetTotalDescriptorCount() : 0; };
    305     uint32_t GetDynamicDescriptorCount() const { return p_layout_ ? p_layout_->GetDynamicDescriptorCount() : 0; };
    306     uint32_t GetBindingCount() const { return p_layout_ ? p_layout_->GetBindingCount() : 0; };
    307     VkDescriptorType GetTypeFromIndex(const uint32_t index) const {
    308         return p_layout_ ? p_layout_->GetTypeFromIndex(index) : VK_DESCRIPTOR_TYPE_MAX_ENUM;
    309     };
    310     VkDescriptorType GetTypeFromGlobalIndex(const uint32_t index) const {
    311         return p_layout_ ? p_layout_->GetTypeFromGlobalIndex(index) : VK_DESCRIPTOR_TYPE_MAX_ENUM;
    312     };
    313     VkDescriptorType GetTypeFromBinding(const uint32_t binding) const {
    314         return p_layout_ ? p_layout_->GetTypeFromBinding(binding) : VK_DESCRIPTOR_TYPE_MAX_ENUM;
    315     };
    316     uint32_t GetDescriptorCountFromIndex(const uint32_t index) const {
    317         return p_layout_ ? p_layout_->GetDescriptorCountFromIndex(index) : 0;
    318     };
    319     uint32_t GetDescriptorCountFromBinding(const uint32_t binding) const {
    320         return p_layout_ ? p_layout_->GetDescriptorCountFromBinding(binding) : 0;
    321     };
    322     // Return true if given binding is present in this set
    323     bool HasBinding(const uint32_t binding) const { return p_layout_->HasBinding(binding); };
    324     // Is this set compatible with the given layout?
    325     bool IsCompatible(const DescriptorSetLayout *, std::string *) const;
    326     // For given bindings validate state at time of draw is correct, returning false on error and writing error details into string*
    327     bool ValidateDrawState(const std::map<uint32_t, descriptor_req> &, const std::vector<uint32_t> &, std::string *) const;
    328     // For given set of bindings, add any buffers and images that will be updated to their respective unordered_sets & return number
    329     // of objects inserted
    330     uint32_t GetStorageUpdates(const std::map<uint32_t, descriptor_req> &, std::unordered_set<VkBuffer> *,
    331                                std::unordered_set<VkImageView> *) const;
    332 
    333     // Descriptor Update functions. These functions validate state and perform update separately
    334     // Validate contents of a WriteUpdate
    335     bool ValidateWriteUpdate(const debug_report_data *, const VkWriteDescriptorSet *, UNIQUE_VALIDATION_ERROR_CODE *,
    336                              std::string *);
    337     // Perform a WriteUpdate whose contents were just validated using ValidateWriteUpdate
    338     void PerformWriteUpdate(const VkWriteDescriptorSet *);
    339     // Validate contents of a CopyUpdate
    340     bool ValidateCopyUpdate(const debug_report_data *, const VkCopyDescriptorSet *, const DescriptorSet *,
    341                             UNIQUE_VALIDATION_ERROR_CODE *, std::string *);
    342     // Perform a CopyUpdate whose contents were just validated using ValidateCopyUpdate
    343     void PerformCopyUpdate(const VkCopyDescriptorSet *, const DescriptorSet *);
    344 
    345     const DescriptorSetLayout *GetLayout() const { return p_layout_; };
    346     VkDescriptorSet GetSet() const { return set_; };
    347     // Return unordered_set of all command buffers that this set is bound to
    348     std::unordered_set<GLOBAL_CB_NODE *> GetBoundCmdBuffers() const { return cb_bindings; }
    349     // Bind given cmd_buffer to this descriptor set
    350     void BindCommandBuffer(GLOBAL_CB_NODE *, const std::unordered_set<uint32_t> &);
    351     // If given cmd_buffer is in the cb_bindings set, remove it
    352     void RemoveBoundCommandBuffer(GLOBAL_CB_NODE *cb_node) { cb_bindings.erase(cb_node); }
    353     VkSampler const *GetImmutableSamplerPtrFromBinding(const uint32_t index) const {
    354         return p_layout_->GetImmutableSamplerPtrFromBinding(index);
    355     };
    356     // For a particular binding, get the global index
    357     uint32_t GetGlobalStartIndexFromBinding(const uint32_t binding) const {
    358         return p_layout_->GetGlobalStartIndexFromBinding(binding);
    359     };
    360     uint32_t GetGlobalEndIndexFromBinding(const uint32_t binding) const {
    361         return p_layout_->GetGlobalEndIndexFromBinding(binding);
    362     };
    363     // Return true if any part of set has ever been updated
    364     bool IsUpdated() const { return some_update_; };
    365 
    366   private:
    367     bool VerifyWriteUpdateContents(const VkWriteDescriptorSet *, const uint32_t, UNIQUE_VALIDATION_ERROR_CODE *,
    368                                    std::string *) const;
    369     bool VerifyCopyUpdateContents(const VkCopyDescriptorSet *, const DescriptorSet *, VkDescriptorType, uint32_t,
    370                                   UNIQUE_VALIDATION_ERROR_CODE *, std::string *) const;
    371     bool ValidateBufferUsage(BUFFER_NODE const *, VkDescriptorType, UNIQUE_VALIDATION_ERROR_CODE *, std::string *) const;
    372     bool ValidateBufferUpdate(VkDescriptorBufferInfo const *, VkDescriptorType, UNIQUE_VALIDATION_ERROR_CODE *,
    373                               std::string *) const;
    374     // Private helper to set all bound cmd buffers to INVALID state
    375     void InvalidateBoundCmdBuffers();
    376     bool some_update_; // has any part of the set ever been updated?
    377     VkDescriptorSet set_;
    378     DESCRIPTOR_POOL_STATE *pool_state_;
    379     const DescriptorSetLayout *p_layout_;
    380     std::vector<std::unique_ptr<Descriptor>> descriptors_;
    381     // Ptr to device data used for various data look-ups
    382     const core_validation::layer_data *device_data_;
    383 };
    384 }
    385 #endif // CORE_VALIDATION_DESCRIPTOR_SETS_H_
    386