From 23ba2f62f8a3e8ff94675a79bad3d7a74dfe673b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 25 Sep 2026 09:06:56 -0600 Subject: [PATCH] Vulkan: Don't wait for an image in frames that never acquired one A frame that never draws to the backbuffer never acquires an image, but its final submit still waited on the acquire semaphore, which nothing signals, hanging the GPU. Skip the swap for such frames when finishing them. This replaces the check for a frame with no steps at all, which could also set it partway through a frame that acquires later. Co-Authored-By: Claude Opus 5.5 (1M context) --- Common/GPU/Vulkan/VulkanRenderManager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index ea0ead8886..bcde55490b 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -1706,14 +1706,15 @@ void VulkanRenderManager::Run(VKRRenderThreadTask &task) { frameData.profile.descWriteTime = time_now_d() - descStart; queueRunner_.PreprocessSteps(task.steps); - // Likely during shutdown, happens in headless. - if (task.steps.empty() && !frameData.hasAcquired) - frameData.skipSwap = true; //queueRunner_.LogSteps(stepsOnThread, false); queueRunner_.RunSteps(task.steps, task.frame, frameData, frameDataShared_); switch (task.runType) { case VKRRunType::SUBMIT: + // A frame that never drew to the backbuffer never acquired an image, so there's nothing to + // wait for or present. Headless has such frames, and so does shutdown. + if (!frameData.hasAcquired) + frameData.skipSwap = true; frameData.Submit(vulkan_, FrameSubmitType::FinishFrame, frameDataShared_); break;