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:
parent
e4318d2207
commit
35e5a67a83
|
@ -149,7 +149,7 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
|
||||||
const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout();
|
const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout();
|
||||||
swapchain.Create(layout.width, layout.height, is_srgb);
|
swapchain.Create(layout.width, layout.height, is_srgb);
|
||||||
};
|
};
|
||||||
if (swapchain.IsSubOptimal() || swapchain.HasColorSpaceChanged(is_srgb)) {
|
if (swapchain.NeedsRecreation(is_srgb)) {
|
||||||
recreate_swapchain();
|
recreate_swapchain();
|
||||||
}
|
}
|
||||||
bool is_outdated;
|
bool is_outdated;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/frontend/framebuffer_layout.h"
|
#include "core/frontend/framebuffer_layout.h"
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.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) {
|
VkPresentModeKHR ChooseSwapPresentMode(vk::Span<VkPresentModeKHR> modes) {
|
||||||
// Mailbox doesn't lock the application like fifo (vsync), prefer it
|
// 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);
|
const auto found_mailbox = std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR);
|
||||||
return found != modes.end() ? *found : VK_PRESENT_MODE_FIFO_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) {
|
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 auto present_modes{physical_device.GetSurfacePresentModesKHR(surface)};
|
||||||
|
|
||||||
const VkSurfaceFormatKHR surface_format{ChooseSwapSurfaceFormat(formats)};
|
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};
|
u32 requested_image_count{capabilities.minImageCount + 1};
|
||||||
if (capabilities.maxImageCount > 0 && requested_image_count > capabilities.maxImageCount) {
|
if (capabilities.maxImageCount > 0 && requested_image_count > capabilities.maxImageCount) {
|
||||||
|
@ -196,6 +208,7 @@ void VKSwapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities,
|
||||||
|
|
||||||
extent = swapchain_ci.imageExtent;
|
extent = swapchain_ci.imageExtent;
|
||||||
current_srgb = srgb;
|
current_srgb = srgb;
|
||||||
|
current_fps_unlocked = Settings::values.disable_fps_limit.GetValue();
|
||||||
|
|
||||||
images = swapchain.GetImages();
|
images = swapchain.GetImages();
|
||||||
image_count = static_cast<u32>(images.size());
|
image_count = static_cast<u32>(images.size());
|
||||||
|
@ -248,4 +261,14 @@ void VKSwapchain::Destroy() {
|
||||||
swapchain.reset();
|
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
|
} // namespace Vulkan
|
||||||
|
|
|
@ -33,6 +33,11 @@ public:
|
||||||
/// Presents the rendered image to the swapchain.
|
/// Presents the rendered image to the swapchain.
|
||||||
void Present(VkSemaphore render_semaphore);
|
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.
|
/// Returns true when the color space has changed.
|
||||||
bool HasColorSpaceChanged(bool is_srgb) const {
|
bool HasColorSpaceChanged(bool is_srgb) const {
|
||||||
return current_srgb != is_srgb;
|
return current_srgb != is_srgb;
|
||||||
|
@ -84,6 +89,10 @@ private:
|
||||||
|
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
|
bool HasFpsUnlockChanged() const;
|
||||||
|
|
||||||
|
bool NeedsPresentModeUpdate() const;
|
||||||
|
|
||||||
const VkSurfaceKHR surface;
|
const VkSurfaceKHR surface;
|
||||||
const Device& device;
|
const Device& device;
|
||||||
VKScheduler& scheduler;
|
VKScheduler& scheduler;
|
||||||
|
@ -102,8 +111,10 @@ private:
|
||||||
|
|
||||||
VkFormat image_view_format{};
|
VkFormat image_view_format{};
|
||||||
VkExtent2D extent{};
|
VkExtent2D extent{};
|
||||||
|
VkPresentModeKHR present_mode{};
|
||||||
|
|
||||||
bool current_srgb{};
|
bool current_srgb{};
|
||||||
|
bool current_fps_unlocked{};
|
||||||
bool is_outdated{};
|
bool is_outdated{};
|
||||||
bool is_suboptimal{};
|
bool is_suboptimal{};
|
||||||
};
|
};
|
||||||
|
|
Reference in New Issue