Merge pull request #8347 from Jupeyy/pr_vk_minirefactor

Fix segfault when swapchain images change (e.g. toggling Vsync)
This commit is contained in:
Robert Müller 2024-05-12 20:16:30 +00:00 committed by GitHub
commit f3bb5feffc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -986,8 +986,6 @@ private:
std::vector<VkSemaphore> m_vWaitSemaphores; std::vector<VkSemaphore> m_vWaitSemaphores;
std::vector<VkSemaphore> m_vSigSemaphores; std::vector<VkSemaphore> m_vSigSemaphores;
std::vector<VkSemaphore> m_vMemorySemaphores;
std::vector<VkFence> m_vFrameFences; std::vector<VkFence> m_vFrameFences;
std::vector<VkFence> m_vImagesFences; std::vector<VkFence> m_vImagesFences;
@ -1053,7 +1051,7 @@ private:
std::vector<SStreamMemory<SFrameBuffers>> m_vStreamedVertexBuffers; std::vector<SStreamMemory<SFrameBuffers>> m_vStreamedVertexBuffers;
std::vector<SStreamMemory<SFrameUniformBuffers>> m_vStreamedUniformBuffers; std::vector<SStreamMemory<SFrameUniformBuffers>> m_vStreamedUniformBuffers;
uint32_t m_CurFrames = 0; uint32_t m_CurFrameSyncObject = 0;
uint32_t m_CurImageIndex = 0; uint32_t m_CurImageIndex = 0;
uint32_t m_CanvasWidth; uint32_t m_CanvasWidth;
@ -2275,7 +2273,7 @@ protected:
return false; return false;
} }
VkSemaphore WaitSemaphore = m_vWaitSemaphores[m_CurFrames]; VkSemaphore WaitSemaphore = m_vWaitSemaphores[m_CurFrameSyncObject];
VkSubmitInfo SubmitInfo{}; VkSubmitInfo SubmitInfo{};
SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
@ -2304,13 +2302,13 @@ protected:
SubmitInfo.pWaitSemaphores = aWaitSemaphores.data(); SubmitInfo.pWaitSemaphores = aWaitSemaphores.data();
SubmitInfo.pWaitDstStageMask = aWaitStages.data(); SubmitInfo.pWaitDstStageMask = aWaitStages.data();
std::array<VkSemaphore, 1> aSignalSemaphores = {m_vSigSemaphores[m_CurFrames]}; std::array<VkSemaphore, 1> aSignalSemaphores = {m_vSigSemaphores[m_CurFrameSyncObject]};
SubmitInfo.signalSemaphoreCount = aSignalSemaphores.size(); SubmitInfo.signalSemaphoreCount = aSignalSemaphores.size();
SubmitInfo.pSignalSemaphores = aSignalSemaphores.data(); SubmitInfo.pSignalSemaphores = aSignalSemaphores.data();
vkResetFences(m_VKDevice, 1, &m_vFrameFences[m_CurFrames]); vkResetFences(m_VKDevice, 1, &m_vFrameFences[m_CurFrameSyncObject]);
VkResult QueueSubmitRes = vkQueueSubmit(m_VKGraphicsQueue, 1, &SubmitInfo, m_vFrameFences[m_CurFrames]); VkResult QueueSubmitRes = vkQueueSubmit(m_VKGraphicsQueue, 1, &SubmitInfo, m_vFrameFences[m_CurFrameSyncObject]);
if(QueueSubmitRes != VK_SUCCESS) if(QueueSubmitRes != VK_SUCCESS)
{ {
const char *pCritErrorMsg = CheckVulkanCriticalError(QueueSubmitRes); const char *pCritErrorMsg = CheckVulkanCriticalError(QueueSubmitRes);
@ -2321,7 +2319,7 @@ protected:
} }
} }
std::swap(m_vWaitSemaphores[m_CurFrames], m_vSigSemaphores[m_CurFrames]); std::swap(m_vWaitSemaphores[m_CurFrameSyncObject], m_vSigSemaphores[m_CurFrameSyncObject]);
VkPresentInfoKHR PresentInfo{}; VkPresentInfoKHR PresentInfo{};
PresentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; PresentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
@ -2348,7 +2346,7 @@ protected:
} }
} }
m_CurFrames = (m_CurFrames + 1) % m_SwapChainImageCount; m_CurFrameSyncObject = (m_CurFrameSyncObject + 1) % m_vWaitSemaphores.size();
return true; return true;
} }
@ -2364,7 +2362,7 @@ protected:
RecreateSwapChain(); RecreateSwapChain();
} }
auto AcqResult = vkAcquireNextImageKHR(m_VKDevice, m_VKSwapChain, std::numeric_limits<uint64_t>::max(), m_vSigSemaphores[m_CurFrames], VK_NULL_HANDLE, &m_CurImageIndex); auto AcqResult = vkAcquireNextImageKHR(m_VKDevice, m_VKSwapChain, std::numeric_limits<uint64_t>::max(), m_vSigSemaphores[m_CurFrameSyncObject], VK_NULL_HANDLE, &m_CurImageIndex);
if(AcqResult != VK_SUCCESS) if(AcqResult != VK_SUCCESS)
{ {
if(AcqResult == VK_ERROR_OUT_OF_DATE_KHR || m_RecreateSwapChain) if(AcqResult == VK_ERROR_OUT_OF_DATE_KHR || m_RecreateSwapChain)
@ -2395,13 +2393,13 @@ protected:
} }
} }
} }
std::swap(m_vWaitSemaphores[m_CurFrames], m_vSigSemaphores[m_CurFrames]); std::swap(m_vWaitSemaphores[m_CurFrameSyncObject], m_vSigSemaphores[m_CurFrameSyncObject]);
if(m_vImagesFences[m_CurImageIndex] != VK_NULL_HANDLE) if(m_vImagesFences[m_CurImageIndex] != VK_NULL_HANDLE)
{ {
vkWaitForFences(m_VKDevice, 1, &m_vImagesFences[m_CurImageIndex], VK_TRUE, std::numeric_limits<uint64_t>::max()); vkWaitForFences(m_VKDevice, 1, &m_vImagesFences[m_CurImageIndex], VK_TRUE, std::numeric_limits<uint64_t>::max());
} }
m_vImagesFences[m_CurImageIndex] = m_vFrameFences[m_CurFrames]; m_vImagesFences[m_CurImageIndex] = m_vFrameFences[m_CurFrameSyncObject];
// next frame // next frame
m_CurFrame++; m_CurFrame++;
@ -5333,12 +5331,12 @@ public:
[[nodiscard]] bool CreateSyncObjects() [[nodiscard]] bool CreateSyncObjects()
{ {
m_vWaitSemaphores.resize(m_SwapChainImageCount); // Create one more sync object than there are frames in flight
m_vSigSemaphores.resize(m_SwapChainImageCount); auto SyncObjectCount = m_SwapChainImageCount + 1;
m_vWaitSemaphores.resize(SyncObjectCount);
m_vSigSemaphores.resize(SyncObjectCount);
m_vMemorySemaphores.resize(m_SwapChainImageCount); m_vFrameFences.resize(SyncObjectCount);
m_vFrameFences.resize(m_SwapChainImageCount);
m_vImagesFences.resize(m_SwapChainImageCount, VK_NULL_HANDLE); m_vImagesFences.resize(m_SwapChainImageCount, VK_NULL_HANDLE);
VkSemaphoreCreateInfo CreateSemaphoreInfo{}; VkSemaphoreCreateInfo CreateSemaphoreInfo{};
@ -5348,11 +5346,10 @@ public:
FenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; FenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
FenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; FenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
for(size_t i = 0; i < m_SwapChainImageCount; i++) for(size_t i = 0; i < SyncObjectCount; i++)
{ {
if(vkCreateSemaphore(m_VKDevice, &CreateSemaphoreInfo, nullptr, &m_vWaitSemaphores[i]) != VK_SUCCESS || if(vkCreateSemaphore(m_VKDevice, &CreateSemaphoreInfo, nullptr, &m_vWaitSemaphores[i]) != VK_SUCCESS ||
vkCreateSemaphore(m_VKDevice, &CreateSemaphoreInfo, nullptr, &m_vSigSemaphores[i]) != VK_SUCCESS || vkCreateSemaphore(m_VKDevice, &CreateSemaphoreInfo, nullptr, &m_vSigSemaphores[i]) != VK_SUCCESS ||
vkCreateSemaphore(m_VKDevice, &CreateSemaphoreInfo, nullptr, &m_vMemorySemaphores[i]) != VK_SUCCESS ||
vkCreateFence(m_VKDevice, &FenceInfo, nullptr, &m_vFrameFences[i]) != VK_SUCCESS) vkCreateFence(m_VKDevice, &FenceInfo, nullptr, &m_vFrameFences[i]) != VK_SUCCESS)
{ {
SetError(EGfxErrorType::GFX_ERROR_TYPE_INIT, "Creating swap chain sync objects(fences, semaphores) failed."); SetError(EGfxErrorType::GFX_ERROR_TYPE_INIT, "Creating swap chain sync objects(fences, semaphores) failed.");
@ -5365,21 +5362,20 @@ public:
void DestroySyncObjects() void DestroySyncObjects()
{ {
for(size_t i = 0; i < m_SwapChainImageCount; i++) for(size_t i = 0; i < m_vWaitSemaphores.size(); i++)
{ {
vkDestroySemaphore(m_VKDevice, m_vWaitSemaphores[i], nullptr); vkDestroySemaphore(m_VKDevice, m_vWaitSemaphores[i], nullptr);
vkDestroySemaphore(m_VKDevice, m_vSigSemaphores[i], nullptr); vkDestroySemaphore(m_VKDevice, m_vSigSemaphores[i], nullptr);
vkDestroySemaphore(m_VKDevice, m_vMemorySemaphores[i], nullptr);
vkDestroyFence(m_VKDevice, m_vFrameFences[i], nullptr); vkDestroyFence(m_VKDevice, m_vFrameFences[i], nullptr);
} }
m_vWaitSemaphores.clear(); m_vWaitSemaphores.clear();
m_vSigSemaphores.clear(); m_vSigSemaphores.clear();
m_vMemorySemaphores.clear();
m_vFrameFences.clear(); m_vFrameFences.clear();
m_vImagesFences.clear(); m_vImagesFences.clear();
m_CurFrameSyncObject = 0;
} }
void DestroyBufferOfFrame(size_t ImageIndex, SFrameBuffers &Buffer) void DestroyBufferOfFrame(size_t ImageIndex, SFrameBuffers &Buffer)
@ -5433,7 +5429,7 @@ public:
} }
template<bool IsLastCleanup> template<bool IsLastCleanup>
void CleanupVulkan() void CleanupVulkan(size_t SwapchainCount)
{ {
if(IsLastCleanup) if(IsLastCleanup)
{ {
@ -5471,7 +5467,7 @@ public:
m_vStreamedVertexBuffers.clear(); m_vStreamedVertexBuffers.clear();
m_vStreamedUniformBuffers.clear(); m_vStreamedUniformBuffers.clear();
for(size_t i = 0; i < m_SwapChainImageCount; ++i) for(size_t i = 0; i < SwapchainCount; ++i)
{ {
ClearFrameData(i); ClearFrameData(i);
} }
@ -5480,11 +5476,11 @@ public:
m_vvFrameDelayedTextureCleanup.clear(); m_vvFrameDelayedTextureCleanup.clear();
m_vvFrameDelayedTextTexturesCleanup.clear(); m_vvFrameDelayedTextTexturesCleanup.clear();
m_StagingBufferCache.DestroyFrameData(m_SwapChainImageCount); m_StagingBufferCache.DestroyFrameData(SwapchainCount);
m_StagingBufferCacheImage.DestroyFrameData(m_SwapChainImageCount); m_StagingBufferCacheImage.DestroyFrameData(SwapchainCount);
m_VertexBufferCache.DestroyFrameData(m_SwapChainImageCount); m_VertexBufferCache.DestroyFrameData(SwapchainCount);
for(auto &ImageBufferCache : m_ImageBufferCaches) for(auto &ImageBufferCache : m_ImageBufferCaches)
ImageBufferCache.second.DestroyFrameData(m_SwapChainImageCount); ImageBufferCache.second.DestroyFrameData(SwapchainCount);
if(IsLastCleanup) if(IsLastCleanup)
{ {
@ -5562,7 +5558,7 @@ public:
if(OldSwapChainImageCount != m_SwapChainImageCount) if(OldSwapChainImageCount != m_SwapChainImageCount)
{ {
CleanupVulkan<false>(); CleanupVulkan<false>(OldSwapChainImageCount);
InitVulkan<false>(); InitVulkan<false>();
} }
@ -6116,20 +6112,20 @@ public:
template<bool IsFirstInitialization> template<bool IsFirstInitialization>
int InitVulkan() int InitVulkan()
{ {
if(!CreateDescriptorSetLayouts())
return -1;
if(!CreateTextDescriptorSetLayout())
return -1;
if(!CreateSpriteMultiUniformDescriptorSetLayout())
return -1;
if(!CreateQuadUniformDescriptorSetLayout())
return -1;
if(IsFirstInitialization) if(IsFirstInitialization)
{ {
if(!CreateDescriptorSetLayouts())
return -1;
if(!CreateTextDescriptorSetLayout())
return -1;
if(!CreateSpriteMultiUniformDescriptorSetLayout())
return -1;
if(!CreateQuadUniformDescriptorSetLayout())
return -1;
VkSwapchainKHR OldSwapChain = VK_NULL_HANDLE; VkSwapchainKHR OldSwapChain = VK_NULL_HANDLE;
if(InitVulkanSwapChain(OldSwapChain) != 0) if(InitVulkanSwapChain(OldSwapChain) != 0)
return -1; return -1;
@ -6626,7 +6622,7 @@ public:
DestroyIndexBuffer(m_IndexBuffer, m_IndexBufferMemory); DestroyIndexBuffer(m_IndexBuffer, m_IndexBufferMemory);
DestroyIndexBuffer(m_RenderIndexBuffer, m_RenderIndexBufferMemory); DestroyIndexBuffer(m_RenderIndexBuffer, m_RenderIndexBufferMemory);
CleanupVulkan<true>(); CleanupVulkan<true>(m_SwapChainImageCount);
return true; return true;
} }