Fix Vulkan synchronization between CPU and GPU to prevent running over frames in flight

This commit is contained in:
Wojtek Figat
2026-01-28 20:43:01 +01:00
parent 45306ca20e
commit 43b337e163
7 changed files with 57 additions and 12 deletions

View File

@@ -20,7 +20,7 @@ void BackBufferVulkan::Setup(GPUSwapChainVulkan* window, VkImage backbuffer, Pix
initResource(VK_IMAGE_LAYOUT_UNDEFINED);
Device = window->GetDevice();
Handle.Init(window->GetDevice(), this, backbuffer, 1, format, MSAALevel::None, extent, VK_IMAGE_VIEW_TYPE_2D);
Handle.Init(Device, this, backbuffer, 1, format, MSAALevel::None, extent, VK_IMAGE_VIEW_TYPE_2D);
RenderingDoneSemaphore = New<SemaphoreVulkan>(Device);
ImageAcquiredSemaphore = New<SemaphoreVulkan>(Device);
}
@@ -30,6 +30,12 @@ void BackBufferVulkan::Release()
Handle.Release();
Delete(RenderingDoneSemaphore);
Delete(ImageAcquiredSemaphore);
if (SubmitCmdBuffer)
{
SubmitCmdBuffer->Wait();
SubmitCmdBuffer = nullptr;
}
Device = nullptr;
}
GPUSwapChainVulkan::GPUSwapChainVulkan(GPUDeviceVulkan* device, Window* window)
@@ -133,6 +139,22 @@ GPUTextureView* GPUSwapChainVulkan::GetBackBufferView()
return &_backBuffers[_acquiredImageIndex].Handle;
}
void GPUSwapChainVulkan::Begin(RenderTask* task)
{
GPUSwapChain::Begin(task);
// Wait for the backbuffer to be available
if (_currentImageIndex != -1)
{
auto& backBuffer = _backBuffers[_currentImageIndex];
if (backBuffer.SubmitCmdBuffer)
{
backBuffer.SubmitCmdBuffer->Wait();
backBuffer.SubmitCmdBuffer = nullptr;
}
}
}
bool GPUSwapChainVulkan::Resize(int32 width, int32 height)
{
// Check if size won't change
@@ -540,6 +562,11 @@ void GPUSwapChainVulkan::Present(bool vsync)
context->AddImageBarrier(backBuffer, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
context->FlushBarriers();
// Cache a command buffer to wait on its fence before drawing to this backbuffer again
auto& acquiredBackBuffer = _backBuffers[_acquiredImageIndex];
ASSERT(acquiredBackBuffer.SubmitCmdBuffer == nullptr);
acquiredBackBuffer.SubmitCmdBuffer = context->GetCmdBufferManager()->GetActiveCmdBuffer();
context->GetCmdBufferManager()->SubmitActiveCmdBuffer(_backBuffers[_acquiredImageIndex].RenderingDoneSemaphore);
// Present the back buffer to the viewport window