bug-14746: add batched submit for semaphores and command buffers
diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp
index 7a33ffb..d36b1af 100755
--- a/layers/draw_state.cpp
+++ b/layers/draw_state.cpp
@@ -1543,32 +1543,35 @@
                                    pCount, pProperties);
 }
 
-VK_LAYER_EXPORT VkResult VKAPI vkQueueSubmit(VkQueue queue, uint32_t cmdBufferCount, const VkCmdBuffer* pCmdBuffers, VkFence fence)
+VK_LAYER_EXPORT VkResult VKAPI vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmitInfo, VkFence fence)
 {
     VkBool32 skipCall = VK_FALSE;
     GLOBAL_CB_NODE* pCB = NULL;
     layer_data* dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
-    for (uint32_t i=0; i < cmdBufferCount; i++) {
-        // Validate that cmd buffers have been updated
-        pCB = getCBNode(dev_data, pCmdBuffers[i]);
-        loader_platform_thread_lock_mutex(&globalLock);
-        pCB->submitCount++; // increment submit count
-        if ((pCB->beginInfo.flags & VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT) && (pCB->submitCount > 1)) {
-            skipCall |= log_msg(dev_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, 0, 0, DRAWSTATE_CMD_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS",
-                    "CB %#" PRIxLEAST64 " was begun w/ VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT set, but has been submitted %#" PRIxLEAST64 " times.", reinterpret_cast<uint64_t>(pCB->cmdBuffer), pCB->submitCount);
-        }
-        if (CB_UPDATE_COMPLETE != pCB->state) {
-            // Flag error for using CB w/o vkEndCommandBuffer() called
-            // TODO : How to pass cb as srcObj?
-            skipCall |= log_msg(dev_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, 0, 0, DRAWSTATE_NO_END_CMD_BUFFER, "DS",
-                    "You must call vkEndCommandBuffer() on CB %#" PRIxLEAST64 " before this call to vkQueueSubmit()!", reinterpret_cast<uint64_t>(pCB->cmdBuffer));
+    for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
+        const VkSubmitInfo *submit = &pSubmitInfo[submit_idx];
+        for (uint32_t i=0; i < submit->cmdBufferCount; i++) {
+            // Validate that cmd buffers have been updated
+            pCB = getCBNode(dev_data, submit->pCommandBuffers[i]);
+            loader_platform_thread_lock_mutex(&globalLock);
+            pCB->submitCount++; // increment submit count
+            if ((pCB->beginInfo.flags & VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT) && (pCB->submitCount > 1)) {
+                skipCall |= log_msg(dev_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, 0, 0, DRAWSTATE_CMD_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS",
+                        "CB %#" PRIxLEAST64 " was begun w/ VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT set, but has been submitted %#" PRIxLEAST64 " times.", reinterpret_cast<uint64_t>(pCB->cmdBuffer), pCB->submitCount);
+            }
+            if (CB_UPDATE_COMPLETE != pCB->state) {
+                // Flag error for using CB w/o vkEndCommandBuffer() called
+                // TODO : How to pass cb as srcObj?
+                skipCall |= log_msg(dev_data->report_data, VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, 0, 0, DRAWSTATE_NO_END_CMD_BUFFER, "DS",
+                        "You must call vkEndCommandBuffer() on CB %#" PRIxLEAST64 " before this call to vkQueueSubmit()!", reinterpret_cast<uint64_t>(pCB->cmdBuffer));
+                loader_platform_thread_unlock_mutex(&globalLock);
+                return VK_ERROR_VALIDATION_FAILED;
+            }
             loader_platform_thread_unlock_mutex(&globalLock);
-            return VK_ERROR_VALIDATION_FAILED;
         }
-        loader_platform_thread_unlock_mutex(&globalLock);
     }
     if (VK_FALSE == skipCall)
-        return dev_data->device_dispatch_table->QueueSubmit(queue, cmdBufferCount, pCmdBuffers, fence);
+        return dev_data->device_dispatch_table->QueueSubmit(queue, submitCount, pSubmitInfo, fence);
     return VK_ERROR_VALIDATION_FAILED;
 }
 
diff --git a/layers/mem_tracker.cpp b/layers/mem_tracker.cpp
index 4a1e85f..704e007 100644
--- a/layers/mem_tracker.cpp
+++ b/layers/mem_tracker.cpp
@@ -1141,8 +1141,8 @@
 
 VK_LAYER_EXPORT VkResult VKAPI vkQueueSubmit(
     VkQueue             queue,
-    uint32_t            cmdBufferCount,
-    const VkCmdBuffer  *pCmdBuffers,
+    uint32_t            submitCount,
+    const VkSubmitInfo *pSubmitInfo,
     VkFence             fence)
 {
     VkResult result = VK_ERROR_VALIDATION_FAILED;
@@ -1155,17 +1155,20 @@
 
     print_mem_list(queue);
     printCBList(queue);
-    for (uint32_t i = 0; i < cmdBufferCount; i++) {
-        pCBInfo = get_cmd_buf_info(pCmdBuffers[i]);
-        pCBInfo->fenceId = fenceId;
-        pCBInfo->lastSubmittedFence = fence;
-        pCBInfo->lastSubmittedQueue = queue;
+    for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
+        const VkSubmitInfo *submit = &pSubmitInfo[submit_idx];
+        for (uint32_t i = 0; i < submit->cmdBufferCount; i++) {
+            pCBInfo = get_cmd_buf_info(submit->pCommandBuffers[i]);
+            pCBInfo->fenceId = fenceId;
+            pCBInfo->lastSubmittedFence = fence;
+            pCBInfo->lastSubmittedQueue = queue;
+        }
     }
 
     loader_platform_thread_unlock_mutex(&globalLock);
     if (VK_FALSE == skipCall) {
         result = get_dispatch_table(mem_tracker_device_table_map, queue)->QueueSubmit(
-            queue, cmdBufferCount, pCmdBuffers, fence);
+            queue, submitCount, pSubmitInfo, fence);
     }
     return result;
 }
diff --git a/layers/param_checker.cpp b/layers/param_checker.cpp
index de4890a..9772779 100644
--- a/layers/param_checker.cpp
+++ b/layers/param_checker.cpp
@@ -2199,15 +2199,17 @@
 
 VK_LAYER_EXPORT VkResult VKAPI vkQueueSubmit(
     VkQueue queue,
-    uint32_t cmdBufferCount,
-    const VkCmdBuffer* pCmdBuffers,
+    uint32_t submitCount,
+    const VkSubmitInfo* pSubmitInfo,
     VkFence fence)
 {
-    PreQueueSubmit(queue, pCmdBuffers);
+    for (uint32_t i = 0; i < submitCount; i++) {
+        PreQueueSubmit(queue, pSubmitInfo[i].pCommandBuffers);
+    }
 
-    VkResult result = get_dispatch_table(pc_device_table_map, queue)->QueueSubmit(queue, cmdBufferCount, pCmdBuffers, fence);
+    VkResult result = get_dispatch_table(pc_device_table_map, queue)->QueueSubmit(queue, submitCount, pSubmitInfo, fence);
 
-    PostQueueSubmit(queue, cmdBufferCount, fence, result);
+    PostQueueSubmit(queue, submitCount, fence, result);
 
     return result;
 }
diff --git a/layers/screenshot.cpp b/layers/screenshot.cpp
index c468257..05e7414 100644
--- a/layers/screenshot.cpp
+++ b/layers/screenshot.cpp
@@ -244,7 +244,17 @@
     err = pTableCmdBuffer->EndCommandBuffer(cmdBuffer);
     assert(!err);
 
-    err = pTableQueue->QueueSubmit(queue, 1, &cmdBuffer, VK_NULL_HANDLE);
+    VkFence nullFence = { VK_NULL_HANDLE };
+    VkSubmitInfo submit_info = {
+        .waitSemCount = 0,
+        .pWaitSemaphores = NULL,
+        .cmdBufferCount = 1,
+        .pCommandBuffers = &cmdBuffer,
+        .signalSemCount = 0,
+        .pSignalSemaphores = NULL
+    };
+
+    err = pTableQueue->QueueSubmit(queue, 1, &submit_info, nullFence);
     assert(!err);
 
     err = pTableQueue->QueueWaitIdle(queue);