From 5c23a8e012baf048f72e358743dc2c5ea50e9a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Quang=20Ng=C3=B4?= Date: Sat, 28 Dec 2024 14:30:21 +0700 Subject: [PATCH] renderer_vulkan: Fix deadlock when resizing the SDL window --- src/video_core/renderer_vulkan/vk_presenter.cpp | 17 ++++++++++++++--- src/video_core/renderer_vulkan/vk_swapchain.cpp | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_presenter.cpp b/src/video_core/renderer_vulkan/vk_presenter.cpp index bc55cde2309..93206262d3b 100644 --- a/src/video_core/renderer_vulkan/vk_presenter.cpp +++ b/src/video_core/renderer_vulkan/vk_presenter.cpp @@ -636,8 +636,22 @@ void Presenter::Present(Frame* frame) { if (!swapchain.AcquireNextImage()) { swapchain.Recreate(window.GetWidth(), window.GetHeight()); + if (!swapchain.AcquireNextImage()) { + // User resizes the window too fast and GPU can't keep up. Skip this frame. + LOG_WARNING(Render_Vulkan, "Skipping frame!"); + // Free the frame for reuse + std::scoped_lock fl{free_mutex}; + free_queue.push(frame); + free_cv.notify_one(); + return; + } } + // Reset fence for queue submission. Do it here instead of GetRenderFrame() because we may + // skip frame because of slow swapchain recreation. If a frame skip occurs, we skip signal + // the frame's present fence and future GetRenderFrame() call will hang waiting for this frame. + instance.GetDevice().resetFences(frame->present_done); + ImGui::Core::NewFrame(); const vk::Image swapchain_image = swapchain.Image(); @@ -776,9 +790,6 @@ Frame* Presenter::GetRenderFrame() { } } - // Reset fence for next queue submission. - device.resetFences(frame->present_done); - // If the window dimensions changed, recreate this frame if (frame->width != window.GetWidth() || frame->height != window.GetHeight()) { RecreateFrame(frame, window.GetWidth(), window.GetHeight()); diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 380660a2f06..44f4be6dd64 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -84,6 +84,7 @@ void Swapchain::Create(u32 width_, u32 height_, vk::SurfaceKHR surface_) { } void Swapchain::Recreate(u32 width_, u32 height_) { + LOG_DEBUG(Render_Vulkan, "Recreate the swapchain: width={} height={}", width_, height_); Create(width_, height_, surface); }