GS/Vulkan: Prefer mailbox presentation for vsync-on

This commit is contained in:
Stenzek 2024-05-22 19:44:22 +10:00 committed by Connor McLaughlin
parent 68bbc2cc92
commit 99e38bc458
3 changed files with 30 additions and 24 deletions

View File

@ -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<VkPresentModeKHR> 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<VkSurfaceFormatKHR> 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<VkPresentModeKHR> present_mode = SelectPresentMode(m_surface, requested_mode);
if (!surface_format.has_value() || !present_mode.has_value())
return false;

View File

@ -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();

View File

@ -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();