diff options
| author | John Zulauf <jzulauf@lunarg.com> | 2018-02-16 12:58:37 -0700 |
|---|---|---|
| committer | jzulauf-lunarg <32470354+jzulauf-lunarg@users.noreply.github.com> | 2018-03-07 13:11:29 -0700 |
| commit | 76fbd478fcd0bb52f53478c2a546b4d486155836 (patch) | |
| tree | 7a52f7351a284c21f7585da75c6772a7ef047618 /layers/descriptor_sets.cpp | |
| parent | 7bb723b747121736713d02d10717c80f5e213e65 (diff) | |
| download | usermoji-76fbd478fcd0bb52f53478c2a546b4d486155836.tar.xz | |
layers: Split DescriptorSetLayout data structure
In preparing for use of "common definiton" id's split the
DescriptorSetLayout data structure into handle specific and common (def)
components. Object interface is preserved.
Change-Id: I5c6b1e726aa70de548c65a5f5ad08726b0a7507b
Diffstat (limited to 'layers/descriptor_sets.cpp')
| -rw-r--r-- | layers/descriptor_sets.cpp | 191 |
1 files changed, 99 insertions, 92 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) {} |
