From b5496851dca6f5d2523a64888ef0d487a1a3344e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 17 Jan 2024 21:34:31 +0100 Subject: [PATCH] Vulkan: Semaphore-per-frame seems to be the way to go, according to the new validation layers. --- Common/GPU/Vulkan/VulkanFrameData.cpp | 30 +++++++++++++-------------- Common/GPU/Vulkan/VulkanFrameData.h | 8 +++---- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanFrameData.cpp b/Common/GPU/Vulkan/VulkanFrameData.cpp index 3f1ee5113353..093d32133573 100644 --- a/Common/GPU/Vulkan/VulkanFrameData.cpp +++ b/Common/GPU/Vulkan/VulkanFrameData.cpp @@ -21,10 +21,17 @@ void FrameData::Init(VulkanContext *vulkan, int index) { this->index = index; VkDevice device = vulkan->GetDevice(); + VkSemaphoreCreateInfo semaphoreCreateInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; + semaphoreCreateInfo.flags = 0; + VkResult res = vkCreateSemaphore(vulkan->GetDevice(), &semaphoreCreateInfo, nullptr, &acquireSemaphore); + _dbg_assert_(res == VK_SUCCESS); + res = vkCreateSemaphore(vulkan->GetDevice(), &semaphoreCreateInfo, nullptr, &renderingCompleteSemaphore); + _dbg_assert_(res == VK_SUCCESS); + VkCommandPoolCreateInfo cmd_pool_info = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO }; cmd_pool_info.queueFamilyIndex = vulkan->GetGraphicsQueueFamilyIndex(); cmd_pool_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT; - VkResult res = vkCreateCommandPool(device, &cmd_pool_info, nullptr, &cmdPoolInit); + res = vkCreateCommandPool(device, &cmd_pool_info, nullptr, &cmdPoolInit); _dbg_assert_(res == VK_SUCCESS); res = vkCreateCommandPool(device, &cmd_pool_info, nullptr, &cmdPoolMain); _dbg_assert_(res == VK_SUCCESS); @@ -61,6 +68,8 @@ void FrameData::Destroy(VulkanContext *vulkan) { vkDestroyCommandPool(device, cmdPoolMain, nullptr); vkDestroyFence(device, fence, nullptr); vkDestroyQueryPool(device, profile.queryPool, nullptr); + vkDestroySemaphore(device, acquireSemaphore, nullptr); + vkDestroySemaphore(device, renderingCompleteSemaphore, nullptr); readbacks_.IterateMut([=](const ReadbackKey &key, CachedReadback *value) { value->Destroy(vulkan); @@ -69,11 +78,11 @@ void FrameData::Destroy(VulkanContext *vulkan) { readbacks_.Clear(); } -void FrameData::AcquireNextImage(VulkanContext *vulkan, FrameDataShared &shared) { +void FrameData::AcquireNextImage(VulkanContext *vulkan) { _dbg_assert_(!hasAcquired); // Get the index of the next available swapchain image, and a semaphore to block command buffer execution on. - VkResult res = vkAcquireNextImageKHR(vulkan->GetDevice(), vulkan->GetSwapchain(), UINT64_MAX, shared.acquireSemaphore, (VkFence)VK_NULL_HANDLE, &curSwapchainImage); + VkResult res = vkAcquireNextImageKHR(vulkan->GetDevice(), vulkan->GetSwapchain(), UINT64_MAX, acquireSemaphore, (VkFence)VK_NULL_HANDLE, &curSwapchainImage); switch (res) { case VK_SUCCESS: hasAcquired = true; @@ -111,7 +120,7 @@ VkResult FrameData::QueuePresent(VulkanContext *vulkan, FrameDataShared &shared) present.swapchainCount = 1; present.pSwapchains = &swapchain; present.pImageIndices = &curSwapchainImage; - present.pWaitSemaphores = &shared.renderingCompleteSemaphore; + present.pWaitSemaphores = &renderingCompleteSemaphore; present.waitSemaphoreCount = 1; // Can't move these into the if. @@ -213,14 +222,14 @@ void FrameData::SubmitPending(VulkanContext *vulkan, FrameSubmitType type, Frame if (type == FrameSubmitType::Present && !skipSwap) { _dbg_assert_(hasAcquired); submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &sharedData.acquireSemaphore; + submit_info.pWaitSemaphores = &acquireSemaphore; submit_info.pWaitDstStageMask = waitStage; } submit_info.commandBufferCount = (uint32_t)numCmdBufs; submit_info.pCommandBuffers = cmdBufs; if (type == FrameSubmitType::Present && !skipSwap) { submit_info.signalSemaphoreCount = 1; - submit_info.pSignalSemaphores = &sharedData.renderingCompleteSemaphore; + submit_info.pSignalSemaphores = &renderingCompleteSemaphore; } VkResult res; @@ -253,13 +262,6 @@ void FrameData::SubmitPending(VulkanContext *vulkan, FrameSubmitType type, Frame } void FrameDataShared::Init(VulkanContext *vulkan, bool useMultiThreading, bool measurePresentTime) { - VkSemaphoreCreateInfo semaphoreCreateInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO }; - semaphoreCreateInfo.flags = 0; - VkResult res = vkCreateSemaphore(vulkan->GetDevice(), &semaphoreCreateInfo, nullptr, &acquireSemaphore); - _dbg_assert_(res == VK_SUCCESS); - res = vkCreateSemaphore(vulkan->GetDevice(), &semaphoreCreateInfo, nullptr, &renderingCompleteSemaphore); - _dbg_assert_(res == VK_SUCCESS); - // This fence is used for synchronizing readbacks. Does not need preinitialization. readbackFence = vulkan->CreateFence(false); vulkan->SetDebugName(readbackFence, VK_OBJECT_TYPE_FENCE, "readbackFence"); @@ -270,7 +272,5 @@ void FrameDataShared::Init(VulkanContext *vulkan, bool useMultiThreading, bool m void FrameDataShared::Destroy(VulkanContext *vulkan) { VkDevice device = vulkan->GetDevice(); - vkDestroySemaphore(device, acquireSemaphore, nullptr); - vkDestroySemaphore(device, renderingCompleteSemaphore, nullptr); vkDestroyFence(device, readbackFence, nullptr); } diff --git a/Common/GPU/Vulkan/VulkanFrameData.h b/Common/GPU/Vulkan/VulkanFrameData.h index a5decd63c072..97d387efe838 100644 --- a/Common/GPU/Vulkan/VulkanFrameData.h +++ b/Common/GPU/Vulkan/VulkanFrameData.h @@ -53,10 +53,6 @@ struct CachedReadback { }; struct FrameDataShared { - // Permanent objects - VkSemaphore acquireSemaphore = VK_NULL_HANDLE; - VkSemaphore renderingCompleteSemaphore = VK_NULL_HANDLE; - // For synchronous readbacks. VkFence readbackFence = VK_NULL_HANDLE; bool useMultiThreading; @@ -81,6 +77,8 @@ struct FrameData { bool readyForFence = true; VkFence fence = VK_NULL_HANDLE; + VkSemaphore acquireSemaphore = VK_NULL_HANDLE; + VkSemaphore renderingCompleteSemaphore = VK_NULL_HANDLE; // These are on different threads so need separate pools. VkCommandPool cmdPoolInit = VK_NULL_HANDLE; // Written to from main thread @@ -117,7 +115,7 @@ struct FrameData { void Init(VulkanContext *vulkan, int index); void Destroy(VulkanContext *vulkan); - void AcquireNextImage(VulkanContext *vulkan, FrameDataShared &shared); + void AcquireNextImage(VulkanContext *vulkan); VkResult QueuePresent(VulkanContext *vulkan, FrameDataShared &shared); // Generally called from the main thread, unlike most of the rest.