aboutsummaryrefslogtreecommitdiff
path: root/layers/descriptor_sets.cpp
diff options
context:
space:
mode:
authorJohn Zulauf <jzulauf@lunarg.com>2018-02-16 12:58:37 -0700
committerjzulauf-lunarg <32470354+jzulauf-lunarg@users.noreply.github.com>2018-03-07 13:11:29 -0700
commit76fbd478fcd0bb52f53478c2a546b4d486155836 (patch)
tree7a52f7351a284c21f7585da75c6772a7ef047618 /layers/descriptor_sets.cpp
parent7bb723b747121736713d02d10717c80f5e213e65 (diff)
downloadusermoji-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.cpp191
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) {}