#include "buffer_validation.h"
#include <sstream>
#include <algorithm>
+#include <memory>
struct BindingNumCmp {
bool operator()(const VkDescriptorSetLayoutBinding *a, const VkDescriptorSetLayoutBinding *b) const {
// 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;
}
}
-// 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());
// 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
}
// 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;
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;
}
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
}
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;
}
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()) {
// 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
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) {}
* 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_; }
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;
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));
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...
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.
// 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; }