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_vSigSemaphores;
std::vector<VkSemaphore> m_vMemorySemaphores;
std::vector<VkFence> m_vFrameFences;
std::vector<VkFence> m_vImagesFences;
@ -1053,7 +1051,7 @@ private:
std::vector<SStreamMemory<SFrameBuffers>> m_vStreamedVertexBuffers;
std::vector<SStreamMemory<SFrameUniformBuffers>> m_vStreamedUniformBuffers;
uint32_t m_CurFrames = 0;
uint32_t m_CurFrameSyncObject = 0;
uint32_t m_CurImageIndex = 0;
uint32_t m_CanvasWidth;
@ -2275,7 +2273,7 @@ protected:
return false;
}
VkSemaphore WaitSemaphore = m_vWaitSemaphores[m_CurFrames];
VkSemaphore WaitSemaphore = m_vWaitSemaphores[m_CurFrameSyncObject];
VkSubmitInfo SubmitInfo{};
SubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
@ -2304,13 +2302,13 @@ protected:
SubmitInfo.pWaitSemaphores = aWaitSemaphores.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.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)
{
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{};
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;
}
@ -2364,7 +2362,7 @@ protected:
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_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)
{
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
m_CurFrame++;
@ -5333,12 +5331,12 @@ public:
[[nodiscard]] bool CreateSyncObjects()
{
m_vWaitSemaphores.resize(m_SwapChainImageCount);
m_vSigSemaphores.resize(m_SwapChainImageCount);
// Create one more sync object than there are frames in flight
auto SyncObjectCount = m_SwapChainImageCount + 1;
m_vWaitSemaphores.resize(SyncObjectCount);
m_vSigSemaphores.resize(SyncObjectCount);
m_vMemorySemaphores.resize(m_SwapChainImageCount);
m_vFrameFences.resize(m_SwapChainImageCount);
m_vFrameFences.resize(SyncObjectCount);
m_vImagesFences.resize(m_SwapChainImageCount, VK_NULL_HANDLE);
VkSemaphoreCreateInfo CreateSemaphoreInfo{};
@ -5348,11 +5346,10 @@ public:
FenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
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 ||
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)
{
SetError(EGfxErrorType::GFX_ERROR_TYPE_INIT, "Creating swap chain sync objects(fences, semaphores) failed.");
@ -5365,21 +5362,20 @@ public:
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_vSigSemaphores[i], nullptr);
vkDestroySemaphore(m_VKDevice, m_vMemorySemaphores[i], nullptr);
vkDestroyFence(m_VKDevice, m_vFrameFences[i], nullptr);
}
m_vWaitSemaphores.clear();
m_vSigSemaphores.clear();
m_vMemorySemaphores.clear();
m_vFrameFences.clear();
m_vImagesFences.clear();
m_CurFrameSyncObject = 0;
}
void DestroyBufferOfFrame(size_t ImageIndex, SFrameBuffers &Buffer)
@ -5433,7 +5429,7 @@ public:
}
template<bool IsLastCleanup>
void CleanupVulkan()
void CleanupVulkan(size_t SwapchainCount)
{
if(IsLastCleanup)
{
@ -5471,7 +5467,7 @@ public:
m_vStreamedVertexBuffers.clear();
m_vStreamedUniformBuffers.clear();
for(size_t i = 0; i < m_SwapChainImageCount; ++i)
for(size_t i = 0; i < SwapchainCount; ++i)
{
ClearFrameData(i);
}
@ -5480,11 +5476,11 @@ public:
m_vvFrameDelayedTextureCleanup.clear();
m_vvFrameDelayedTextTexturesCleanup.clear();
m_StagingBufferCache.DestroyFrameData(m_SwapChainImageCount);
m_StagingBufferCacheImage.DestroyFrameData(m_SwapChainImageCount);
m_VertexBufferCache.DestroyFrameData(m_SwapChainImageCount);
m_StagingBufferCache.DestroyFrameData(SwapchainCount);
m_StagingBufferCacheImage.DestroyFrameData(SwapchainCount);
m_VertexBufferCache.DestroyFrameData(SwapchainCount);
for(auto &ImageBufferCache : m_ImageBufferCaches)
ImageBufferCache.second.DestroyFrameData(m_SwapChainImageCount);
ImageBufferCache.second.DestroyFrameData(SwapchainCount);
if(IsLastCleanup)
{
@ -5562,7 +5558,7 @@ public:
if(OldSwapChainImageCount != m_SwapChainImageCount)
{
CleanupVulkan<false>();
CleanupVulkan<false>(OldSwapChainImageCount);
InitVulkan<false>();
}
@ -6115,6 +6111,8 @@ public:
template<bool IsFirstInitialization>
int InitVulkan()
{
if(IsFirstInitialization)
{
if(!CreateDescriptorSetLayouts())
return -1;
@ -6128,8 +6126,6 @@ public:
if(!CreateQuadUniformDescriptorSetLayout())
return -1;
if(IsFirstInitialization)
{
VkSwapchainKHR OldSwapChain = VK_NULL_HANDLE;
if(InitVulkanSwapChain(OldSwapChain) != 0)
return -1;
@ -6626,7 +6622,7 @@ public:
DestroyIndexBuffer(m_IndexBuffer, m_IndexBufferMemory);
DestroyIndexBuffer(m_RenderIndexBuffer, m_RenderIndexBufferMemory);
CleanupVulkan<true>();
CleanupVulkan<true>(m_SwapChainImageCount);
return true;
}