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<uint32_t, uint32_t> 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) {
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) {
*
* 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 {
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
// 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;