bug 15022: Need a way to specify dummy descriptors for unused bindings (WIP)
Add binding to VkDescriptorSetLayoutBinding.
https://cvs.khronos.org/bugzilla/show_bug.cgi?id=15022
diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp
index 17ebb48..fda3b52 100755
--- a/layers/draw_state.cpp
+++ b/layers/draw_state.cpp
@@ -697,7 +697,9 @@
static uint32_t getBindingStartIndex(const LAYOUT_NODE* pLayout, const uint32_t binding)
{
uint32_t offsetIndex = 0;
- for (uint32_t i = 0; i<binding; i++) {
+ for (uint32_t i = 0; i < pLayout->createInfo.bindingCount; i++) {
+ if (pLayout->createInfo.pBinding[i].binding == binding)
+ break;
offsetIndex += pLayout->createInfo.pBinding[i].arraySize;
}
return offsetIndex;
@@ -706,8 +708,10 @@
static uint32_t getBindingEndIndex(const LAYOUT_NODE* pLayout, const uint32_t binding)
{
uint32_t offsetIndex = 0;
- for (uint32_t i = 0; i<=binding; i++) {
+ for (uint32_t i = 0; i < pLayout->createInfo.bindingCount; i++) {
offsetIndex += pLayout->createInfo.pBinding[i].arraySize;
+ if (pLayout->createInfo.pBinding[i].binding == binding)
+ break;
}
return offsetIndex-1;
}
@@ -1024,7 +1028,7 @@
uint32_t binding = 0, endIndex = 0;
binding = pWDS[i].dstBinding;
// Make sure that layout being updated has the binding being updated
- if (pLayout->createInfo.bindingCount < binding) {
+ if (pLayout->bindings.find(binding) == pLayout->bindings.end()) {
skipCall |= log_msg(my_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t) ds, 0, DRAWSTATE_INVALID_UPDATE_INDEX, "DS",
"Descriptor Set %p does not have binding to match update binding %u for update type %s!", ds, binding, string_VkStructureType(pUpdate->sType));
} else {
@@ -1075,11 +1079,11 @@
pSrcLayout = pSrcSet->pLayout;
pDstLayout = pDstSet->pLayout;
// Validate that src binding is valid for src set layout
- if (pSrcLayout->createInfo.bindingCount < pCDS[i].srcBinding) {
+ if (pSrcLayout->bindings.find(pCDS[i].srcBinding) == pSrcLayout->bindings.end()) {
skipCall |= log_msg(my_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t) pSrcSet->set, 0, DRAWSTATE_INVALID_UPDATE_INDEX, "DS",
"Copy descriptor update %u has srcBinding %u which is out of bounds for underlying SetLayout %#" PRIxLEAST64 " which only has bindings 0-%u.",
i, pCDS[i].srcBinding, (uint64_t) pSrcLayout->layout, pSrcLayout->createInfo.bindingCount-1);
- } else if (pDstLayout->createInfo.bindingCount < pCDS[i].dstBinding) {
+ } else if (pDstLayout->bindings.find(pCDS[i].dstBinding) == pDstLayout->bindings.end()) {
skipCall |= log_msg(my_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t) pDstSet->set, 0, DRAWSTATE_INVALID_UPDATE_INDEX, "DS",
"Copy descriptor update %u has dstBinding %u which is out of bounds for underlying SetLayout %#" PRIxLEAST64 " which only has bindings 0-%u.",
i, pCDS[i].dstBinding, (uint64_t) pDstLayout->layout, pDstLayout->createInfo.bindingCount-1);
@@ -2029,8 +2033,17 @@
memcpy((void*)&pNewNode->createInfo, pCreateInfo, sizeof(VkDescriptorSetLayoutCreateInfo));
pNewNode->createInfo.pBinding = new VkDescriptorSetLayoutBinding[pCreateInfo->bindingCount];
memcpy((void*)pNewNode->createInfo.pBinding, pCreateInfo->pBinding, sizeof(VkDescriptorSetLayoutBinding)*pCreateInfo->bindingCount);
+ // g++ does not like reserve with size 0
+ if (pCreateInfo->bindingCount)
+ pNewNode->bindings.reserve(pCreateInfo->bindingCount);
uint32_t totalCount = 0;
for (uint32_t i=0; i<pCreateInfo->bindingCount; i++) {
+ if (!pNewNode->bindings.insert(pCreateInfo->pBinding[i].binding).second) {
+ if (log_msg(dev_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, (uint64_t) *pSetLayout, 0, DRAWSTATE_INVALID_LAYOUT, "DS",
+ "duplicated binding number in VkDescriptorSetLayoutBinding"))
+ return VK_ERROR_VALIDATION_FAILED;
+ }
+
totalCount += pCreateInfo->pBinding[i].arraySize;
if (pCreateInfo->pBinding[i].pImmutableSamplers) {
VkSampler** ppIS = (VkSampler**)&pNewNode->createInfo.pBinding[i].pImmutableSamplers;
diff --git a/layers/draw_state.h b/layers/draw_state.h
index 3aa9494..83b494b 100755
--- a/layers/draw_state.h
+++ b/layers/draw_state.h
@@ -148,6 +148,7 @@
uint32_t endIndex; // last index of this layout
vector<VkDescriptorType> descriptorTypes; // Type per descriptor in this layout to verify correct updates
vector<VkShaderStageFlags> stageFlags; // stageFlags per descriptor in this layout to verify correct updates
+ unordered_set<uint32_t> bindings;
} LAYOUT_NODE;
// Store layouts and pushconstants for PipelineLayout
struct PIPELINE_LAYOUT_NODE {
diff --git a/layers/shader_checker.cpp b/layers/shader_checker.cpp
index 63c17a0..2b078b7 100644
--- a/layers/shader_checker.cpp
+++ b/layers/shader_checker.cpp
@@ -26,6 +26,7 @@
#include <assert.h>
#include <map>
#include <unordered_map>
+#include <unordered_set>
#include <map>
#include <vector>
#include <string>
@@ -53,8 +54,8 @@
VkLayerInstanceDispatchTable* instance_dispatch_table;
std::unordered_map<VkShaderModule, shader_module *> shader_module_map;
- std::unordered_map<VkDescriptorSetLayout, std::vector<VkDescriptorSetLayoutBinding>*> descriptor_set_layout_map;
- std::unordered_map<VkPipelineLayout, std::vector<std::vector<VkDescriptorSetLayoutBinding>*>*> pipeline_layout_map;
+ std::unordered_map<VkDescriptorSetLayout, std::unordered_set<uint32_t>*> descriptor_set_layout_map;
+ std::unordered_map<VkPipelineLayout, std::vector<std::unordered_set<uint32_t>*>*> pipeline_layout_map;
std::unordered_map<VkRenderPass, render_pass *> render_pass_map;
layer_data() :
@@ -133,8 +134,11 @@
if (VK_SUCCESS == result) {
loader_platform_thread_lock_mutex(&globalLock);
auto& bindings = my_data->descriptor_set_layout_map[*pSetLayout];
- bindings = new std::vector<VkDescriptorSetLayoutBinding>(
- pCreateInfo->pBinding, pCreateInfo->pBinding + pCreateInfo->bindingCount);
+ bindings = new std::unordered_set<uint32_t>();
+ bindings->reserve(pCreateInfo->bindingCount);
+ for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++)
+ bindings->insert(pCreateInfo->pBinding[i].binding);
+
loader_platform_thread_unlock_mutex(&globalLock);
}
@@ -153,7 +157,7 @@
if (VK_SUCCESS == result) {
loader_platform_thread_lock_mutex(&globalLock);
auto& layouts = my_data->pipeline_layout_map[*pPipelineLayout];
- layouts = new std::vector<std::vector<VkDescriptorSetLayoutBinding>*>();
+ layouts = new std::vector<std::unordered_set<uint32_t>*>();
layouts->reserve(pCreateInfo->setLayoutCount);
for (unsigned i = 0; i < pCreateInfo->setLayoutCount; i++) {
layouts->push_back(my_data->descriptor_set_layout_map[pCreateInfo->pSetLayouts[i]]);
@@ -979,22 +983,19 @@
};
-static VkDescriptorSetLayoutBinding *
-find_descriptor_binding(std::vector<std::vector<VkDescriptorSetLayoutBinding>*>* layout,
- std::pair<unsigned, unsigned> slot)
+static bool
+has_descriptor_binding(std::vector<std::unordered_set<uint32_t>*>* layout,
+ std::pair<unsigned, unsigned> slot)
{
if (!layout)
- return nullptr;
+ return false;
if (slot.first >= layout->size())
- return nullptr;
+ return false;
auto set = (*layout)[slot.first];
- if (slot.second >= set->size())
- return nullptr;
-
- return &(*set)[slot.second];
+ return (set->find(slot.second) != set->end());
}
static uint32_t get_shader_stage_id(VkShaderStageFlagBits stage)
@@ -1046,9 +1047,9 @@
for (auto it = descriptor_uses.begin(); it != descriptor_uses.end(); it++) {
/* find the matching binding */
- auto binding = find_descriptor_binding(layout, it->first);
+ auto found = has_descriptor_binding(layout, it->first);
- if (binding == nullptr) {
+ if (!found) {
char type_name[1024];
describe_type(type_name, module, it->second.type_id);
if (log_msg(my_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_DEVICE, /*dev*/0, 0,