diff --git a/pcsx2/GS/Renderers/Vulkan/VKSwapChain.cpp b/pcsx2/GS/Renderers/Vulkan/VKSwapChain.cpp index fc296ba20b..194f1dcfe0 100644 --- a/pcsx2/GS/Renderers/Vulkan/VKSwapChain.cpp +++ b/pcsx2/GS/Renderers/Vulkan/VKSwapChain.cpp @@ -4,6 +4,7 @@ #include "GS/Renderers/Vulkan/GSDeviceVK.h" #include "GS/Renderers/Vulkan/VKBuilders.h" #include "GS/Renderers/Vulkan/VKSwapChain.h" +#include "VMManager.h" #include "common/Assertions.h" #include "common/CocoaTools.h" @@ -250,28 +251,22 @@ std::optional VKSwapChain::SelectPresentMode(VkSurfaceKHR surf return it != present_modes.end(); }; - // Use preferred mode if available. - VkPresentModeKHR selected_mode; - if (CheckForMode(requested_mode)) - { - selected_mode = requested_mode; - } - else if (requested_mode != VK_PRESENT_MODE_FIFO_KHR && CheckForMode(VK_PRESENT_MODE_MAILBOX_KHR)) - { - // Prefer mailbox over fifo for adaptive vsync/no-vsync. This way it'll only delay one frame. - selected_mode = VK_PRESENT_MODE_MAILBOX_KHR; - } - else if (requested_mode == VK_PRESENT_MODE_FIFO_RELAXED_KHR && CheckForMode(VK_PRESENT_MODE_FIFO_KHR)) - { - // Fallback to FIFO if we're using any kind of vsync. - // This should never fail, FIFO is mandated. - selected_mode = VK_PRESENT_MODE_FIFO_KHR; - } - else - { - // Fall back to whatever is available. - selected_mode = present_modes[0]; - } + // Use preferred mode if available. + VkPresentModeKHR selected_mode; + if (CheckForMode(requested_mode)) + { + selected_mode = requested_mode; + } + else if (requested_mode == VK_PRESENT_MODE_IMMEDIATE_KHR && CheckForMode(VK_PRESENT_MODE_MAILBOX_KHR)) + { + // Prefer mailbox over FIFO for vsync-off, since we don't want to block. + selected_mode = VK_PRESENT_MODE_MAILBOX_KHR; + } + else + { + // Fallback to FIFO if we we can't use mailbox. This should never fail, FIFO is mandated. + selected_mode = VK_PRESENT_MODE_FIFO_KHR; + } DevCon.WriteLn("(SwapChain) Preferred present mode: %s, selected: %s", PresentModeToString(requested_mode), PresentModeToString(selected_mode)); @@ -284,9 +279,12 @@ bool VKSwapChain::CreateSwapChain() // Select swap chain format and present mode std::optional surface_format = SelectSurfaceFormat(m_surface); - // Prefer relaxed vsync if available, stalling is bad. + // Prefer mailbox if not syncing to host refresh, because that requires "real" vsync. const VkPresentModeKHR requested_mode = - m_vsync_enabled ? VK_PRESENT_MODE_FIFO_RELAXED_KHR : VK_PRESENT_MODE_IMMEDIATE_KHR; + m_vsync_enabled ? (VMManager::IsUsingVSyncForTiming() ? + VK_PRESENT_MODE_FIFO_KHR : + VK_PRESENT_MODE_MAILBOX_KHR) : + VK_PRESENT_MODE_IMMEDIATE_KHR; std::optional present_mode = SelectPresentMode(m_surface, requested_mode); if (!surface_format.has_value() || !present_mode.has_value()) return false; diff --git a/pcsx2/VMManager.cpp b/pcsx2/VMManager.cpp index cbef449f6b..653b3aab20 100644 --- a/pcsx2/VMManager.cpp +++ b/pcsx2/VMManager.cpp @@ -2105,6 +2105,11 @@ bool VMManager::IsTargetSpeedAdjustedToHost() return s_target_speed_synced_to_host; } +bool VMManager::IsUsingVSyncForTiming() +{ + return s_use_vsync_for_timing; +} + float VMManager::GetFrameRate() { return GetVerticalFrequency(); diff --git a/pcsx2/VMManager.h b/pcsx2/VMManager.h index 8c9b29d7e2..96d4316822 100644 --- a/pcsx2/VMManager.h +++ b/pcsx2/VMManager.h @@ -159,6 +159,9 @@ namespace VMManager /// Returns true if the target speed is being synchronized with the host's refresh rate. bool IsTargetSpeedAdjustedToHost(); + /// Returns true if host vsync is being used for frame timing/pacing, and not its internal throttler. + bool IsUsingVSyncForTiming(); + /// Returns the current frame rate of the virtual machine. float GetFrameRate();