vk_swapchain: Use immediate present mode when mailbox is unavailable and FPS is unlocked
Allows drivers that do not support VK_PRESENT_MODE_MAILBOX_KHR the ability to present at a framerate higher than the monitor's refresh rate when the FPS is unlocked.
This commit is contained in:
		| @@ -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; | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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{}; | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 ameerj
					ameerj