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/include/vulkan.h b/include/vulkan.h
index f233790..df7c461 100644
--- a/include/vulkan.h
+++ b/include/vulkan.h
@@ -1831,6 +1831,7 @@
} VkSamplerCreateInfo;
typedef struct VkDescriptorSetLayoutBinding {
+ uint32_t binding;
VkDescriptorType descriptorType;
uint32_t arraySize;
VkShaderStageFlags stageFlags;
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,
diff --git a/tests/layer_validation_tests.cpp b/tests/layer_validation_tests.cpp
index 3cbb2c6..079981e 100644
--- a/tests/layer_validation_tests.cpp
+++ b/tests/layer_validation_tests.cpp
@@ -898,6 +898,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -1115,6 +1116,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -1376,6 +1378,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -1476,6 +1479,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -1537,6 +1541,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -1652,6 +1657,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -1817,6 +1823,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -1916,6 +1923,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -2040,6 +2048,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -2145,6 +2154,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -2249,6 +2259,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -2406,6 +2417,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -2846,6 +2858,7 @@
err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool);
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -2942,6 +2955,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -3039,6 +3053,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -3134,6 +3149,7 @@
err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool);
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -3230,6 +3246,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -3304,6 +3321,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -3404,10 +3422,12 @@
err = vkCreateDescriptorPool(m_device->device(), &ds_pool_ci, NULL, &ds_pool);
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding[2] = {};
+ dsl_binding[0].binding = 0;
dsl_binding[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding[0].arraySize = 1;
dsl_binding[0].stageFlags = VK_SHADER_STAGE_ALL;
dsl_binding[0].pImmutableSamplers = NULL;
+ dsl_binding[1].binding = 1;
dsl_binding[1].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
dsl_binding[1].arraySize = 1;
dsl_binding[1].stageFlags = VK_SHADER_STAGE_ALL;
@@ -3548,6 +3568,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -3639,6 +3660,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -3744,6 +3766,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
@@ -5456,6 +5479,7 @@
ASSERT_VK_SUCCESS(err);
VkDescriptorSetLayoutBinding dsl_binding = {};
+ dsl_binding.binding = 0;
dsl_binding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
dsl_binding.arraySize = 1;
dsl_binding.stageFlags = VK_SHADER_STAGE_ALL;
diff --git a/tests/vkrenderframework.cpp b/tests/vkrenderframework.cpp
index 2fa1e61..1d003c9 100644
--- a/tests/vkrenderframework.cpp
+++ b/tests/vkrenderframework.cpp
@@ -501,6 +501,7 @@
vector<VkDescriptorSetLayoutBinding> bindings;
bindings.resize(m_type_counts.size());
for (int i = 0; i < m_type_counts.size(); i++) {
+ bindings[i].binding = i;
bindings[i].descriptorType = m_type_counts[i].type;
bindings[i].arraySize = m_type_counts[i].descriptorCount;
bindings[i].stageFlags = VK_SHADER_STAGE_ALL;