diff options
| author | lat9nq <22451773+lat9nq@users.noreply.github.com> | 2023-05-01 20:31:22 -0400 | 
|---|---|---|
| committer | lat9nq <22451773+lat9nq@users.noreply.github.com> | 2023-05-02 21:52:43 -0400 | 
| commit | 952b2710920fdeef705a357762a7925483d27d20 (patch) | |
| tree | 91cb395a879e6101b2a4f9c7a556629483afc1f5 | |
| parent | a090a380be674ae001aea47434e1a2f008574a48 (diff) | |
vk_swapchain: Use certain modes for unlocked
Uses mailbox, then immediate for unlocked framerate depending on
support for either. Also adds support for FIFO_RELAXED.
This function now assumes vsync_mode was originially configured to a value
that the driver supports.
vk_swapchain: ChooseSwapPresentMode determines updates
Simplifies swapchain a bit and allows us to change the present mode
during guest runtime.
vk_swapchain: Fix MSVC error
vk_swapchain: Enforce available present modes
Some frontends don't check the value of vsync_mode before comitting it.
Just as well, since a driver update or misconfiguration could problems
in the swap chain.
vk_swapchain: Silence warnings
Silences GCC warnings implicit-fallthrough and shadow, which apparently
are not enabled on clang.
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_swapchain.cpp | 70 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_swapchain.h | 6 | 
2 files changed, 50 insertions, 26 deletions
| diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 08d82769c..1e80ce463 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp @@ -14,6 +14,7 @@  #include "video_core/renderer_vulkan/vk_swapchain.h"  #include "video_core/vulkan_common/vulkan_device.h"  #include "video_core/vulkan_common/vulkan_wrapper.h" +#include "vulkan/vulkan_core.h"  namespace Vulkan { @@ -33,24 +34,47 @@ VkSurfaceFormatKHR ChooseSwapSurfaceFormat(vk::Span<VkSurfaceFormatKHR> formats)      return found != formats.end() ? *found : formats[0];  } -VkPresentModeKHR ChooseSwapPresentMode(vk::Span<VkPresentModeKHR> modes) { -    // Mailbox (triple buffering) doesn't lock the application like FIFO (vsync) +static constexpr VkPresentModeKHR ChooseSwapPresentMode(bool has_imm, bool has_mailbox, +                                                        bool has_fifo_relaxed) { +    // Mailbox doesn't lock the application like FIFO (vsync)      // FIFO present mode locks the framerate to the monitor's refresh rate -    const bool has_mailbox = -        std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR) != modes.end(); -    const bool has_imm = -        std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR) != modes.end(); -    const Settings::VSyncMode mode = Settings::values.vsync_mode.GetValue(); +    Settings::VSyncMode setting = [has_imm, has_mailbox]() { +        // Choose Mailbox or Immediate if unlocked and those modes are supported +        const auto mode = Settings::values.vsync_mode.GetValue(); +        if (Settings::values.use_speed_limit.GetValue()) { +            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; +        } +    }(); +    if ((setting == Settings::VSyncMode::Mailbox && !has_mailbox) || +        (setting == Settings::VSyncMode::Immediate && !has_imm) || +        (setting == Settings::VSyncMode::FIFORelaxed && !has_fifo_relaxed)) { +        setting = Settings::VSyncMode::FIFO; +    } -    if (mode == Settings::VSyncMode::Immediate && has_imm) { -        LOG_INFO(Render_Vulkan, "Using swap present mode Immediate"); +    switch (setting) { +    case Settings::VSyncMode::Immediate:          return VK_PRESENT_MODE_IMMEDIATE_KHR; -    } else if (mode == Settings::VSyncMode::Mailbox && has_mailbox) { -        LOG_INFO(Render_Vulkan, "Using swap present mode Mailbox"); +    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;      } -    LOG_INFO(Render_Vulkan, "Using swap present mode FIFO"); -    return VK_PRESENT_MODE_FIFO_KHR;  }  VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, u32 width, u32 height) { @@ -168,11 +192,17 @@ void Swapchain::Present(VkSemaphore render_semaphore) {  void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bool srgb) {      const auto physical_device{device.GetPhysical()};      const auto formats{physical_device.GetSurfaceFormatsKHR(surface)}; -    const auto present_modes{physical_device.GetSurfacePresentModesKHR(surface)}; +    const auto present_modes = physical_device.GetSurfacePresentModesKHR(surface); +    has_mailbox = std::find(present_modes.begin(), present_modes.end(), +                            VK_PRESENT_MODE_MAILBOX_KHR) != present_modes.end(); +    has_imm = std::find(present_modes.begin(), present_modes.end(), +                        VK_PRESENT_MODE_IMMEDIATE_KHR) != present_modes.end(); +    has_fifo_relaxed = std::find(present_modes.begin(), present_modes.end(), +                                 VK_PRESENT_MODE_FIFO_RELAXED_KHR) != present_modes.end();      const VkCompositeAlphaFlagBitsKHR alpha_flags{ChooseAlphaFlags(capabilities)};      surface_format = ChooseSwapSurfaceFormat(formats); -    present_mode = ChooseSwapPresentMode(present_modes); +    present_mode = ChooseSwapPresentMode(has_imm, has_mailbox, has_fifo_relaxed);      u32 requested_image_count{capabilities.minImageCount + 1};      // Ensure Triple buffering if possible. @@ -233,7 +263,6 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bo      extent = swapchain_ci.imageExtent;      current_srgb = srgb; -    current_fps_unlocked = !Settings::values.use_speed_limit.GetValue();      images = swapchain.GetImages();      image_count = static_cast<u32>(images.size()); @@ -255,14 +284,9 @@ void Swapchain::Destroy() {      swapchain.reset();  } -bool Swapchain::HasFpsUnlockChanged() const { -    return current_fps_unlocked != !Settings::values.use_speed_limit.GetValue(); -} -  bool Swapchain::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(); +    const auto requested_mode = ChooseSwapPresentMode(has_imm, has_mailbox, has_fifo_relaxed); +    return present_mode != requested_mode;  }  } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h index 419742586..bf1ea7254 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.h +++ b/src/video_core/renderer_vulkan/vk_swapchain.h @@ -116,8 +116,6 @@ private:      void Destroy(); -    bool HasFpsUnlockChanged() const; -      bool NeedsPresentModeUpdate() const;      const VkSurfaceKHR surface; @@ -142,9 +140,11 @@ private:      VkExtent2D extent{};      VkPresentModeKHR present_mode{};      VkSurfaceFormatKHR surface_format{}; +    bool has_imm{false}; +    bool has_mailbox{false}; +    bool has_fifo_relaxed{false};      bool current_srgb{}; -    bool current_fps_unlocked{};      bool is_outdated{};      bool is_suboptimal{};  }; | 
