layers: Validate secondary command buffers are most recently bound.
authorMichael Lentine <mlentine@google.com>
Wed, 3 Feb 2016 16:55:23 +0000 (10:55 -0600)
committerTobin Ehlis <tobine@google.com>
Thu, 4 Feb 2016 19:20:17 +0000 (12:20 -0700)
Secondary cmd buffer bound to new primary cmd buffer cannot be submitted
under the first primary cmd buffer.

This is based on spec valid usage restriction in vkQueueSubmit:

Any given element of pCommandBuffers must not contain commands that execute a
secondary command buffer, if that secondary command buffer has been recorded in
another primary command buffer after it was recorded into this VkCommandBuffer

layers/draw_state.cpp
layers/draw_state.h

index ee343dbda94a3c42e46dadc1d7e897a63a19e0df..018795243150a746774979e2ebbf957bcb58a9cd 100644 (file)
@@ -2805,6 +2805,7 @@ static void resetCB(layer_data* my_data, const VkCommandBuffer cb)
         pCB->imageLayoutMap.clear();
         pCB->drawData.clear();
         pCB->currentDrawData.buffers.clear();
+        pCB->primaryCommandBuffer = VK_NULL_HANDLE;
         pCB->secondaryCommandBuffers.clear();
         pCB->dynamicOffsets.clear();
     }
@@ -3455,6 +3456,20 @@ static VkBool32 validateCommandBufferState(layer_data *dev_data,
                 dev_data, dev_data->commandBufferMap[secondaryCmdBuffer]);
             GLOBAL_CB_NODE* pSubCB = getCBNode(dev_data, secondaryCmdBuffer);
             skipCall |= validateCommandBufferSimultaneousUse(dev_data, pSubCB);
+            if (pSubCB->primaryCommandBuffer != pCB->commandBuffer) {
+                log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
+                        VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
+                        __LINE__,
+                        DRAWSTATE_COMMAND_BUFFER_SINGLE_SUBMIT_VIOLATION, "DS",
+                        "CB %#" PRIxLEAST64
+                        " was submitted with secondary buffer %#" PRIxLEAST64
+                        " but that buffer has subsequently been bound to "
+                        "primary cmd buffer %#" PRIxLEAST64 ".",
+                        reinterpret_cast<uint64_t>(pCB->commandBuffer),
+                        reinterpret_cast<uint64_t>(secondaryCmdBuffer),
+                        reinterpret_cast<uint64_t>(
+                            pSubCB->primaryCommandBuffer));
+            }
         }
     }
     if ((pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) &&
@@ -6593,6 +6608,7 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands(VkCommandBuffer
                     pCB->beginInfo.flags &= ~VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
                 }
             }
+            pSubCB->primaryCommandBuffer = pCB->commandBuffer;
             pCB->secondaryCommandBuffers.insert(pSubCB->commandBuffer);
             dev_data->globalInFlightCmdBuffers.insert(pSubCB->commandBuffer);
         }
index 0726e0f6bce378ec25fc3807224828de561bda3a..52b259c85ede37af3bcf5296be3bc78fcf5b8f6e 100755 (executable)
@@ -608,7 +608,9 @@ typedef struct _GLOBAL_CB_NODE {
     unordered_map<VkImage, IMAGE_CMD_BUF_NODE> imageLayoutMap;
     vector<DRAW_DATA>            drawData;
     DRAW_DATA                    currentDrawData;
-    // If cmd buffer is primary, track secondary command buffers pending execution
+    VkCommandBuffer primaryCommandBuffer;
+    // If cmd buffer is primary, track secondary command buffers pending
+    // execution
     std::unordered_set<VkCommandBuffer> secondaryCommandBuffers;
     vector<uint32_t>             dynamicOffsets; // one dynamic offset per dynamic descriptor bound to this CB
 } GLOBAL_CB_NODE;