diff options
| -rw-r--r-- | src/video_core/renderer_vulkan/renderer_vulkan.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_swapchain.cpp | 29 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_swapchain.h | 11 | 
3 files changed, 38 insertions, 4 deletions
| diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 9ff0a28cd..adb6b7a3b 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -149,7 +149,7 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {          const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout();          swapchain.Create(layout.width, layout.height, is_srgb);      }; -    if (swapchain.IsSubOptimal() || swapchain.HasColorSpaceChanged(is_srgb)) { +    if (swapchain.NeedsRecreation(is_srgb)) {          recreate_swapchain();      }      bool is_outdated; diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index aadf03cb0..8972a6921 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -9,6 +9,7 @@  #include "common/assert.h"  #include "common/logging/log.h" +#include "common/settings.h"  #include "core/core.h"  #include "core/frontend/framebuffer_layout.h"  #include "video_core/renderer_vulkan/vk_scheduler.h" @@ -36,8 +37,19 @@ VkSurfaceFormatKHR ChooseSwapSurfaceFormat(vk::Span<VkSurfaceFormatKHR> formats)  VkPresentModeKHR ChooseSwapPresentMode(vk::Span<VkPresentModeKHR> modes) {      // Mailbox doesn't lock the application like fifo (vsync), prefer it -    const auto found = std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR); -    return found != modes.end() ? *found : VK_PRESENT_MODE_FIFO_KHR; +    const auto found_mailbox = std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR); +    if (found_mailbox != modes.end()) { +        return VK_PRESENT_MODE_MAILBOX_KHR; +    } +    if (Settings::values.disable_fps_limit.GetValue()) { +        // FIFO present mode locks the framerate to the monitor's refresh rate, +        // Find an alternative to surpass this limitation if FPS is unlocked. +        const auto found_imm = std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR); +        if (found_imm != modes.end()) { +            return VK_PRESENT_MODE_IMMEDIATE_KHR; +        } +    } +    return VK_PRESENT_MODE_FIFO_KHR;  }  VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, u32 width, u32 height) { @@ -143,7 +155,7 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,      const auto present_modes{physical_device.GetSurfacePresentModesKHR(surface)};      const VkSurfaceFormatKHR surface_format{ChooseSwapSurfaceFormat(formats)}; -    const VkPresentModeKHR present_mode{ChooseSwapPresentMode(present_modes)}; +    present_mode = ChooseSwapPresentMode(present_modes);      u32 requested_image_count{capabilities.minImageCount + 1};      if (capabilities.maxImageCount > 0 && requested_image_count > capabilities.maxImageCount) { @@ -196,6 +208,7 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,      extent = swapchain_ci.imageExtent;      current_srgb = srgb; +    current_fps_unlocked = Settings::values.disable_fps_limit.GetValue();      images = swapchain.GetImages();      image_count = static_cast<u32>(images.size()); @@ -248,4 +261,14 @@ void VKSwapchain::Destroy() {      swapchain.reset();  } +bool VKSwapchain::HasFpsUnlockChanged() const { +    return current_fps_unlocked != Settings::values.disable_fps_limit.GetValue(); +} + +bool VKSwapchain::NeedsPresentModeUpdate() const { +    // Mailbox present mode is the ideal for all scenarios. If it is not available, +    // A different present mode is needed to support unlocked FPS above the monitor's refresh rate. +    return present_mode != VK_PRESENT_MODE_MAILBOX_KHR && HasFpsUnlockChanged(); +} +  } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h index 5bce41e21..61a6d959e 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.h +++ b/src/video_core/renderer_vulkan/vk_swapchain.h @@ -33,6 +33,11 @@ public:      /// Presents the rendered image to the swapchain.      void Present(VkSemaphore render_semaphore); +    /// Returns true when the swapchain needs to be recreated. +    bool NeedsRecreation(bool is_srgb) const { +        return HasColorSpaceChanged(is_srgb) || IsSubOptimal() || NeedsPresentModeUpdate(); +    } +      /// Returns true when the color space has changed.      bool HasColorSpaceChanged(bool is_srgb) const {          return current_srgb != is_srgb; @@ -84,6 +89,10 @@ private:      void Destroy(); +    bool HasFpsUnlockChanged() const; + +    bool NeedsPresentModeUpdate() const; +      const VkSurfaceKHR surface;      const Device& device;      VKScheduler& scheduler; @@ -102,8 +111,10 @@ private:      VkFormat image_view_format{};      VkExtent2D extent{}; +    VkPresentModeKHR present_mode{};      bool current_srgb{}; +    bool current_fps_unlocked{};      bool is_outdated{};      bool is_suboptimal{};  }; | 
