From a8b53c2421022059306bfd808e83794cec168543 Mon Sep 17 00:00:00 2001 From: Michael Lentine Date: Wed, 6 Jan 2016 10:05:48 -0600 Subject: [PATCH] layers: MR118, Add validation for semaphore ordering Conflicts: layers/draw_state.cpp layers/draw_state.h --- layers/draw_state.cpp | 97 ++++++++++++++++++++++++++++++++++++++++++++++++--- layers/draw_state.h | 1 + 2 files changed, 93 insertions(+), 5 deletions(-) diff --git a/layers/draw_state.cpp b/layers/draw_state.cpp index 4ce634c..b18e772 100644 --- a/layers/draw_state.cpp +++ b/layers/draw_state.cpp @@ -114,15 +114,15 @@ struct layer_data { unordered_map deviceMap; unordered_map eventMap; unordered_map queryToStateMap; - // Map for layout chains + unordered_map semaphoreSignaledMap; unordered_map commandBufferMap; unordered_map frameBufferMap; unordered_map imageLayoutMap; unordered_map renderPassMap; - unordered_map shaderModuleMap; + unordered_map shaderModuleMap; // Current render pass - VkRenderPassBeginInfo renderPassBeginInfo; - uint32_t currentSubpass; + VkRenderPassBeginInfo renderPassBeginInfo; + uint32_t currentSubpass; layer_data() : report_data(nullptr), @@ -131,6 +131,7 @@ struct layer_data { device_extensions() {}; }; + // Code imported from ShaderChecker static void build_type_def_index(std::vector const &words, std::unordered_map &type_def_index); @@ -3065,6 +3066,18 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit(VkQueue queue, uint // Same goes for any secondary CBs under the primary CB for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) { const VkSubmitInfo *submit = &pSubmits[submit_idx]; + for (uint32_t i=0; i < submit->waitSemaphoreCount; ++i) { + if (dev_data->semaphoreSignaledMap[submit->pWaitSemaphores[i]]) { + dev_data->semaphoreSignaledMap[submit->pWaitSemaphores[i]] = 0; + } else { + skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", + "Queue %#" PRIx64 " is waiting on semaphore %#" PRIx64 " that has no way to be signaled.", + reinterpret_cast(queue), reinterpret_cast(submit->pWaitSemaphores[i])); + } + } + for (uint32_t i=0; i < submit->signalSemaphoreCount; ++i) { + dev_data->semaphoreSignaledMap[submit->pSignalSemaphores[i]] = 1; + } for (uint32_t i=0; i < submit->commandBufferCount; i++) { #ifndef DISABLE_IMAGE_LAYOUT_VALIDATION @@ -3189,7 +3202,9 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyFence(VkDevice device, VkFen VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator) { - get_my_data_ptr(get_dispatch_key(device), layer_data_map)->device_dispatch_table->DestroySemaphore(device, semaphore, pAllocator); + layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); + dev_data->device_dispatch_table->DestroySemaphore(device, semaphore, pAllocator); + dev_data->semaphoreSignaledMap.erase(semaphore); // TODO : Clean up any internal data structures using this obj. } @@ -5736,6 +5751,48 @@ VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent(VkDevice device, VkEvent event) { return result; } +VKAPI_ATTR VkResult VKAPI_CALL vkQueueBindSparse( + VkQueue queue, + uint32_t bindInfoCount, + const VkBindSparseInfo* pBindInfo, + VkFence fence) +{ + layer_data* dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map); + bool skip_call = false; + + for (uint32_t bindIdx=0; bindIdx < bindInfoCount; ++bindIdx) { + const VkBindSparseInfo& bindInfo = pBindInfo[bindIdx]; + for (uint32_t i=0; i < bindInfo.waitSemaphoreCount; ++i) { + if (dev_data->semaphoreSignaledMap[bindInfo.pWaitSemaphores[i]]) { + dev_data->semaphoreSignaledMap[bindInfo.pWaitSemaphores[i]] = 0; + } else { + skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", + "Queue %#" PRIx64 " is waiting on semaphore %#" PRIx64 " that has no way to be signaled.", + reinterpret_cast(queue), reinterpret_cast(bindInfo.pWaitSemaphores[i])); + } + } + for (uint32_t i=0; i < bindInfo.signalSemaphoreCount; ++i) { + dev_data->semaphoreSignaledMap[bindInfo.pSignalSemaphores[i]] = 1; + } + } + + if (!skip_call) + return dev_data->device_dispatch_table->QueueBindSparse(queue, bindInfoCount, pBindInfo, fence); +} + +VKAPI_ATTR VkResult VKAPI_CALL vkCreateSemaphore( + VkDevice device, + const VkSemaphoreCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSemaphore* pSemaphore) +{ + layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); + VkResult result = dev_data->device_dispatch_table->CreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore); + if (result == VK_SUCCESS) { + dev_data->semaphoreSignaledMap[*pSemaphore] = 0; + } +} + VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR( VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, @@ -5810,6 +5867,15 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(VkQueue queue, #ifndef DISABLE_IMAGE_LAYOUT_VALIDATION if (pPresentInfo) { + for (uint32_t i=0; i < pPresentInfo->waitSemaphoreCount; ++i) { + if (dev_data->semaphoreSignaledMap[pPresentInfo->pWaitSemaphores[i]]) { + dev_data->semaphoreSignaledMap[pPresentInfo->pWaitSemaphores[i]] = 0; + } else { + skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0, __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS", + "Queue %#" PRIx64 " is waiting on semaphore %#" PRIx64 " that has no way to be signaled.", + reinterpret_cast(queue), reinterpret_cast(pPresentInfo->pWaitSemaphores[i])); + } + } for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) { auto swapchain_data = dev_data->device_extensions.swapchainMap.find(pPresentInfo->pSwapchains[i]); if (swapchain_data != dev_data->device_extensions.swapchainMap.end() && pPresentInfo->pImageIndices[i] < swapchain_data->second->images.size()) { @@ -5831,6 +5897,19 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(VkQueue queue, return VK_ERROR_VALIDATION_FAILED_EXT; } +VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR( + VkDevice device, + VkSwapchainKHR swapchain, + uint64_t timeout, + VkSemaphore semaphore, + VkFence fence, + uint32_t* pImageIndex) +{ + layer_data* dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map); + VkResult result = dev_data->device_dispatch_table->AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex); + dev_data->semaphoreSignaledMap[semaphore] = 1; +} + VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT( VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, @@ -6116,6 +6195,12 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD return (PFN_vkVoidFunction) vkMapMemory; if (!strcmp(funcName, "vkGetQueryPoolResults")) return (PFN_vkVoidFunction) vkGetQueryPoolResults; + if (!strcmp(funcName, "vkBindImageMemory")) + return (PFN_vkVoidFunction) vkBindImageMemory; + if (!strcmp(funcName, "vkQueueBindSparse")) + return (PFN_vkVoidFunction) vkQueueBindSparse; + if (!strcmp(funcName, "vkCreateSemaphore")) + return (PFN_vkVoidFunction) vkCreateSemaphore; if (dev_data->device_extensions.wsi_enabled) { @@ -6125,6 +6210,8 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD return (PFN_vkVoidFunction) vkDestroySwapchainKHR; if (!strcmp(funcName, "vkGetSwapchainImagesKHR")) return (PFN_vkVoidFunction) vkGetSwapchainImagesKHR; + if (!strcmp(funcName, "vkAcquireNextImageKHR")) + return (PFN_vkVoidFunction) vkAcquireNextImageKHR; if (!strcmp(funcName, "vkQueuePresentKHR")) return (PFN_vkVoidFunction) vkQueuePresentKHR; } diff --git a/layers/draw_state.h b/layers/draw_state.h index 11e9c3e..e632e7e 100755 --- a/layers/draw_state.h +++ b/layers/draw_state.h @@ -98,6 +98,7 @@ typedef enum _DRAW_STATE_ERROR DRAWSTATE_DYNAMIC_OFFSET_OVERFLOW, // At draw time the dynamic offset combined with buffer offset and range oversteps size of buffer DRAWSTATE_DOUBLE_DESTROY, // Destroying an object twice DRAWSTATE_OBJECT_INUSE, // Destroying an object in use by a command buffer + DRAWSTATE_QUEUE_FORWARD_PROGRESS, // Queue cannot guarantee forward progress } DRAW_STATE_ERROR; typedef enum _SHADER_CHECKER_ERROR { -- 2.7.4