diff options
| -rw-r--r-- | layers/descriptor_sets.cpp | 191 | ||||
| -rw-r--r-- | layers/descriptor_sets.h | 110 |
2 files changed, 195 insertions, 106 deletions
diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index 9294dde9..96b75023 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -28,6 +28,7 @@ #include "buffer_validation.h" #include <sstream> #include <algorithm> +#include <memory> struct BindingNumCmp { bool operator()(const VkDescriptorSetLayoutBinding *a, const VkDescriptorSetLayoutBinding *b) const { @@ -37,14 +38,8 @@ struct BindingNumCmp { // Construct DescriptorSetLayout instance from given create info // Proactively reserve and resize as possible, as the reallocation was visible in profiling -cvdescriptorset::DescriptorSetLayout::DescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo *p_create_info, - const VkDescriptorSetLayout layout) - : layout_(layout), - layout_destroyed_(false), - flags_(p_create_info->flags), - binding_count_(0), - descriptor_count_(0), - dynamic_descriptor_count_(0) { +cvdescriptorset::DescriptorSetLayoutDef::DescriptorSetLayoutDef(const VkDescriptorSetLayoutCreateInfo *p_create_info) + : flags_(p_create_info->flags), binding_count_(0), descriptor_count_(0), dynamic_descriptor_count_(0) { binding_type_stats_ = {0, 0, 0}; std::set<const VkDescriptorSetLayoutBinding *, BindingNumCmp> sorted_bindings; const uint32_t input_bindings_count = p_create_info->bindingCount; @@ -106,91 +101,39 @@ cvdescriptorset::DescriptorSetLayout::DescriptorSetLayout(const VkDescriptorSetL } } -// Validate descriptor set layout create info -bool cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(const debug_report_data *report_data, - const VkDescriptorSetLayoutCreateInfo *create_info, - const bool push_descriptor_ext, const uint32_t max_push_descriptors) { - bool skip = false; - std::unordered_set<uint32_t> bindings; - uint64_t total_descriptors = 0; - - const bool push_descriptor_set = create_info->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; - if (push_descriptor_set && !push_descriptor_ext) { - skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, - DRAWSTATE_EXTENSION_NOT_ENABLED, "DS", - "Attemped to use %s in %s but its required extension %s has not been enabled.\n", - "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR", "VkDescriptorSetLayoutCreateInfo::flags", - VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - } - - auto valid_type = [push_descriptor_set](const VkDescriptorType type) { - return !push_descriptor_set || - ((type != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) && (type != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)); - }; - - for (uint32_t i = 0; i < create_info->bindingCount; ++i) { - const auto &binding_info = create_info->pBindings[i]; - if (!bindings.insert(binding_info.binding).second) { - skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, - VALIDATION_ERROR_0500022e, "DS", "duplicated binding number in VkDescriptorSetLayoutBinding. %s", - validation_error_map[VALIDATION_ERROR_0500022e]); - } - if (!valid_type(binding_info.descriptorType)) { - skip |= - log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, - VALIDATION_ERROR_05000230, "DS", - "invalid type %s ,for push descriptors in VkDescriptorSetLayoutBinding entry %" PRIu32 ". %s", - string_VkDescriptorType(binding_info.descriptorType), i, validation_error_map[VALIDATION_ERROR_05000230]); - } - total_descriptors += binding_info.descriptorCount; - } - - if ((push_descriptor_set) && (total_descriptors > max_push_descriptors)) { - const char *undefined = push_descriptor_ext ? "" : " -- undefined"; - skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, - VALIDATION_ERROR_05000232, "DS", - "for push descriptor, total descriptor count in layout (%" PRIu64 - ") must not be greater than VkPhysicalDevicePushDescriptorPropertiesKHR::maxPushDescriptors (%" PRIu32 - "%s). %s", - total_descriptors, max_push_descriptors, undefined, validation_error_map[VALIDATION_ERROR_05000232]); - } - - return skip; -} - // Return valid index or "end" i.e. binding_count_; // The asserts in "Get" are reduced to the set where no valid answer(like null or 0) could be given // Common code for all binding lookups. -uint32_t cvdescriptorset::DescriptorSetLayout::GetIndexFromBinding(uint32_t binding) const { +uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetIndexFromBinding(uint32_t binding) const { const auto &bi_itr = binding_to_index_map_.find(binding); if (bi_itr != binding_to_index_map_.cend()) return bi_itr->second; return GetBindingCount(); } -VkDescriptorSetLayoutBinding const *cvdescriptorset::DescriptorSetLayout::GetDescriptorSetLayoutBindingPtrFromIndex( +VkDescriptorSetLayoutBinding const *cvdescriptorset::DescriptorSetLayoutDef::GetDescriptorSetLayoutBindingPtrFromIndex( const uint32_t index) const { if (index >= bindings_.size()) return nullptr; return bindings_[index].ptr(); } // Return descriptorCount for given index, 0 if index is unavailable -uint32_t cvdescriptorset::DescriptorSetLayout::GetDescriptorCountFromIndex(const uint32_t index) const { +uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetDescriptorCountFromIndex(const uint32_t index) const { if (index >= bindings_.size()) return 0; return bindings_[index].descriptorCount; } // For the given index, return descriptorType -VkDescriptorType cvdescriptorset::DescriptorSetLayout::GetTypeFromIndex(const uint32_t index) const { +VkDescriptorType cvdescriptorset::DescriptorSetLayoutDef::GetTypeFromIndex(const uint32_t index) const { assert(index < bindings_.size()); if (index < bindings_.size()) return bindings_[index].descriptorType; return VK_DESCRIPTOR_TYPE_MAX_ENUM; } // For the given index, return stageFlags -VkShaderStageFlags cvdescriptorset::DescriptorSetLayout::GetStageFlagsFromIndex(const uint32_t index) const { +VkShaderStageFlags cvdescriptorset::DescriptorSetLayoutDef::GetStageFlagsFromIndex(const uint32_t index) const { assert(index < bindings_.size()); if (index < bindings_.size()) return bindings_[index].stageFlags; return VkShaderStageFlags(0); } // For the given global index, return index -uint32_t cvdescriptorset::DescriptorSetLayout::GetIndexFromGlobalIndex(const uint32_t global_index) const { +uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetIndexFromGlobalIndex(const uint32_t global_index) const { auto start_it = global_start_to_index_map_.upper_bound(global_index); uint32_t index = binding_count_; assert(start_it != global_start_to_index_map_.cbegin()); @@ -207,7 +150,7 @@ uint32_t cvdescriptorset::DescriptorSetLayout::GetIndexFromGlobalIndex(const uin // For the given binding, return the global index range // As start and end are often needed in pairs, get both with a single hash lookup. -const cvdescriptorset::IndexRange &cvdescriptorset::DescriptorSetLayout::GetGlobalIndexRangeFromBinding( +const cvdescriptorset::IndexRange &cvdescriptorset::DescriptorSetLayoutDef::GetGlobalIndexRangeFromBinding( const uint32_t binding) const { assert(binding_to_global_index_range_map_.count(binding)); // In error case max uint32_t so index is out of bounds to break ASAP @@ -220,7 +163,7 @@ const cvdescriptorset::IndexRange &cvdescriptorset::DescriptorSetLayout::GetGlob } // For given binding, return ptr to ImmutableSampler array -VkSampler const *cvdescriptorset::DescriptorSetLayout::GetImmutableSamplerPtrFromBinding(const uint32_t binding) const { +VkSampler const *cvdescriptorset::DescriptorSetLayoutDef::GetImmutableSamplerPtrFromBinding(const uint32_t binding) const { const auto &bi_itr = binding_to_index_map_.find(binding); if (bi_itr != binding_to_index_map_.end()) { return bindings_[bi_itr->second].pImmutableSamplers; @@ -228,14 +171,14 @@ VkSampler const *cvdescriptorset::DescriptorSetLayout::GetImmutableSamplerPtrFro return nullptr; } // Move to next valid binding having a non-zero binding count -uint32_t cvdescriptorset::DescriptorSetLayout::GetNextValidBinding(const uint32_t binding) const { +uint32_t cvdescriptorset::DescriptorSetLayoutDef::GetNextValidBinding(const uint32_t binding) const { auto it = non_empty_bindings_.upper_bound(binding); assert(it != non_empty_bindings_.cend()); if (it != non_empty_bindings_.cend()) return *it; return GetMaxBinding() + 1; } // For given index, return ptr to ImmutableSampler array -VkSampler const *cvdescriptorset::DescriptorSetLayout::GetImmutableSamplerPtrFromIndex(const uint32_t index) const { +VkSampler const *cvdescriptorset::DescriptorSetLayoutDef::GetImmutableSamplerPtrFromIndex(const uint32_t index) const { if (index < bindings_.size()) { return bindings_[index].pImmutableSamplers; } @@ -247,11 +190,18 @@ bool cvdescriptorset::DescriptorSetLayout::IsCompatible(DescriptorSetLayout cons std::string *error_msg) const { // Trivial case if (layout_ == rh_ds_layout->GetDescriptorSetLayout()) return true; - if (descriptor_count_ != rh_ds_layout->descriptor_count_) { + return get_layout_def()->IsCompatible(layout_, rh_ds_layout->GetDescriptorSetLayout(), rh_ds_layout->get_layout_def(), + error_msg); +} + +bool cvdescriptorset::DescriptorSetLayoutDef::IsCompatible(VkDescriptorSetLayout ds_layout, VkDescriptorSetLayout rh_ds_layout, + DescriptorSetLayoutDef const *const rh_ds_layout_def, + std::string *error_msg) const { + if (descriptor_count_ != rh_ds_layout_def->descriptor_count_) { std::stringstream error_str; - error_str << "DescriptorSetLayout " << layout_ << " has " << descriptor_count_ << " descriptors, but DescriptorSetLayout " - << rh_ds_layout->GetDescriptorSetLayout() << ", which comes from pipelineLayout, has " - << rh_ds_layout->descriptor_count_ << " descriptors."; + error_str << "DescriptorSetLayout " << ds_layout << " has " << descriptor_count_ << " descriptors, but DescriptorSetLayout " + << rh_ds_layout << ", which comes from pipelineLayout, has " << rh_ds_layout_def->descriptor_count_ + << " descriptors."; *error_msg = error_str.str(); return false; // trivial fail case } @@ -260,29 +210,28 @@ bool cvdescriptorset::DescriptorSetLayout::IsCompatible(DescriptorSetLayout cons for (auto binding : bindings_) { // TODO : Do we also need to check immutable samplers? // VkDescriptorSetLayoutBinding *rh_binding; - if (binding.descriptorCount != rh_ds_layout->GetDescriptorCountFromBinding(binding.binding)) { + if (binding.descriptorCount != rh_ds_layout_def->GetDescriptorCountFromBinding(binding.binding)) { std::stringstream error_str; - error_str << "Binding " << binding.binding << " for DescriptorSetLayout " << layout_ << " has a descriptorCount of " + error_str << "Binding " << binding.binding << " for DescriptorSetLayout " << ds_layout << " has a descriptorCount of " << binding.descriptorCount << " but binding " << binding.binding << " for DescriptorSetLayout " - << rh_ds_layout->GetDescriptorSetLayout() << ", which comes from pipelineLayout, has a descriptorCount of " - << rh_ds_layout->GetDescriptorCountFromBinding(binding.binding); + << rh_ds_layout << ", which comes from pipelineLayout, has a descriptorCount of " + << rh_ds_layout_def->GetDescriptorCountFromBinding(binding.binding); *error_msg = error_str.str(); return false; - } else if (binding.descriptorType != rh_ds_layout->GetTypeFromBinding(binding.binding)) { + } else if (binding.descriptorType != rh_ds_layout_def->GetTypeFromBinding(binding.binding)) { std::stringstream error_str; - error_str << "Binding " << binding.binding << " for DescriptorSetLayout " << layout_ << " is type '" + error_str << "Binding " << binding.binding << " for DescriptorSetLayout " << ds_layout << " is type '" << string_VkDescriptorType(binding.descriptorType) << "' but binding " << binding.binding - << " for DescriptorSetLayout " << rh_ds_layout->GetDescriptorSetLayout() - << ", which comes from pipelineLayout, is type '" - << string_VkDescriptorType(rh_ds_layout->GetTypeFromBinding(binding.binding)) << "'"; + << " for DescriptorSetLayout " << rh_ds_layout << ", which comes from pipelineLayout, is type '" + << string_VkDescriptorType(rh_ds_layout_def->GetTypeFromBinding(binding.binding)) << "'"; *error_msg = error_str.str(); return false; - } else if (binding.stageFlags != rh_ds_layout->GetStageFlagsFromBinding(binding.binding)) { + } else if (binding.stageFlags != rh_ds_layout_def->GetStageFlagsFromBinding(binding.binding)) { std::stringstream error_str; - error_str << "Binding " << binding.binding << " for DescriptorSetLayout " << layout_ << " has stageFlags " - << binding.stageFlags << " but binding " << binding.binding << " for DescriptorSetLayout " - << rh_ds_layout->GetDescriptorSetLayout() << ", which comes from pipelineLayout, has stageFlags " - << rh_ds_layout->GetStageFlagsFromBinding(binding.binding); + error_str << "Binding " << binding.binding << " for DescriptorSetLayout " << ds_layout << " has stageFlags " + << binding.stageFlags << " but binding " << binding.binding << " for DescriptorSetLayout " << rh_ds_layout + << ", which comes from pipelineLayout, has stageFlags " + << rh_ds_layout_def->GetStageFlagsFromBinding(binding.binding); *error_msg = error_str.str(); return false; } @@ -290,7 +239,7 @@ bool cvdescriptorset::DescriptorSetLayout::IsCompatible(DescriptorSetLayout cons return true; } -bool cvdescriptorset::DescriptorSetLayout::IsNextBindingConsistent(const uint32_t binding) const { +bool cvdescriptorset::DescriptorSetLayoutDef::IsNextBindingConsistent(const uint32_t binding) const { if (!binding_to_index_map_.count(binding + 1)) return false; auto const &bi_itr = binding_to_index_map_.find(binding); if (bi_itr != binding_to_index_map_.end()) { @@ -313,9 +262,9 @@ bool cvdescriptorset::DescriptorSetLayout::IsNextBindingConsistent(const uint32_ // descriptor updates and verify that for any binding boundaries that are crossed, the next binding(s) are all consistent // Consistency means that their type, stage flags, and whether or not they use immutable samplers matches // If so, return true. If not, fill in error_msg and return false -bool cvdescriptorset::DescriptorSetLayout::VerifyUpdateConsistency(uint32_t current_binding, uint32_t offset, uint32_t update_count, - const char *type, const VkDescriptorSet set, - std::string *error_msg) const { +bool cvdescriptorset::DescriptorSetLayoutDef::VerifyUpdateConsistency(uint32_t current_binding, uint32_t offset, + uint32_t update_count, const char *type, + const VkDescriptorSet set, std::string *error_msg) const { // Verify consecutive bindings match (if needed) auto orig_binding = current_binding; // Track count of descriptors in the current_bindings that are remaining to be updated @@ -346,6 +295,64 @@ bool cvdescriptorset::DescriptorSetLayout::VerifyUpdateConsistency(uint32_t curr return true; } +// The DescriptorSetLayout stores the per handle data for a descriptor set layout, and references the common defintion for the +// handle invariant portion +cvdescriptorset::DescriptorSetLayout::DescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo *p_create_info, + const VkDescriptorSetLayout layout) + : layout_(layout), layout_destroyed_(false), layout_id_(std::make_shared<DescriptorSetLayoutDef>(p_create_info)) {} + +// Validate descriptor set layout create info +bool cvdescriptorset::DescriptorSetLayout::ValidateCreateInfo(const debug_report_data *report_data, + const VkDescriptorSetLayoutCreateInfo *create_info, + const bool push_descriptor_ext, const uint32_t max_push_descriptors) { + bool skip = false; + std::unordered_set<uint32_t> bindings; + uint64_t total_descriptors = 0; + + const bool push_descriptor_set = create_info->flags & VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR; + if (push_descriptor_set && !push_descriptor_ext) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, + DRAWSTATE_EXTENSION_NOT_ENABLED, "DS", + "Attemped to use %s in %s but its required extension %s has not been enabled.\n", + "VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR", "VkDescriptorSetLayoutCreateInfo::flags", + VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); + } + + auto valid_type = [push_descriptor_set](const VkDescriptorType type) { + return !push_descriptor_set || + ((type != VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) && (type != VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)); + }; + + for (uint32_t i = 0; i < create_info->bindingCount; ++i) { + const auto &binding_info = create_info->pBindings[i]; + if (!bindings.insert(binding_info.binding).second) { + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, + VALIDATION_ERROR_0500022e, "DS", "duplicated binding number in VkDescriptorSetLayoutBinding. %s", + validation_error_map[VALIDATION_ERROR_0500022e]); + } + if (!valid_type(binding_info.descriptorType)) { + skip |= + log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, + VALIDATION_ERROR_05000230, "DS", + "invalid type %s ,for push descriptors in VkDescriptorSetLayoutBinding entry %" PRIu32 ". %s", + string_VkDescriptorType(binding_info.descriptorType), i, validation_error_map[VALIDATION_ERROR_05000230]); + } + total_descriptors += binding_info.descriptorCount; + } + + if ((push_descriptor_set) && (total_descriptors > max_push_descriptors)) { + const char *undefined = push_descriptor_ext ? "" : " -- undefined"; + skip |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, + VALIDATION_ERROR_05000232, "DS", + "for push descriptor, total descriptor count in layout (%" PRIu64 + ") must not be greater than VkPhysicalDevicePushDescriptorPropertiesKHR::maxPushDescriptors (%" PRIu32 + "%s). %s", + total_descriptors, max_push_descriptors, undefined, validation_error_map[VALIDATION_ERROR_05000232]); + } + + return skip; +} + cvdescriptorset::AllocateDescriptorSetsData::AllocateDescriptorSetsData(uint32_t count) : required_descriptors_by_type{}, layout_nodes(count, nullptr) {} diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index ac5bede4..a20d602d 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -81,16 +81,12 @@ typedef std::map<uint32_t, descriptor_req> BindingReqMap; * 10, then the GlobalStartIndex of the 2nd lowest binding# will be 10 where 0-9 are the * global indices for the lowest binding#. */ -class DescriptorSetLayout { +class DescriptorSetLayoutDef { public: // Constructors and destructor - DescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo *p_create_info, const VkDescriptorSetLayout layout); - // Validate create info - should be called prior to creation - static bool ValidateCreateInfo(const debug_report_data *, const VkDescriptorSetLayoutCreateInfo *, const bool, const uint32_t); - // Straightforward Get functions - VkDescriptorSetLayout GetDescriptorSetLayout() const { return layout_; }; - bool IsDestroyed() const { return layout_destroyed_; } - void MarkDestroyed() { layout_destroyed_ = true; } + DescriptorSetLayoutDef(const VkDescriptorSetLayoutCreateInfo *p_create_info); + size_t hash() const; + uint32_t GetTotalDescriptorCount() const { return descriptor_count_; }; uint32_t GetDynamicDescriptorCount() const { return dynamic_descriptor_count_; }; VkDescriptorSetLayoutCreateFlags GetCreateFlags() const { return flags_; } @@ -102,7 +98,7 @@ class DescriptorSetLayout { bool HasBinding(const uint32_t binding) const { return binding_to_index_map_.count(binding) > 0; }; // Return true if this layout is compatible with passed in layout from a pipelineLayout, // else return false and update error_msg with description of incompatibility - bool IsCompatible(DescriptorSetLayout const *const, std::string *) const; + bool IsCompatible(VkDescriptorSetLayout, VkDescriptorSetLayout, DescriptorSetLayoutDef const *const, std::string *) const; // Return true if binding 1 beyond given exists and has same type, stageFlags & immutable sampler use bool IsNextBindingConsistent(const uint32_t) const; uint32_t GetIndexFromBinding(uint32_t binding) const; @@ -113,6 +109,7 @@ class DescriptorSetLayout { VkDescriptorSetLayoutBinding const *GetDescriptorSetLayoutBindingPtrFromBinding(uint32_t binding) const { return GetDescriptorSetLayoutBindingPtrFromIndex(GetIndexFromBinding(binding)); } + const std::vector<safe_VkDescriptorSetLayoutBinding> &GetBindings() const { return bindings_; } uint32_t GetDescriptorCountFromIndex(const uint32_t) const; uint32_t GetDescriptorCountFromBinding(const uint32_t binding) const { return GetDescriptorCountFromIndex(GetIndexFromBinding(binding)); @@ -157,8 +154,11 @@ class DescriptorSetLayout { const BindingTypeStats &GetBindingTypeStats() const { return binding_type_stats_; } private: - VkDescriptorSetLayout layout_; - bool layout_destroyed_; + // Only the first two are needed for hash and equality checks, the other fields are derivative them uniquely + VkDescriptorSetLayoutCreateFlags flags_; + std::vector<safe_VkDescriptorSetLayoutBinding> bindings_; + + // Convenience data structures for rapid lookup of various descriptor set layout properties std::set<uint32_t> non_empty_bindings_; // Containing non-emtpy bindings in numerical order std::unordered_map<uint32_t, uint32_t> binding_to_index_map_; // The following map allows an non-iterative lookup of a binding from a global index... @@ -166,14 +166,96 @@ class DescriptorSetLayout { std::unordered_map<uint32_t, IndexRange> binding_to_global_index_range_map_; // range is exclusive of .end // For a given binding map to associated index in the dynamic offset array std::unordered_map<uint32_t, uint32_t> binding_to_dynamic_array_idx_map_; - VkDescriptorSetLayoutCreateFlags flags_; + uint32_t binding_count_; // # of bindings in this layout - std::vector<safe_VkDescriptorSetLayoutBinding> bindings_; uint32_t descriptor_count_; // total # descriptors in this layout uint32_t dynamic_descriptor_count_; BindingTypeStats binding_type_stats_; }; +using DescriptorSetLayoutId = std::shared_ptr<DescriptorSetLayoutDef>; + +class DescriptorSetLayout { + public: + // Constructors and destructor + DescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo *p_create_info, const VkDescriptorSetLayout layout); + // Validate create info - should be called prior to creation + static bool ValidateCreateInfo(const debug_report_data *, const VkDescriptorSetLayoutCreateInfo *, const bool, const uint32_t); + bool HasBinding(const uint32_t binding) const { return layout_id_->HasBinding(binding); } + // Return true if this layout is compatible with passed in layout from a pipelineLayout, + // else return false and update error_msg with description of incompatibility + bool IsCompatible(DescriptorSetLayout const *const, std::string *) const; + // Straightforward Get functions + VkDescriptorSetLayout GetDescriptorSetLayout() const { return layout_; }; + bool IsDestroyed() const { return layout_destroyed_; } + void MarkDestroyed() { layout_destroyed_ = true; } + const DescriptorSetLayoutDef *get_layout_def() const { return layout_id_.get(); } + uint32_t GetTotalDescriptorCount() const { return layout_id_->GetTotalDescriptorCount(); }; + uint32_t GetDynamicDescriptorCount() const { return layout_id_->GetDynamicDescriptorCount(); }; + uint32_t GetBindingCount() const { return layout_id_->GetBindingCount(); }; + VkDescriptorSetLayoutCreateFlags GetCreateFlags() const { return layout_id_->GetCreateFlags(); } + bool IsNextBindingConsistent(const uint32_t) const; + uint32_t GetIndexFromBinding(uint32_t binding) const { return layout_id_->GetIndexFromBinding(binding); } + // Various Get functions that can either be passed a binding#, which will + // be automatically translated into the appropriate index, or the index# can be passed in directly + uint32_t GetMaxBinding() const { return layout_id_->GetMaxBinding(); } + VkDescriptorSetLayoutBinding const *GetDescriptorSetLayoutBindingPtrFromIndex(const uint32_t index) const { + return layout_id_->GetDescriptorSetLayoutBindingPtrFromIndex(index); + } + VkDescriptorSetLayoutBinding const *GetDescriptorSetLayoutBindingPtrFromBinding(uint32_t binding) const { + return layout_id_->GetDescriptorSetLayoutBindingPtrFromBinding(binding); + } + const std::vector<safe_VkDescriptorSetLayoutBinding> &GetBindings() const { return layout_id_->GetBindings(); } + uint32_t GetDescriptorCountFromIndex(const uint32_t index) const { return layout_id_->GetDescriptorCountFromIndex(index); } + uint32_t GetDescriptorCountFromBinding(const uint32_t binding) const { + return layout_id_->GetDescriptorCountFromBinding(binding); + } + VkDescriptorType GetTypeFromIndex(const uint32_t index) const { return layout_id_->GetTypeFromIndex(index); } + VkDescriptorType GetTypeFromBinding(const uint32_t binding) const { return layout_id_->GetTypeFromBinding(binding); } + VkShaderStageFlags GetStageFlagsFromIndex(const uint32_t index) const { return layout_id_->GetStageFlagsFromIndex(index); } + VkShaderStageFlags GetStageFlagsFromBinding(const uint32_t binding) const { + return layout_id_->GetStageFlagsFromBinding(binding); + } + uint32_t GetIndexFromGlobalIndex(const uint32_t global_index) const { + return layout_id_->GetIndexFromGlobalIndex(global_index); + } + VkDescriptorType GetTypeFromGlobalIndex(const uint32_t global_index) const { + return GetTypeFromIndex(GetIndexFromGlobalIndex(global_index)); + } + VkSampler const *GetImmutableSamplerPtrFromBinding(const uint32_t binding) const { + return layout_id_->GetImmutableSamplerPtrFromBinding(binding); + } + VkSampler const *GetImmutableSamplerPtrFromIndex(const uint32_t index) const { + return layout_id_->GetImmutableSamplerPtrFromIndex(index); + } + // For a given binding and array index, return the corresponding index into the dynamic offset array + int32_t GetDynamicOffsetIndexFromBinding(uint32_t binding) const { + return layout_id_->GetDynamicOffsetIndexFromBinding(binding); + } + // For a particular binding, get the global index range + // This call should be guarded by a call to "HasBinding(binding)" to verify that the given binding exists + const IndexRange &GetGlobalIndexRangeFromBinding(const uint32_t binding) const { + return layout_id_->GetGlobalIndexRangeFromBinding(binding); + } + // Helper function to get the next valid binding for a descriptor + uint32_t GetNextValidBinding(const uint32_t binding) const { return layout_id_->GetNextValidBinding(binding); } + // For a particular binding starting at offset and having update_count descriptors + // updated, verify that for any binding boundaries crossed, the update is consistent + bool VerifyUpdateConsistency(uint32_t current_binding, uint32_t offset, uint32_t update_count, const char *type, + const VkDescriptorSet set, std::string *error_msg) const { + return layout_id_->VerifyUpdateConsistency(current_binding, offset, update_count, type, set, error_msg); + } + bool IsPushDescriptor() const { return layout_id_->IsPushDescriptor(); } + + using BindingTypeStats = DescriptorSetLayoutDef::BindingTypeStats; + const BindingTypeStats &GetBindingTypeStats() const { return layout_id_->GetBindingTypeStats(); } + + private: + VkDescriptorSetLayout layout_; + bool layout_destroyed_; + DescriptorSetLayoutId layout_id_; +}; + /* * Descriptor classes * Descriptor is an abstract base class from which 5 separate descriptor types are derived. @@ -379,7 +461,7 @@ class DescriptorSet : public BASE_NODE { // Perform a CopyUpdate whose contents were just validated using ValidateCopyUpdate void PerformCopyUpdate(const VkCopyDescriptorSet *, const DescriptorSet *); - std::shared_ptr<DescriptorSetLayout const> const GetLayout() const { return p_layout_; }; + const std::shared_ptr<DescriptorSetLayout const> GetLayout() const { return p_layout_; }; VkDescriptorSet GetSet() const { return set_; }; // Return unordered_set of all command buffers that this set is bound to std::unordered_set<GLOBAL_CB_NODE *> GetBoundCmdBuffers() const { return cb_bindings; } |
