diff options
| author | Tobin Ehlis <tobine@google.com> | 2016-04-18 15:45:20 -0600 |
|---|---|---|
| committer | Tobin Ehlis <tobine@google.com> | 2016-04-21 07:32:08 -0600 |
| commit | 685d2e1ff51eb668a715d5f7e59999cd404b64ef (patch) | |
| tree | 637832b7b9af778f6ae6468cefc0509249f6abe3 /layers | |
| parent | 3e2f58b5b8dd321462366d9d6c6cf54e8c9b4b07 (diff) | |
| download | usermoji-685d2e1ff51eb668a715d5f7e59999cd404b64ef.tar.xz | |
layers: Cleanup core_validation fence tracking
There were two separate mechanisms for tracking fence state in core_validation.
This change removes the last[Retired|Submitted]Id per queue method.
We also no longer over-write the fence createInfo to track fence state, but
just use the needsSignaled bool for all fence state tracking.
Finally, there was a validation test/check flagging an error if an
unsignaled fence was reset, but this is valid based on the spec so removed
the check and changed test to be a positive test expected to pass.
Diffstat (limited to 'layers')
| -rw-r--r-- | layers/core_validation.cpp | 254 | ||||
| -rw-r--r-- | layers/core_validation.h | 25 |
2 files changed, 73 insertions, 206 deletions
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp index 454de2ef..02800890 100644 --- a/layers/core_validation.cpp +++ b/layers/core_validation.cpp @@ -101,7 +101,6 @@ struct layer_data { VkLayerInstanceDispatchTable *instance_dispatch_table; devExts device_extensions; - uint64_t currentFenceId; unordered_set<VkQueue> queues; // all queues under given device // Global set of all cmdBuffers that are inFlight on this device unordered_set<VkCommandBuffer> globalInFlightCmdBuffers; @@ -138,8 +137,7 @@ struct layer_data { layer_data() : report_data(nullptr), device_dispatch_table(nullptr), instance_dispatch_table(nullptr), device_extensions(), - currentFenceId(1), device(VK_NULL_HANDLE), phys_dev_properties{}, - phys_dev_mem_props{} {}; + device(VK_NULL_HANDLE), phys_dev_properties{}, phys_dev_mem_props{} {}; }; // TODO : Do we need to guard access to layer_data_map w/ lock? @@ -263,69 +261,6 @@ template layer_data *get_my_data_ptr<layer_data>(void *data_key, std::unordered_ static GLOBAL_CB_NODE *getCBNode(layer_data *, const VkCommandBuffer); #if MTMERGESOURCE -// Add a fence, creating one if necessary to our list of fences/fenceIds -static bool add_fence_info(layer_data *my_data, VkFence fence, VkQueue queue, uint64_t *fenceId) { - bool skipCall = false; - *fenceId = my_data->currentFenceId++; - - // If no fence, create an internal fence to track the submissions - if (fence != VK_NULL_HANDLE) { - my_data->fenceMap[fence].fenceId = *fenceId; - my_data->fenceMap[fence].queue = queue; - // Validate that fence is in UNSIGNALED state - VkFenceCreateInfo *pFenceCI = &(my_data->fenceMap[fence].createInfo); - if (pFenceCI->flags & VK_FENCE_CREATE_SIGNALED_BIT) { - skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, - (uint64_t)fence, __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", - "Fence %#" PRIxLEAST64 " submitted in SIGNALED state. Fences must be reset before being submitted", - (uint64_t)fence); - } - } else { - // TODO : Do we need to create an internal fence here for tracking purposes? - } - // Update most recently submitted fence and fenceId for Queue - my_data->queueMap[queue].lastSubmittedId = *fenceId; - return skipCall; -} - -// Record information when a fence is known to be signalled -static void update_fence_tracking(layer_data *my_data, VkFence fence) { - auto fence_item = my_data->fenceMap.find(fence); - if (fence_item != my_data->fenceMap.end()) { - FENCE_NODE *pCurFenceInfo = &(*fence_item).second; - VkQueue queue = pCurFenceInfo->queue; - auto queue_item = my_data->queueMap.find(queue); - if (queue_item != my_data->queueMap.end()) { - QUEUE_NODE *pQueueInfo = &(*queue_item).second; - if (pQueueInfo->lastRetiredId < pCurFenceInfo->fenceId) { - pQueueInfo->lastRetiredId = pCurFenceInfo->fenceId; - } - } - } - - // Update fence state in fenceCreateInfo structure - auto pFCI = &(my_data->fenceMap[fence].createInfo); - pFCI->flags = static_cast<VkFenceCreateFlags>(pFCI->flags | VK_FENCE_CREATE_SIGNALED_BIT); -} - -// Helper routine that updates the fence list for a specific queue to all-retired -static void retire_queue_fences(layer_data *my_data, VkQueue queue) { - QUEUE_NODE *pQueueInfo = &my_data->queueMap[queue]; - // Set queue's lastRetired to lastSubmitted indicating all fences completed - pQueueInfo->lastRetiredId = pQueueInfo->lastSubmittedId; -} - -// Helper routine that updates all queues to all-retired -static void retire_device_fences(layer_data *my_data, VkDevice device) { - // Process each queue for device - // TODO: Add multiple device support - for (auto ii = my_data->queueMap.begin(); ii != my_data->queueMap.end(); ++ii) { - // Set queue's lastRetired to lastSubmitted indicating all fences completed - QUEUE_NODE *pQueueInfo = &(*ii).second; - pQueueInfo->lastRetiredId = pQueueInfo->lastSubmittedId; - } -} - // Helper function to validate correct usage bits set for buffers or images // Verify that (actual & desired) flags != 0 or, // if strict is true, verify that (actual & desired) flags == desired @@ -532,28 +467,6 @@ static bool deleteMemObjInfo(layer_data *my_data, void *object, VkDeviceMemory m return skipCall; } -// Check if fence for given CB is completed -static bool checkCBCompleted(layer_data *my_data, const VkCommandBuffer cb, bool *complete) { - GLOBAL_CB_NODE *pCBNode = getCBNode(my_data, cb); - bool skipCall = false; - *complete = true; - - if (pCBNode) { - if (pCBNode->lastSubmittedQueue != NULL) { - VkQueue queue = pCBNode->lastSubmittedQueue; - QUEUE_NODE *pQueueInfo = &my_data->queueMap[queue]; - if (pCBNode->fenceId > pQueueInfo->lastRetiredId) { - skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, - VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)cb, __LINE__, MEMTRACK_NONE, "MEM", - "fence %#" PRIxLEAST64 " for CB %p has not been checked for completion", - (uint64_t)pCBNode->lastSubmittedFence, cb); - *complete = false; - } - } - } - return skipCall; -} - static bool freeMemObjInfo(layer_data *dev_data, void *object, VkDeviceMemory mem, bool internal) { bool skipCall = false; // Parse global list to find info w/ mem @@ -576,9 +489,7 @@ static bool freeMemObjInfo(layer_data *dev_data, void *object, VkDeviceMemory me // and probably not needed in practice in c++11 auto bindings = pInfo->commandBufferBindings; for (auto cb : bindings) { - bool commandBufferComplete = false; - skipCall |= checkCBCompleted(dev_data, cb, &commandBufferComplete); - if (commandBufferComplete) { + if (!dev_data->globalInFlightCmdBuffers.count(cb)) { clear_cmd_buf_and_mem_references(dev_data, cb); } } @@ -816,8 +727,7 @@ static void printCBList(layer_data *my_data) { pCBInfo = cb_node.second; log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0, - __LINE__, MEMTRACK_NONE, "MEM", " CB Info (%p) has CB %p, fenceId %" PRIx64 ", and fence %#" PRIxLEAST64, - (void *)pCBInfo, (void *)pCBInfo->commandBuffer, pCBInfo->fenceId, (uint64_t)pCBInfo->lastSubmittedFence); + __LINE__, MEMTRACK_NONE, "MEM", " CB Info (%p) has CB %p", (void *)pCBInfo, (void *)pCBInfo->commandBuffer); if (pCBInfo->memObjs.size() <= 0) continue; @@ -4433,7 +4343,6 @@ static void resetCB(layer_data *dev_data, const VkCommandBuffer cb) { pCB->activeRenderPass = 0; pCB->activeSubpassContents = VK_SUBPASS_CONTENTS_INLINE; pCB->activeSubpass = 0; - pCB->fenceId = 0; pCB->lastSubmittedFence = VK_NULL_HANDLE; pCB->lastSubmittedQueue = VK_NULL_HANDLE; pCB->destroyedSets.clear(); @@ -4961,7 +4870,8 @@ static void decrementResources(layer_data *my_data, VkCommandBuffer cmdBuffer) { my_data->eventMap[eventStagePair.first].stageMask = eventStagePair.second; } } - +// For fenceCount fences in pFences, mark fence signaled, decrement in_use, and call +// decrementResources for all priorFences and cmdBuffers associated with fence. static void decrementResources(layer_data *my_data, uint32_t fenceCount, const VkFence *pFences) { for (uint32_t i = 0; i < fenceCount; ++i) { auto fence_data = my_data->fenceMap.find(pFences[i]); @@ -4976,7 +4886,7 @@ static void decrementResources(layer_data *my_data, uint32_t fenceCount, const V } } } - +// Decrement in_use for all outstanding cmd buffers that were submitted on this queue static void decrementResources(layer_data *my_data, VkQueue queue) { auto queue_data = my_data->queueMap.find(queue); if (queue_data != my_data->queueMap.end()) { @@ -5206,13 +5116,20 @@ vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; std::unique_lock<std::mutex> lock(global_lock); // First verify that fence is not in use - if ((fence != VK_NULL_HANDLE) && (submitCount != 0) && dev_data->fenceMap[fence].in_use.load()) { - skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, - (uint64_t)(fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", - "Fence %#" PRIx64 " is already in use by another submission.", (uint64_t)(fence)); + if (fence != VK_NULL_HANDLE) { + dev_data->fenceMap[fence].queue = queue; + if ((submitCount != 0) && dev_data->fenceMap[fence].in_use.load()) { + skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, + (uint64_t)(fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", + "Fence %#" PRIx64 " is already in use by another submission.", (uint64_t)(fence)); + } + if (!dev_data->fenceMap[fence].needsSignaled) { + skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, + reinterpret_cast<uint64_t &>(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", + "Fence %#" PRIxLEAST64 " submitted in SIGNALED state. Fences must be reset before being submitted", + reinterpret_cast<uint64_t &>(fence)); + } } - uint64_t fenceId = 0; - skipCall = add_fence_info(dev_data, fence, queue, &fenceId); // TODO : Review these old print functions and clean up as appropriate print_mem_list(dev_data); printCBList(dev_data); @@ -5265,7 +5182,6 @@ vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, if (pCBNode) { pCBNode->semaphores = semaphoreList; pCBNode->submitCount++; // increment submit count - pCBNode->fenceId = fenceId; pCBNode->lastSubmittedFence = fence; pCBNode->lastSubmittedQueue = queue; skipCall |= validatePrimaryCommandBufferState(dev_data, pCBNode); @@ -5448,14 +5364,16 @@ static inline void removeInFlightCmdBuffer(layer_data *dev_data, VkCommandBuffer } } } -#if MTMERGESOURCE -static inline bool verifyFenceStatus(VkDevice device, VkFence fence, const char *apiCall) { +// Verify that state for fence being waited on is appropriate. That is, +// a fence being waited on should not already be signalled and +// it should have been submitted on a queue or during acquire next image +static inline bool verifyWaitFenceState(VkDevice device, VkFence fence, const char *apiCall) { layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); bool skipCall = false; auto pFenceInfo = my_data->fenceMap.find(fence); if (pFenceInfo != my_data->fenceMap.end()) { if (!pFenceInfo->second.firstTimeFlag) { - if ((pFenceInfo->second.createInfo.flags & VK_FENCE_CREATE_SIGNALED_BIT) && !pFenceInfo->second.firstTimeFlag) { + if (!pFenceInfo->second.needsSignaled) { skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, (uint64_t)fence, __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", @@ -5474,21 +5392,20 @@ static inline bool verifyFenceStatus(VkDevice device, VkFence fence, const char } return skipCall; } -#endif + VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, uint64_t timeout) { layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); bool skip_call = false; -#if MTMERGESOURCE // Verify fence status of submitted fences std::unique_lock<std::mutex> lock(global_lock); for (uint32_t i = 0; i < fenceCount; i++) { - skip_call |= verifyFenceStatus(device, pFences[i], "vkWaitForFences"); + skip_call |= verifyWaitFenceState(device, pFences[i], "vkWaitForFences"); } lock.unlock(); if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; -#endif + VkResult result = dev_data->device_dispatch_table->WaitForFences(device, fenceCount, pFences, waitAll, timeout); if (result == VK_SUCCESS) { @@ -5496,11 +5413,9 @@ vkWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, Vk // When we know that all fences are complete we can clean/remove their CBs if (waitAll || fenceCount == 1) { for (uint32_t i = 0; i < fenceCount; ++i) { -#if MTMERGESOURCE - update_fence_tracking(dev_data, pFences[i]); -#endif - VkQueue fence_queue = dev_data->fenceMap[pFences[i]].queue; - for (auto cmdBuffer : dev_data->fenceMap[pFences[i]].cmdBuffers) { + auto &fence_node = dev_data->fenceMap[pFences[i]]; + VkQueue fence_queue = fence_node.queue; + for (auto cmdBuffer : fence_node.cmdBuffers) { skip_call |= cleanInFlightCmdBuffer(dev_data, cmdBuffer); removeInFlightCmdBuffer(dev_data, cmdBuffer, fence_queue); } @@ -5521,22 +5436,20 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceStatus(VkDevice device, layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); bool skipCall = false; VkResult result = VK_ERROR_VALIDATION_FAILED_EXT; -#if MTMERGESOURCE std::unique_lock<std::mutex> lock(global_lock); - skipCall = verifyFenceStatus(device, fence, "vkGetFenceStatus"); + skipCall = verifyWaitFenceState(device, fence, "vkGetFenceStatus"); lock.unlock(); + if (skipCall) return result; -#endif + result = dev_data->device_dispatch_table->GetFenceStatus(device, fence); bool skip_call = false; lock.lock(); if (result == VK_SUCCESS) { -#if MTMERGESOURCE - update_fence_tracking(dev_data, fence); -#endif - auto fence_queue = dev_data->fenceMap[fence].queue; - for (auto cmdBuffer : dev_data->fenceMap[fence].cmdBuffers) { + auto &fence_node = dev_data->fenceMap[fence]; + auto fence_queue = fence_node.queue; + for (auto cmdBuffer : fence_node.cmdBuffers) { skip_call |= cleanInFlightCmdBuffer(dev_data, cmdBuffer); removeInFlightCmdBuffer(dev_data, cmdBuffer, fence_queue); } @@ -5559,10 +5472,6 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue(VkDevice device, uin if (result.second == true) { QUEUE_NODE *pQNode = &dev_data->queueMap[*pQueue]; pQNode->device = device; -#if MTMERGESOURCE - pQNode->lastRetiredId = 0; - pQNode->lastSubmittedId = 0; -#endif } } @@ -5582,13 +5491,6 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueueWaitIdle(VkQueue queue) { if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; VkResult result = dev_data->device_dispatch_table->QueueWaitIdle(queue); -#if MTMERGESOURCE - if (VK_SUCCESS == result) { - lock.lock(); - retire_queue_fences(dev_data, queue); - lock.unlock(); - } -#endif return result; } @@ -5611,13 +5513,6 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle(VkDevice device) if (skip_call) return VK_ERROR_VALIDATION_FAILED_EXT; VkResult result = dev_data->device_dispatch_table->DeviceWaitIdle(device); -#if MTMERGESOURCE - if (VK_SUCCESS == result) { - lock.lock(); - retire_device_fences(dev_data, device); - lock.unlock(); - } -#endif return result; } @@ -6154,29 +6049,16 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkResetFences(VkDevice device, ui bool skipCall = false; std::unique_lock<std::mutex> lock(global_lock); for (uint32_t i = 0; i < fenceCount; ++i) { -#if MTMERGESOURCE - // Reset fence state in fenceCreateInfo structure - // MTMTODO : Merge with code below auto fence_item = dev_data->fenceMap.find(pFences[i]); if (fence_item != dev_data->fenceMap.end()) { - // Validate fences in SIGNALED state - if (!(fence_item->second.createInfo.flags & VK_FENCE_CREATE_SIGNALED_BIT)) { - // TODO: I don't see a Valid Usage section for ResetFences. This behavior should be documented there. - skipCall = log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, - (uint64_t)pFences[i], __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", - "Fence %#" PRIxLEAST64 " submitted to VkResetFences in UNSIGNALED STATE", (uint64_t)pFences[i]); - } else { - fence_item->second.createInfo.flags = - static_cast<VkFenceCreateFlags>(fence_item->second.createInfo.flags & ~VK_FENCE_CREATE_SIGNALED_BIT); + fence_item->second.needsSignaled = true; + if (fence_item->second.in_use.load()) { + skipCall |= + log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, + reinterpret_cast<const uint64_t &>(pFences[i]), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", + "Fence %#" PRIx64 " is in use by a command buffer.", reinterpret_cast<const uint64_t &>(pFences[i])); } } -#endif - if (dev_data->fenceMap[pFences[i]].in_use.load()) { - skipCall |= - log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, - reinterpret_cast<const uint64_t &>(pFences[i]), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", - "Fence %#" PRIx64 " is in use by a command buffer.", reinterpret_cast<const uint64_t &>(pFences[i])); - } } lock.unlock(); if (!skipCall) @@ -6329,15 +6211,14 @@ vkCreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAll VkResult result = dev_data->device_dispatch_table->CreateFence(device, pCreateInfo, pAllocator, pFence); if (VK_SUCCESS == result) { std::lock_guard<std::mutex> lock(global_lock); - FENCE_NODE *pFN = &dev_data->fenceMap[*pFence]; -#if MTMERGESOURCE - memset(pFN, 0, sizeof(MT_FENCE_INFO)); - memcpy(&(pFN->createInfo), pCreateInfo, sizeof(VkFenceCreateInfo)); + auto &fence_node = dev_data->fenceMap[*pFence]; + fence_node.createInfo = *pCreateInfo; + fence_node.needsSignaled = true; if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) { - pFN->firstTimeFlag = true; + fence_node.firstTimeFlag = true; + fence_node.needsSignaled = false; } -#endif - pFN->in_use.store(0); + fence_node.in_use.store(0); } return result; } @@ -6821,18 +6702,16 @@ vkBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginIn // Validate command buffer level GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer); if (pCB) { - bool commandBufferComplete = false; // This implicitly resets the Cmd Buffer so make sure any fence is done and then clear memory references - skipCall = checkCBCompleted(dev_data, commandBuffer, &commandBufferComplete); - clear_cmd_buf_and_mem_references(dev_data, pCB); - - if (!commandBufferComplete) { - skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, - (uint64_t)commandBuffer, __LINE__, MEMTRACK_RESET_CB_WHILE_IN_FLIGHT, "MEM", - "Calling vkBeginCommandBuffer() on active CB %p before it has completed. " - "You must check CB flag before this call.", - commandBuffer); + if (dev_data->globalInFlightCmdBuffers.count(commandBuffer)) { + skipCall |= + log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, + (uint64_t)commandBuffer, __LINE__, MEMTRACK_RESET_CB_WHILE_IN_FLIGHT, "MEM", + "Calling vkBeginCommandBuffer() on active CB %p before it has completed. " + "You must check CB fence before this call.", + commandBuffer); } + clear_cmd_buf_and_mem_references(dev_data, pCB); if (pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) { // Secondary Command Buffer const VkCommandBufferInheritanceInfo *pInfo = pBeginInfo->pInheritanceInfo; @@ -10203,13 +10082,22 @@ vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo bool skip_call = false; std::unique_lock<std::mutex> lock(global_lock); // First verify that fence is not in use - if ((fence != VK_NULL_HANDLE) && (bindInfoCount != 0) && dev_data->fenceMap[fence].in_use.load()) { - skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, - reinterpret_cast<uint64_t &>(fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", - "Fence %#" PRIx64 " is already in use by another submission.", reinterpret_cast<uint64_t &>(fence)); + if (fence != VK_NULL_HANDLE) { + dev_data->fenceMap[fence].queue = queue; + if ((bindInfoCount != 0) && dev_data->fenceMap[fence].in_use.load()) { + skip_call |= + log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, + reinterpret_cast<uint64_t &>(fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS", + "Fence %#" PRIx64 " is already in use by another submission.", reinterpret_cast<uint64_t &>(fence)); + } + if (!dev_data->fenceMap[fence].needsSignaled) { + skip_call |= + log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, + reinterpret_cast<uint64_t &>(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM", + "Fence %#" PRIxLEAST64 " submitted in SIGNALED state. Fences must be reset before being submitted", + reinterpret_cast<uint64_t &>(fence)); + } } - uint64_t fenceId = 0; - skip_call = add_fence_info(dev_data, fence, queue, &fenceId); for (uint32_t bindIdx = 0; bindIdx < bindInfoCount; ++bindIdx) { const VkBindSparseInfo &bindInfo = pBindInfo[bindIdx]; // Track objects tied to memory diff --git a/layers/core_validation.h b/layers/core_validation.h index 0831c775..8ab1bdfb 100644 --- a/layers/core_validation.h +++ b/layers/core_validation.h @@ -170,23 +170,6 @@ struct MT_PASS_ATTACHMENT_INFO { VkAttachmentStoreOp store_op; }; -// Associate fenceId with a fence object -struct MT_FENCE_INFO { - uint64_t fenceId; // Sequence number for fence at last submit - VkQueue queue; // Queue that this fence is submitted against or NULL - VkSwapchainKHR swapchain; // Swapchain that this fence is submitted against or NULL - bool firstTimeFlag; // Fence was created in signaled state, avoid warnings for first use - VkFenceCreateInfo createInfo; -}; - -// Track Queue information -struct MT_QUEUE_INFO { - uint64_t lastRetiredId; - uint64_t lastSubmittedId; - list<VkCommandBuffer> pQueueCommandBuffers; - list<VkDeviceMemory> pMemRefList; -}; - struct MT_DESCRIPTOR_SET_INFO { std::vector<VkImageView> images; std::vector<VkBuffer> buffers; @@ -572,19 +555,17 @@ class PHYS_DEV_PROPERTIES_NODE { class FENCE_NODE : public BASE_NODE { public: using BASE_NODE::in_use; -#if MTMERGE - uint64_t fenceId; // Sequence number for fence at last submit + VkSwapchainKHR swapchain; // Swapchain that this fence is submitted against or NULL bool firstTimeFlag; // Fence was created in signaled state, avoid warnings for first use VkFenceCreateInfo createInfo; -#endif VkQueue queue; vector<VkCommandBuffer> cmdBuffers; bool needsSignaled; vector<VkFence> priorFences; // Default constructor - FENCE_NODE() : queue(NULL), needsSignaled(VK_FALSE){}; + FENCE_NODE() : queue(VK_NULL_HANDLE), needsSignaled(false){}; }; class SEMAPHORE_NODE : public BASE_NODE { @@ -606,8 +587,6 @@ class QUEUE_NODE { VkDevice device; vector<VkFence> lastFences; #if MTMERGE - uint64_t lastRetiredId; - uint64_t lastSubmittedId; // MTMTODO : merge cmd_buffer data structs here list<VkCommandBuffer> pQueueCommandBuffers; list<VkDeviceMemory> pMemRefList; |
