summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.cpp70
-rw-r--r--src/video_core/renderer_vulkan/vk_swapchain.h6
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{};
};