layers: Add validation check to enforce ONE_TIME_SUBMIT of cmd buffers
Track createInfo and beginInfo independently per cmdBuffer & check begin flags at QueueSubmit time to verify cmd buffer not submitted multiple times if VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT is set.
Add CmdBufferTwoSubmits test to verify this check.
diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp
index 0e82f3b..c6a82d9 100644
--- a/layers/draw_state.cpp
+++ b/layers/draw_state.cpp
@@ -1111,13 +1111,11 @@
cmd_list.pop_back();
}
pCB->pCmds.clear();
- // Reset CB state
- VkFlags saveFlags = pCB->flags;
- VkCmdPool savedPool = pCB->pool;
+ // Reset CB state (need to save createInfo)
+ VkCmdBufferCreateInfo saveCBCI = pCB->createInfo;
memset(pCB, 0, sizeof(GLOBAL_CB_NODE));
pCB->cmdBuffer = cb;
- pCB->flags = saveFlags;
- pCB->pool = savedPool;
+ pCB->createInfo = saveCBCI;
pCB->lastVtxBinding = MAX_BINDING;
}
}
@@ -1468,6 +1466,11 @@
// Validate that cmd buffers have been updated
pCB = getCBNode(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)) {
+ log_msg(mdd(queue), VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, 0, 0, DRAWSTATE_CMD_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS",
+ "CB %#" PRIxLEAST64 " was created w/ VK_CMD_BUFFER_OPTIMIZE_ONE_TIME_SUBMIT_BIT set, but has been submitted %#" PRIxLEAST64 " times.", reinterpret_cast<VkUintPtrLeast64>(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?
@@ -1986,8 +1989,7 @@
GLOBAL_CB_NODE* pCB = new GLOBAL_CB_NODE;
memset(pCB, 0, sizeof(GLOBAL_CB_NODE));
pCB->cmdBuffer = *pCmdBuffer;
- pCB->flags = pCreateInfo->flags;
- pCB->pool = pCreateInfo->cmdPool;
+ pCB->createInfo = *pCreateInfo;
pCB->lastVtxBinding = MAX_BINDING;
pCB->level = pCreateInfo->level;
cmdBufferMap[*pCmdBuffer] = pCB;
@@ -2015,19 +2017,17 @@
"vkCreateCommandBuffer(): Secondary Command Buffers (%p) must specify framebuffer and renderpass parameters", (void*)cmdBuffer);
}
}
+ pCB->beginInfo = *pBeginInfo;
+ } else {
+ // TODO : Need to pass cmdBuffer as objType here
+ log_msg(mdd(cmdBuffer), VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, 0, 0, DRAWSTATE_INVALID_CMD_BUFFER, "DS",
+ "In vkBeginCommandBuffer() and unable to find CmdBuffer Node for CB %p!", (void*)cmdBuffer);
}
VkResult result = get_dispatch_table(draw_state_device_table_map, cmdBuffer)->BeginCommandBuffer(cmdBuffer, pBeginInfo);
if (VK_SUCCESS == result) {
- GLOBAL_CB_NODE* pCB = getCBNode(cmdBuffer);
- if (pCB) {
- if (CB_NEW != pCB->state)
- resetCB(cmdBuffer);
- pCB->state = CB_UPDATE_ACTIVE;
- } else {
- // TODO : Need to pass cmdBuffer as objType here
- log_msg(mdd(cmdBuffer), VK_DBG_REPORT_ERROR_BIT, VK_OBJECT_TYPE_COMMAND_BUFFER, 0, 0, DRAWSTATE_INVALID_CMD_BUFFER, "DS",
- "In vkBeginCommandBuffer() and unable to find CmdBuffer Node for CB %p!", (void*)cmdBuffer);
- }
+ if (CB_NEW != pCB->state)
+ resetCB(cmdBuffer);
+ pCB->state = CB_UPDATE_ACTIVE;
updateCBTracking(cmdBuffer);
}
return result;