layers: LX235, Validate all Pipeline VBOs for CommandBuffers

Validation was throwing errors if a CB had extra VBOs bound, and was not
checking each VBO binding explicitly.

Conflicts:
	layers/draw_state.cpp
	tests/layer_validation_tests.cpp
diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp
index 7a9ceeb..b3173ff 100644
--- a/layers/draw_state.cpp
+++ b/layers/draw_state.cpp
@@ -1254,28 +1254,35 @@
             // If valid set is not bound throw an error
             if ((pCB->boundDescriptorSets.size() <= setIndex) || (!pCB->boundDescriptorSets[setIndex])) {
                 result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT, (VkDebugReportObjectTypeLUNARG) 0, 0, 0, DRAWSTATE_DESCRIPTOR_SET_NOT_BOUND, "DS",
-                        "VkPipeline %#" PRIxLEAST64 " uses set #%u but that set is not bound.", (uint64_t)pPipe->pipeline, setIndex);
+                    "VkPipeline %#" PRIxLEAST64 " uses set #%u but that set is not bound.", (uint64_t)pPipe->pipeline, setIndex);
             } else if (!verify_set_layout_compatibility(my_data, my_data->setMap[pCB->boundDescriptorSets[setIndex]], pPipe->graphicsPipelineCI.layout, setIndex, errorString)) {
                 // Set is bound but not compatible w/ overlapping pipelineLayout from PSO
                 VkDescriptorSet setHandle = my_data->setMap[pCB->boundDescriptorSets[setIndex]]->set;
                 result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_DESCRIPTOR_SET, (uint64_t)setHandle, 0, DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS",
-                    "VkDescriptorSet (%#" PRIxLEAST64 ") bound as set #%u is not compatible with overlapping VkPipelineLayout %#" PRIxLEAST64 " due to: %s", (uint64_t)setHandle, setIndex, (uint64_t)pPipe->graphicsPipelineCI.layout, errorString.c_str());
+                    "VkDescriptorSet (%#" PRIxLEAST64 ") bound as set #%u is not compatible with overlapping VkPipelineLayout %#" PRIxLEAST64 " due to: %s",
+                    (uint64_t)setHandle, setIndex, (uint64_t)pPipe->graphicsPipelineCI.layout, errorString.c_str());
             }
         }
     }
+
     // Verify Vtx binding
-    if (MAX_BINDING != pCB->lastVtxBinding) {
-        if (pCB->lastVtxBinding >= pPipe->vtxBindingCount) {
-            if (0 == pPipe->vtxBindingCount) {
+    if (pPipe->vtxBindingCount > 0) {
+        VkPipelineVertexInputStateCreateInfo *vtxInCI = &pPipe->vertexInputCI;
+        for (auto i = 0; i < vtxInCI->vertexBindingDescriptionCount; i++) {
+            if ((pCB->boundVtxBuffers.size() < (i+1)) || (pCB->boundVtxBuffers[i] == VK_NULL_HANDLE)) {
                 result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT, (VkDebugReportObjectTypeLUNARG) 0, 0, 0, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS",
-                        "Vtx Buffer Index %u was bound, but no vtx buffers are attached to PSO.", pCB->lastVtxBinding);
-            }
-            else {
-                result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT, (VkDebugReportObjectTypeLUNARG) 0, 0, 0, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS",
-                        "Vtx binding Index of %u exceeds PSO pVertexBindingDescriptions max array index of %u.", pCB->lastVtxBinding, (pPipe->vtxBindingCount - 1));
+                    "The Pipeline State Object (%#" PRIxLEAST64 ") expects that this Command Buffer's vertex binding Index %d should be set via vkCmdBindVertexBuffers.",
+                    (uint64_t)pCB->lastBoundPipeline, i);
             }
         }
+    } else {
+        if (!pCB->boundVtxBuffers.empty()) {
+            result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_PERF_WARN_BIT, (VkDebugReportObjectTypeLUNARG) 0, 0, 0, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS,
+                "DS", "Vertex buffers are bound to command buffer (%#" PRIxLEAST64 ") but no vertex buffers are attached to this Pipeline State Object (%#" PRIxLEAST64 ").",
+                (uint64_t)pCB->commandBuffer, (uint64_t)pCB->lastBoundPipeline);
+        }
     }
+
     // If Viewport or scissors are dynamic, verify that dynamic count matches PSO count
     VkBool32 dynViewport = isDynamic(pPipe, VK_DYNAMIC_STATE_VIEWPORT);
     VkBool32 dynScissor = isDynamic(pPipe, VK_DYNAMIC_STATE_SCISSOR);
@@ -2360,7 +2367,7 @@
         pCB->framebuffer = 0;
         pCB->boundDescriptorSets.clear();
         pCB->imageLayoutMap.clear();
-        pCB->lastVtxBinding = MAX_BINDING;
+        pCB->boundVtxBuffers.clear();
     }
 }
 
@@ -3916,19 +3923,23 @@
 }
 
 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers(
-    VkCommandBuffer                                 commandBuffer,
+    VkCommandBuffer                             commandBuffer,
     uint32_t                                    startBinding,
     uint32_t                                    bindingCount,
-    const VkBuffer*                             pBuffers,
-    const VkDeviceSize*                         pOffsets)
+    const VkBuffer                             *pBuffers,
+    const VkDeviceSize                         *pOffsets)
 {
     VkBool32 skipCall = VK_FALSE;
     layer_data* dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
     GLOBAL_CB_NODE* pCB = getCBNode(dev_data, commandBuffer);
     if (pCB) {
         if (pCB->state == CB_RECORDING) {
-            /* TODO: Need to track all the vertex buffers, not just last one */
-            pCB->lastVtxBinding = startBinding + bindingCount -1;
+            if ((startBinding + bindingCount) > pCB->boundVtxBuffers.size()) {
+                pCB->boundVtxBuffers.resize(startBinding+bindingCount, VK_NULL_HANDLE);
+            }
+            for (auto i = 0; i < bindingCount; i++) {
+                pCB->boundVtxBuffers[i+startBinding] = pBuffers[i];
+            }
             addCmd(dev_data, pCB, CMD_BINDVERTEXBUFFER);
         } else {
             skipCall |= report_error_no_cb_begin(dev_data, commandBuffer, "vkCmdBindVertexBuffer()");