From fbe0c123e8656814254c702d1111111016317a08 Mon Sep 17 00:00:00 2001 From: Tobin Ehlis Date: Mon, 12 Dec 2016 15:59:34 -0700 Subject: [PATCH] layers:Store DescriptorSetLayout class in-order Sort the bindings in the internal data structure of the DescriptorSetLayout class so that they're stored in binding order. This commit keeps the interface and mapping structures the same. Further commits will take more use of the fact that layout is now stored in binding order. --- layers/descriptor_sets.cpp | 35 +++++++++++++++++++++++++++-------- layers/descriptor_sets.h | 33 ++++++++++++++++++--------------- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp index eef6567..4b74838 100644 --- a/layers/descriptor_sets.cpp +++ b/layers/descriptor_sets.cpp @@ -31,23 +31,31 @@ cvdescriptorset::DescriptorSetLayout::DescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo *p_create_info, const VkDescriptorSetLayout layout) : layout_(layout), binding_count_(p_create_info->bindingCount), descriptor_count_(0), dynamic_descriptor_count_(0) { - uint32_t global_index = 0; // Dyn array indicies are ordered by binding # and array index of any array within the binding // so we store up bindings w/ count in ordered map in order to create dyn array mappings below std::map binding_to_dyn_count; for (uint32_t i = 0; i < binding_count_; ++i) { + auto binding_num = p_create_info->pBindings[i].binding; descriptor_count_ += p_create_info->pBindings[i].descriptorCount; - binding_to_index_map_[p_create_info->pBindings[i].binding] = i; - binding_to_global_start_index_map_[p_create_info->pBindings[i].binding] = global_index; - global_index += p_create_info->pBindings[i].descriptorCount ? p_create_info->pBindings[i].descriptorCount - 1 : 0; - binding_to_global_end_index_map_[p_create_info->pBindings[i].binding] = global_index; - global_index += p_create_info->pBindings[i].descriptorCount ? 1 : 0; - bindings_.push_back(safe_VkDescriptorSetLayoutBinding(&p_create_info->pBindings[i])); + uint32_t insert_index = 0; // Track vector index where we insert element + if (bindings_.empty() || binding_num > bindings_.back().binding) { + bindings_.push_back(safe_VkDescriptorSetLayoutBinding(&p_create_info->pBindings[i])); + insert_index = bindings_.size() - 1; + } else { // out-of-order binding number, need to insert into vector in-order + auto it = bindings_.begin(); + // Find currently binding's spot in vector + while (binding_num > it->binding) { + assert(it != bindings_.end()); + ++insert_index; + ++it; + } + bindings_.insert(it, safe_VkDescriptorSetLayoutBinding(&p_create_info->pBindings[i])); + } // In cases where we should ignore pImmutableSamplers make sure it's NULL if ((p_create_info->pBindings[i].pImmutableSamplers) && ((p_create_info->pBindings[i].descriptorType != VK_DESCRIPTOR_TYPE_SAMPLER) && (p_create_info->pBindings[i].descriptorType != VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER))) { - bindings_.back().pImmutableSamplers = nullptr; + bindings_[insert_index].pImmutableSamplers = nullptr; } if (p_create_info->pBindings[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC || p_create_info->pBindings[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) { @@ -55,6 +63,17 @@ cvdescriptorset::DescriptorSetLayout::DescriptorSetLayout(const VkDescriptorSetL dynamic_descriptor_count_ += p_create_info->pBindings[i].descriptorCount; } } + assert(bindings_.size() == binding_count_); + uint32_t global_index = 0; + // Vector order is finalized so create maps of bindings to indices + for (uint32_t i = 0; i < binding_count_; ++i) { + auto binding_num = bindings_[i].binding; + binding_to_index_map_[binding_num] = i; + binding_to_global_start_index_map_[binding_num] = global_index; + global_index += bindings_[i].descriptorCount ? bindings_[i].descriptorCount - 1 : 0; + binding_to_global_end_index_map_[binding_num] = global_index; + global_index += bindings_[i].descriptorCount ? 1 : 0; + } // Now create dyn offset array mapping for any dynamic descriptors uint32_t dyn_array_idx = 0; for (const auto &bc_pair : binding_to_dyn_count) { diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h index b455b35..5aabe62 100644 --- a/layers/descriptor_sets.h +++ b/layers/descriptor_sets.h @@ -67,23 +67,26 @@ * * Index vs Binding - A layout is created with an array of VkDescriptorSetLayoutBinding * where each array index will have a corresponding binding# that is defined in that struct. - * This class, therefore, provides utility functions where you can retrieve data for - * layout bindings based on either the original index into the pBindings array, or based - * on the binding#. - * Typically if you want to cover all of the bindings in a layout, you can do that by - * iterating over GetBindingCount() bindings and using the Get*FromIndex() functions. - * Otherwise, you can use the Get*FromBinding() functions to just grab binding info - * for a particular binding#. + * The binding#, then, is decoupled from VkDescriptorSetLayoutBinding index, which allows + * bindings to be defined out-of-order. This DescriptorSetLayout class, however, stores + * the bindings internally in-order. This is useful for operations which may "roll over" + * from a single binding to the next consecutive binding. * - * Global Index - The "Index" referenced above is the index into the original pBindings - * array. So there are as many indices as there are bindings. + * Note that although the bindings are stored in-order, there still may be "gaps" in the + * binding#. For example, if the binding creation order is 8, 7, 10, 3, 4, then the + * internal binding array will have five entries stored in binding order 3, 4, 7, 8, 10. + * To process all of the bindings in a layout you can iterate from 0 to GetBindingCount() + * and use the Get*FromIndex() functions for each index. To just process a single binding, + * use the Get*FromBinding() functions. + * + * Global Index - The binding vector index has as many indices as there are bindings. * This class also has the concept of a Global Index. For the global index functions, * there are as many global indices as there are descriptors in the layout. * For the global index, consider all of the bindings to be a flat array where - * descriptor 0 of pBinding[0] is index 0 and each descriptor in the layout increments - * from there. So if pBinding[0] in this example had descriptorCount of 10, then - * the GlobalStartIndex of pBinding[1] will be 10 where 0-9 are the global indices - * for pBinding[0]. + * descriptor 0 of of the lowest binding# is index 0 and each descriptor in the layout + * increments from there. So if the lowest binding# in this example had descriptorCount of + * 10, then the GlobalStartIndex of the 2nd lowest binding# will be 10 where 0-9 are the + * global indices for the lowest binding#. */ namespace cvdescriptorset { class DescriptorSetLayout { @@ -97,6 +100,7 @@ class DescriptorSetLayout { uint32_t GetTotalDescriptorCount() const { return descriptor_count_; }; uint32_t GetDynamicDescriptorCount() const { return dynamic_descriptor_count_; }; // For a given binding, return the number of descriptors in that binding and all successive bindings + // TODO : I think this can die with the update uint32_t GetConsecutiveDescriptorCountFromBinding(uint32_t) const; uint32_t GetBindingCount() const { return binding_count_; }; // Fill passed-in set with bindings @@ -109,8 +113,7 @@ class DescriptorSetLayout { // Return true if binding 1 beyond given exists and has same type, stageFlags & immutable sampler use bool IsNextBindingConsistent(const uint32_t) const; // Various Get functions that can either be passed a binding#, which will - // be automatically translated into the appropriate index from the original - // pBindings array, or the index# can be passed in directly + // be automatically translated into the appropriate index, or the index# can be passed in directly VkDescriptorSetLayoutBinding const *GetDescriptorSetLayoutBindingPtrFromBinding(const uint32_t) const; VkDescriptorSetLayoutBinding const *GetDescriptorSetLayoutBindingPtrFromIndex(const uint32_t) const; uint32_t GetDescriptorCountFromBinding(const uint32_t) const; -- 2.7.4