Skip to content

Commit a255d24

Browse files
Fixed Vulkan swap chain errors (close #682)
1 parent 9053bcf commit a255d24

File tree

1 file changed

+11
-7
lines changed

1 file changed

+11
-7
lines changed

Graphics/GraphicsEngineVulkan/src/SwapChainVkImpl.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -617,15 +617,15 @@ VkResult SwapChainVkImpl::AcquireNextImage(DeviceContextVkImpl* pDeviceCtxVk)
617617
m_FrameCompleteFence->Wait(m_FrameIndex - m_SwapChainDesc.BufferCount);
618618
}
619619

620-
VkSemaphore ImageAcquiredSemaphore = m_ImageAcquiredSemaphores[m_SemaphoreIndex]->Get();
620+
RefCntAutoPtr<ManagedSemaphore>& ImageAcquiredSemaphore = m_ImageAcquiredSemaphores[m_SemaphoreIndex];
621621

622-
VkResult res = vkAcquireNextImageKHR(LogicalDevice.GetVkDevice(), m_VkSwapChain, UINT64_MAX, ImageAcquiredSemaphore, VK_NULL_HANDLE, &m_BackBufferIndex);
622+
VkResult res = vkAcquireNextImageKHR(LogicalDevice.GetVkDevice(), m_VkSwapChain, UINT64_MAX, ImageAcquiredSemaphore->Get(), VK_NULL_HANDLE, &m_BackBufferIndex);
623623
if (res == VK_SUCCESS)
624624
{
625625
// Next command in the device context must wait for the next image to be acquired.
626-
// Unlike fences or events, the act of waiting for a semaphore also unsignals that semaphore (6.4.2).
626+
// Unlike fences or events, the act of waiting for a semaphore also unsignals that semaphore.
627627
// Swapchain image may be used as render target or as destination for copy command.
628-
pDeviceCtxVk->AddWaitSemaphore(m_ImageAcquiredSemaphores[m_SemaphoreIndex], VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT);
628+
pDeviceCtxVk->AddWaitSemaphore(ImageAcquiredSemaphore, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT);
629629
if (!m_SwapChainImagesInitialized[m_BackBufferIndex])
630630
{
631631
// Vulkan validation layers do not like uninitialized memory.
@@ -661,13 +661,17 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval)
661661
ITexture* pBackBuffer = GetCurrentBackBufferRTV()->GetTexture();
662662
pImmediateCtxVk->UnbindTextureFromFramebuffer(ClassPtrCast<TextureVkImpl>(pBackBuffer), false);
663663

664+
// To properly handle the case where vkAcquireNextImageKHR returns the same index twice in a row, use
665+
// a separate semaphore per swapchain image and index these semaphores using the index of the acquired image
666+
// https://github.com/DiligentGraphics/DiligentCore/issues/682
667+
RefCntAutoPtr<ManagedSemaphore>& DrawCompleteSemaphore = m_DrawCompleteSemaphores[m_BackBufferIndex];
664668
if (!m_IsMinimized)
665669
{
666670
// TransitionImageLayout() never triggers flush
667671
pImmediateCtxVk->TransitionImageLayout(pBackBuffer, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
668672
// The context can be empty if no render commands were issued by the app
669673
//VERIFY(pImmediateCtxVk->GetNumCommandsInCtx() != 0, "The context must not be flushed");
670-
pImmediateCtxVk->AddSignalSemaphore(m_DrawCompleteSemaphores[m_SemaphoreIndex]);
674+
pImmediateCtxVk->AddSignalSemaphore(DrawCompleteSemaphore);
671675
pImmediateCtxVk->EnqueueSignal(m_FrameCompleteFence, m_FrameIndex++);
672676
}
673677

@@ -680,8 +684,8 @@ void SwapChainVkImpl::Present(Uint32 SyncInterval)
680684
PresentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
681685
PresentInfo.pNext = nullptr;
682686
PresentInfo.waitSemaphoreCount = 1;
683-
// Unlike fences or events, the act of waiting for a semaphore also unsignals that semaphore (6.4.2)
684-
VkSemaphore WaitSemaphore[] = {m_DrawCompleteSemaphores[m_SemaphoreIndex]->Get()};
687+
// Unlike fences or events, the act of waiting for a semaphore also unsignals that semaphore
688+
VkSemaphore WaitSemaphore[] = {DrawCompleteSemaphore->Get()};
685689
PresentInfo.pWaitSemaphores = WaitSemaphore;
686690
PresentInfo.swapchainCount = 1;
687691
PresentInfo.pSwapchains = &m_VkSwapChain;

0 commit comments

Comments
 (0)