diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 4f1d3b4e3..89636f864 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -37,6 +38,27 @@ VkSurfaceFormatKHR ChooseSwapSurfaceFormat(vk::Span formats) static VkPresentModeKHR ChooseSwapPresentMode(bool has_imm, bool has_mailbox, bool has_fifo_relaxed) { + // Wayland-specific optimizations for low-latency presentation. + if (Settings::values.is_wayland_platform.GetValue()) { + LOG_INFO(Render_Vulkan, "Wayland platform detected. Prioritizing low-latency presentation modes."); + + // On Wayland, Mailbox is strongly preferred for smooth, low-latency rendering. + if (has_mailbox) { + LOG_INFO(Render_Vulkan, "Using Mailbox presentation mode for Wayland."); + return VK_PRESENT_MODE_MAILBOX_KHR; + } + + // Allow Immediate for lowest latency if the user explicitly chooses it. + if (has_imm && Settings::values.vsync_mode.GetValue() == Settings::VSyncMode::Immediate) { + LOG_INFO(Render_Vulkan, "Using Immediate presentation mode for Wayland (tearing may occur)."); + return VK_PRESENT_MODE_IMMEDIATE_KHR; + } + + // Fallback to standard FIFO (V-Sync) if Mailbox is not available. + LOG_INFO(Render_Vulkan, "Mailbox not available. Falling back to FIFO presentation mode for Wayland."); + return VK_PRESENT_MODE_FIFO_KHR; + } + // Mailbox doesn't lock the application like FIFO (vsync) // FIFO present mode locks the framerate to the monitor's refresh rate Settings::VSyncMode setting = [has_imm, has_mailbox]() { @@ -46,35 +68,35 @@ static VkPresentModeKHR ChooseSwapPresentMode(bool has_imm, bool has_mailbox, return mode; } switch (mode) { - case Settings::VSyncMode::Fifo: - case Settings::VSyncMode::FifoRelaxed: - if (has_mailbox) { - return Settings::VSyncMode::Mailbox; - } else if (has_imm) { - return Settings::VSyncMode::Immediate; - } - [[fallthrough]]; - default: - return mode; + case Settings::VSyncMode::Fifo: + case Settings::VSyncMode::FifoRelaxed: + if (has_mailbox) { + return Settings::VSyncMode::Mailbox; + } else if (has_imm) { + return Settings::VSyncMode::Immediate; + } + [[fallthrough]]; + default: + return mode; } }(); if ((setting == Settings::VSyncMode::Mailbox && !has_mailbox) || (setting == Settings::VSyncMode::Immediate && !has_imm) || (setting == Settings::VSyncMode::FifoRelaxed && !has_fifo_relaxed)) { setting = Settings::VSyncMode::Fifo; - } + } - switch (setting) { - case Settings::VSyncMode::Immediate: - return VK_PRESENT_MODE_IMMEDIATE_KHR; - case Settings::VSyncMode::Mailbox: - return VK_PRESENT_MODE_MAILBOX_KHR; - case Settings::VSyncMode::Fifo: - return VK_PRESENT_MODE_FIFO_KHR; - case Settings::VSyncMode::FifoRelaxed: - return VK_PRESENT_MODE_FIFO_RELAXED_KHR; - default: - return VK_PRESENT_MODE_FIFO_KHR; + switch (setting) { + case Settings::VSyncMode::Immediate: + return VK_PRESENT_MODE_IMMEDIATE_KHR; + case Settings::VSyncMode::Mailbox: + return VK_PRESENT_MODE_MAILBOX_KHR; + case Settings::VSyncMode::Fifo: + return VK_PRESENT_MODE_FIFO_KHR; + case Settings::VSyncMode::FifoRelaxed: + return VK_PRESENT_MODE_FIFO_RELAXED_KHR; + default: + return VK_PRESENT_MODE_FIFO_KHR; } }