diff options
Diffstat (limited to 'src')
| -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) { | |||
| 149 | const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout(); | 149 | const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout(); |
| 150 | swapchain.Create(layout.width, layout.height, is_srgb); | 150 | swapchain.Create(layout.width, layout.height, is_srgb); |
| 151 | }; | 151 | }; |
| 152 | if (swapchain.IsSubOptimal() || swapchain.HasColorSpaceChanged(is_srgb)) { | 152 | if (swapchain.NeedsRecreation(is_srgb)) { |
| 153 | recreate_swapchain(); | 153 | recreate_swapchain(); |
| 154 | } | 154 | } |
| 155 | bool is_outdated; | 155 | 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 @@ | |||
| 9 | 9 | ||
| 10 | #include "common/assert.h" | 10 | #include "common/assert.h" |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/settings.h" | ||
| 12 | #include "core/core.h" | 13 | #include "core/core.h" |
| 13 | #include "core/frontend/framebuffer_layout.h" | 14 | #include "core/frontend/framebuffer_layout.h" |
| 14 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 15 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| @@ -36,8 +37,19 @@ VkSurfaceFormatKHR ChooseSwapSurfaceFormat(vk::Span<VkSurfaceFormatKHR> formats) | |||
| 36 | 37 | ||
| 37 | VkPresentModeKHR ChooseSwapPresentMode(vk::Span<VkPresentModeKHR> modes) { | 38 | VkPresentModeKHR ChooseSwapPresentMode(vk::Span<VkPresentModeKHR> modes) { |
| 38 | // Mailbox doesn't lock the application like fifo (vsync), prefer it | 39 | // Mailbox doesn't lock the application like fifo (vsync), prefer it |
| 39 | const auto found = std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR); | 40 | const auto found_mailbox = std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR); |
| 40 | return found != modes.end() ? *found : VK_PRESENT_MODE_FIFO_KHR; | 41 | if (found_mailbox != modes.end()) { |
| 42 | return VK_PRESENT_MODE_MAILBOX_KHR; | ||
| 43 | } | ||
| 44 | if (Settings::values.disable_fps_limit.GetValue()) { | ||
| 45 | // FIFO present mode locks the framerate to the monitor's refresh rate, | ||
| 46 | // Find an alternative to surpass this limitation if FPS is unlocked. | ||
| 47 | const auto found_imm = std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR); | ||
| 48 | if (found_imm != modes.end()) { | ||
| 49 | return VK_PRESENT_MODE_IMMEDIATE_KHR; | ||
| 50 | } | ||
| 51 | } | ||
| 52 | return VK_PRESENT_MODE_FIFO_KHR; | ||
| 41 | } | 53 | } |
| 42 | 54 | ||
| 43 | VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, u32 width, u32 height) { | 55 | VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, u32 width, u32 height) { |
| @@ -143,7 +155,7 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, | |||
| 143 | const auto present_modes{physical_device.GetSurfacePresentModesKHR(surface)}; | 155 | const auto present_modes{physical_device.GetSurfacePresentModesKHR(surface)}; |
| 144 | 156 | ||
| 145 | const VkSurfaceFormatKHR surface_format{ChooseSwapSurfaceFormat(formats)}; | 157 | const VkSurfaceFormatKHR surface_format{ChooseSwapSurfaceFormat(formats)}; |
| 146 | const VkPresentModeKHR present_mode{ChooseSwapPresentMode(present_modes)}; | 158 | present_mode = ChooseSwapPresentMode(present_modes); |
| 147 | 159 | ||
| 148 | u32 requested_image_count{capabilities.minImageCount + 1}; | 160 | u32 requested_image_count{capabilities.minImageCount + 1}; |
| 149 | if (capabilities.maxImageCount > 0 && requested_image_count > capabilities.maxImageCount) { | 161 | if (capabilities.maxImageCount > 0 && requested_image_count > capabilities.maxImageCount) { |
| @@ -196,6 +208,7 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, | |||
| 196 | 208 | ||
| 197 | extent = swapchain_ci.imageExtent; | 209 | extent = swapchain_ci.imageExtent; |
| 198 | current_srgb = srgb; | 210 | current_srgb = srgb; |
| 211 | current_fps_unlocked = Settings::values.disable_fps_limit.GetValue(); | ||
| 199 | 212 | ||
| 200 | images = swapchain.GetImages(); | 213 | images = swapchain.GetImages(); |
| 201 | image_count = static_cast<u32>(images.size()); | 214 | image_count = static_cast<u32>(images.size()); |
| @@ -248,4 +261,14 @@ void VKSwapchain::Destroy() { | |||
| 248 | swapchain.reset(); | 261 | swapchain.reset(); |
| 249 | } | 262 | } |
| 250 | 263 | ||
| 264 | bool VKSwapchain::HasFpsUnlockChanged() const { | ||
| 265 | return current_fps_unlocked != Settings::values.disable_fps_limit.GetValue(); | ||
| 266 | } | ||
| 267 | |||
| 268 | bool VKSwapchain::NeedsPresentModeUpdate() const { | ||
| 269 | // Mailbox present mode is the ideal for all scenarios. If it is not available, | ||
| 270 | // A different present mode is needed to support unlocked FPS above the monitor's refresh rate. | ||
| 271 | return present_mode != VK_PRESENT_MODE_MAILBOX_KHR && HasFpsUnlockChanged(); | ||
| 272 | } | ||
| 273 | |||
| 251 | } // namespace Vulkan | 274 | } // 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: | |||
| 33 | /// Presents the rendered image to the swapchain. | 33 | /// Presents the rendered image to the swapchain. |
| 34 | void Present(VkSemaphore render_semaphore); | 34 | void Present(VkSemaphore render_semaphore); |
| 35 | 35 | ||
| 36 | /// Returns true when the swapchain needs to be recreated. | ||
| 37 | bool NeedsRecreation(bool is_srgb) const { | ||
| 38 | return HasColorSpaceChanged(is_srgb) || IsSubOptimal() || NeedsPresentModeUpdate(); | ||
| 39 | } | ||
| 40 | |||
| 36 | /// Returns true when the color space has changed. | 41 | /// Returns true when the color space has changed. |
| 37 | bool HasColorSpaceChanged(bool is_srgb) const { | 42 | bool HasColorSpaceChanged(bool is_srgb) const { |
| 38 | return current_srgb != is_srgb; | 43 | return current_srgb != is_srgb; |
| @@ -84,6 +89,10 @@ private: | |||
| 84 | 89 | ||
| 85 | void Destroy(); | 90 | void Destroy(); |
| 86 | 91 | ||
| 92 | bool HasFpsUnlockChanged() const; | ||
| 93 | |||
| 94 | bool NeedsPresentModeUpdate() const; | ||
| 95 | |||
| 87 | const VkSurfaceKHR surface; | 96 | const VkSurfaceKHR surface; |
| 88 | const Device& device; | 97 | const Device& device; |
| 89 | VKScheduler& scheduler; | 98 | VKScheduler& scheduler; |
| @@ -102,8 +111,10 @@ private: | |||
| 102 | 111 | ||
| 103 | VkFormat image_view_format{}; | 112 | VkFormat image_view_format{}; |
| 104 | VkExtent2D extent{}; | 113 | VkExtent2D extent{}; |
| 114 | VkPresentModeKHR present_mode{}; | ||
| 105 | 115 | ||
| 106 | bool current_srgb{}; | 116 | bool current_srgb{}; |
| 117 | bool current_fps_unlocked{}; | ||
| 107 | bool is_outdated{}; | 118 | bool is_outdated{}; |
| 108 | bool is_suboptimal{}; | 119 | bool is_suboptimal{}; |
| 109 | }; | 120 | }; |