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;