From 223aa70171839a7afa7154d975d6035f9626eeb6 Mon Sep 17 00:00:00 2001 From: "Herman S." <429230+has207@users.noreply.github.com> Date: Sun, 2 Nov 2025 13:00:29 +0900 Subject: [PATCH] [Vulkan] Add semaphor reuse workaround and cvar --- src/xenia/ui/vulkan/functions/device_1_0.inc | 1 + src/xenia/ui/vulkan/vulkan_presenter.cc | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/xenia/ui/vulkan/functions/device_1_0.inc b/src/xenia/ui/vulkan/functions/device_1_0.inc index 02d183375..c2c251131 100644 --- a/src/xenia/ui/vulkan/functions/device_1_0.inc +++ b/src/xenia/ui/vulkan/functions/device_1_0.inc @@ -76,6 +76,7 @@ XE_UI_VULKAN_FUNCTION(vkResetDescriptorPool) XE_UI_VULKAN_FUNCTION(vkResetFences) XE_UI_VULKAN_FUNCTION(vkQueueBindSparse) XE_UI_VULKAN_FUNCTION(vkQueueSubmit) +XE_UI_VULKAN_FUNCTION(vkQueueWaitIdle) XE_UI_VULKAN_FUNCTION(vkUnmapMemory) XE_UI_VULKAN_FUNCTION(vkUpdateDescriptorSets) XE_UI_VULKAN_FUNCTION(vkWaitForFences) diff --git a/src/xenia/ui/vulkan/vulkan_presenter.cc b/src/xenia/ui/vulkan/vulkan_presenter.cc index a19722545..7151586c4 100644 --- a/src/xenia/ui/vulkan/vulkan_presenter.cc +++ b/src/xenia/ui/vulkan/vulkan_presenter.cc @@ -48,6 +48,11 @@ DEFINE_bool( "may present with tearing if frames don't meet the host display refresh " "rate.", "Vulkan"); +DEFINE_bool( + vulkan_semaphore_reuse_workaround, false, + "Wait for presentation queue idle before each frame to prevent semaphore " + "reuse. May fix rendering issues but causes significant performance loss.", + "Vulkan"); namespace xe { namespace ui { @@ -1411,6 +1416,18 @@ Presenter::PaintResult VulkanPresenter::PaintAndPresentImpl( VkSemaphore acquire_semaphore = paint_submission.acquire_semaphore(); + // WORKAROUND: Wait for presentation queue to be idle to ensure semaphore + // from previous present is not in use. This prevents + // VUID-vkQueueSubmit-pSignalSemaphores-00067. + // The semaphore is unsignaled by vkQueuePresentKHR, not by submission fences, + // so we must wait for the present queue specifically. + // TODO(has207): Proper fix requires per-swapchain-image semaphores. + // See https://docs.vulkan.org/guide/latest/swapchain_semaphore_reuse.html + if (cvars::vulkan_semaphore_reuse_workaround) { + const VulkanDevice::Queue::Acquisition queue_acquisition = + vulkan_device_->AcquireQueue(paint_context_.present_queue_family, 0); + dfn.vkQueueWaitIdle(queue_acquisition.queue()); + } uint32_t swapchain_image_index; VkResult acquire_result = dfn.vkAcquireNextImageKHR(