Fixed usage of semaphore signaled on vkAcquireNextImageKHR Based on Article "Swapchain Semaphore Reuse" in Vulkan documentation.
diff --git a/src/VulkanSample.cpp b/src/VulkanSample.cpp index 5b9502d..ef07511 100644 --- a/src/VulkanSample.cpp +++ b/src/VulkanSample.cpp
@@ -91,8 +91,9 @@ static VkFence g_MainCommandBufferExecutedFences[COMMAND_BUFFER_COUNT]; VkFence g_ImmediateFence; static uint32_t g_NextCommandBufferIndex; -// Notice we need as many semaphores as there are swapchain images -static std::vector<VkSemaphore> g_hImageAvailableSemaphores; +// Signaled by vkAcquireNextImageKHR. +static VkSemaphore g_hImageAvailableSemaphores[COMMAND_BUFFER_COUNT]; +// Notice we need as many semaphores as there are swapchain images. static std::vector<VkSemaphore> g_hRenderFinishedSemaphores; static uint32_t g_SwapchainImageCount = 0; static uint32_t g_SwapchainImageIndex = 0; @@ -1365,45 +1366,58 @@ // Destroy the old semaphores and create new ones - if (g_hImageAvailableSemaphores.size() < g_SwapchainImageCount) { - g_hImageAvailableSemaphores.resize(g_SwapchainImageCount); - } if (g_hRenderFinishedSemaphores.size() < g_SwapchainImageCount) { g_hRenderFinishedSemaphores.resize(g_SwapchainImageCount); } VkSemaphoreCreateInfo semaphoreInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; - for (std::size_t swapchain_img_index = 0; swapchain_img_index < g_SwapchainImageCount; swapchain_img_index++) { - if (g_hImageAvailableSemaphores.at(swapchain_img_index) != VK_NULL_HANDLE) { - vkDestroySemaphore(g_hDevice, g_hImageAvailableSemaphores[swapchain_img_index], g_Allocs); - g_hImageAvailableSemaphores[swapchain_img_index] = VK_NULL_HANDLE; + for (std::size_t i = COMMAND_BUFFER_COUNT; i--; ) + { + if (g_hImageAvailableSemaphores[i] != VK_NULL_HANDLE) + { + vkDestroySemaphore(g_hDevice, g_hImageAvailableSemaphores[i], g_Allocs); + g_hImageAvailableSemaphores[i] = VK_NULL_HANDLE; } + } + for (std::size_t swapchain_img_index = 0; swapchain_img_index < g_SwapchainImageCount; swapchain_img_index++) { if (g_hRenderFinishedSemaphores.at(swapchain_img_index) != VK_NULL_HANDLE) { vkDestroySemaphore(g_hDevice, g_hRenderFinishedSemaphores[swapchain_img_index], g_Allocs); g_hRenderFinishedSemaphores[swapchain_img_index] = VK_NULL_HANDLE; } } - for (std::size_t swapchain_img_index = 0; swapchain_img_index < g_SwapchainImageCount; swapchain_img_index++) { - ERR_GUARD_VULKAN(vkCreateSemaphore(g_hDevice, &semaphoreInfo, g_Allocs, &g_hImageAvailableSemaphores[swapchain_img_index])); - std::string semaphoreName = "g_hImageAvailableSemaphores[" + std::to_string(swapchain_img_index) + "]"; - SetDebugUtilsObjectName(VK_OBJECT_TYPE_SEMAPHORE, reinterpret_cast<std::uint64_t>(g_hImageAvailableSemaphores[swapchain_img_index]), semaphoreName); + for (std::size_t i = 0; i < COMMAND_BUFFER_COUNT; ++i) + { + ERR_GUARD_VULKAN(vkCreateSemaphore(g_hDevice, &semaphoreInfo, g_Allocs, &g_hImageAvailableSemaphores[i])); + std::string semaphoreName = "g_hImageAvailableSemaphores[" + std::to_string(i) + "]"; + SetDebugUtilsObjectName(VK_OBJECT_TYPE_SEMAPHORE, + reinterpret_cast<std::uint64_t>(g_hImageAvailableSemaphores[i]), semaphoreName); + } + for (std::size_t swapchain_img_index = 0; swapchain_img_index < g_SwapchainImageCount; swapchain_img_index++) + { ERR_GUARD_VULKAN(vkCreateSemaphore(g_hDevice, &semaphoreInfo, g_Allocs, &g_hRenderFinishedSemaphores[swapchain_img_index])); - semaphoreName = "g_hRenderFinishedSemaphores[" + std::to_string(swapchain_img_index) + "]"; - SetDebugUtilsObjectName(VK_OBJECT_TYPE_SEMAPHORE, reinterpret_cast<std::uint64_t>(g_hRenderFinishedSemaphores[swapchain_img_index]), semaphoreName); + std::string semaphoreName = "g_hRenderFinishedSemaphores[" + std::to_string(swapchain_img_index) + "]"; + SetDebugUtilsObjectName(VK_OBJECT_TYPE_SEMAPHORE, + reinterpret_cast<std::uint64_t>(g_hRenderFinishedSemaphores[swapchain_img_index]), semaphoreName); } } static void DestroySwapchain(bool destroyActualSwapchain) { - for (std::size_t swapchain_img_index = 0; swapchain_img_index < g_SwapchainImageCount; swapchain_img_index++) { - if (g_hImageAvailableSemaphores.at(swapchain_img_index) != VK_NULL_HANDLE) { - vkDestroySemaphore(g_hDevice, g_hImageAvailableSemaphores[swapchain_img_index], g_Allocs); - g_hImageAvailableSemaphores[swapchain_img_index] = VK_NULL_HANDLE; + for (std::size_t i = 0; i < COMMAND_BUFFER_COUNT; i++) + { + if (g_hImageAvailableSemaphores[i] != VK_NULL_HANDLE) + { + vkDestroySemaphore(g_hDevice, g_hImageAvailableSemaphores[i], g_Allocs); + g_hImageAvailableSemaphores[i] = VK_NULL_HANDLE; } - if (g_hRenderFinishedSemaphores.at(swapchain_img_index) != VK_NULL_HANDLE) { + } + for (std::size_t swapchain_img_index = 0; swapchain_img_index < g_SwapchainImageCount; swapchain_img_index++) + { + if (g_hRenderFinishedSemaphores.at(swapchain_img_index) != VK_NULL_HANDLE) + { vkDestroySemaphore(g_hDevice, g_hRenderFinishedSemaphores[swapchain_img_index], g_Allocs); g_hRenderFinishedSemaphores[swapchain_img_index] = VK_NULL_HANDLE; } @@ -2405,9 +2419,11 @@ ERR_GUARD_VULKAN( vkBeginCommandBuffer(hCommandBuffer, &commandBufferBeginInfo) ); SetDebugUtilsObjectName(VK_OBJECT_TYPE_COMMAND_BUFFER, reinterpret_cast<std::uint64_t>(hCommandBuffer), "hCommandBuffer"); + const VkSemaphore imageAvailableSemaphore = g_hImageAvailableSemaphores[cmdBufIndex]; + // Acquire swapchain image uint32_t imageIndex = 0; - VkResult res = vkAcquireNextImageKHR(g_hDevice, g_hSwapchain, UINT64_MAX, g_hImageAvailableSemaphores.at(g_SwapchainImageIndex), VK_NULL_HANDLE, &imageIndex); + VkResult res = vkAcquireNextImageKHR(g_hDevice, g_hSwapchain, UINT64_MAX, imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex); if(res == VK_ERROR_OUT_OF_DATE_KHR) { RecreateSwapChain(); @@ -2485,7 +2501,7 @@ // Submit command buffer - VkSemaphore submitWaitSemaphores[] = { g_hImageAvailableSemaphores.at(g_SwapchainImageIndex)}; + VkSemaphore submitWaitSemaphores[] = { imageAvailableSemaphore }; VkPipelineStageFlags submitWaitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; VkSemaphore submitSignalSemaphores[] = { g_hRenderFinishedSemaphores.at(g_SwapchainImageIndex)}; VkSubmitInfo submitInfo = { VK_STRUCTURE_TYPE_SUBMIT_INFO };