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.
This commit is contained in:
parent
a090a380be
commit
952b271092
2 changed files with 53 additions and 29 deletions
|
@ -14,6 +14,7 @@
|
||||||
#include "video_core/renderer_vulkan/vk_swapchain.h"
|
#include "video_core/renderer_vulkan/vk_swapchain.h"
|
||||||
#include "video_core/vulkan_common/vulkan_device.h"
|
#include "video_core/vulkan_common/vulkan_device.h"
|
||||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
|
#include "vulkan/vulkan_core.h"
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
|
|
||||||
|
@ -33,24 +34,47 @@ VkSurfaceFormatKHR ChooseSwapSurfaceFormat(vk::Span<VkSurfaceFormatKHR> formats)
|
||||||
return found != formats.end() ? *found : formats[0];
|
return found != formats.end() ? *found : formats[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
VkPresentModeKHR ChooseSwapPresentMode(vk::Span<VkPresentModeKHR> modes) {
|
static constexpr VkPresentModeKHR ChooseSwapPresentMode(bool has_imm, bool has_mailbox,
|
||||||
// Mailbox (triple buffering) doesn't lock the application like FIFO (vsync)
|
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
|
// FIFO present mode locks the framerate to the monitor's refresh rate
|
||||||
const bool has_mailbox =
|
Settings::VSyncMode setting = [has_imm, has_mailbox]() {
|
||||||
std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR) != modes.end();
|
// Choose Mailbox or Immediate if unlocked and those modes are supported
|
||||||
const bool has_imm =
|
const auto mode = Settings::values.vsync_mode.GetValue();
|
||||||
std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR) != modes.end();
|
if (Settings::values.use_speed_limit.GetValue()) {
|
||||||
const Settings::VSyncMode mode = Settings::values.vsync_mode.GetValue();
|
return mode;
|
||||||
|
}
|
||||||
if (mode == Settings::VSyncMode::Immediate && has_imm) {
|
switch (mode) {
|
||||||
LOG_INFO(Render_Vulkan, "Using swap present mode Immediate");
|
case Settings::VSyncMode::FIFO:
|
||||||
return VK_PRESENT_MODE_IMMEDIATE_KHR;
|
case Settings::VSyncMode::FIFORelaxed:
|
||||||
} else if (mode == Settings::VSyncMode::Mailbox && has_mailbox) {
|
if (has_mailbox) {
|
||||||
LOG_INFO(Render_Vulkan, "Using swap present mode Mailbox");
|
return Settings::VSyncMode::Mailbox;
|
||||||
return VK_PRESENT_MODE_MAILBOX_KHR;
|
} 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (setting) {
|
||||||
|
case Settings::VSyncMode::Immediate:
|
||||||
|
return VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||||
|
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) {
|
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) {
|
void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bool srgb) {
|
||||||
const auto physical_device{device.GetPhysical()};
|
const auto physical_device{device.GetPhysical()};
|
||||||
const auto formats{physical_device.GetSurfaceFormatsKHR(surface)};
|
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)};
|
const VkCompositeAlphaFlagBitsKHR alpha_flags{ChooseAlphaFlags(capabilities)};
|
||||||
surface_format = ChooseSwapSurfaceFormat(formats);
|
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};
|
u32 requested_image_count{capabilities.minImageCount + 1};
|
||||||
// Ensure Triple buffering if possible.
|
// Ensure Triple buffering if possible.
|
||||||
|
@ -233,7 +263,6 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bo
|
||||||
|
|
||||||
extent = swapchain_ci.imageExtent;
|
extent = swapchain_ci.imageExtent;
|
||||||
current_srgb = srgb;
|
current_srgb = srgb;
|
||||||
current_fps_unlocked = !Settings::values.use_speed_limit.GetValue();
|
|
||||||
|
|
||||||
images = swapchain.GetImages();
|
images = swapchain.GetImages();
|
||||||
image_count = static_cast<u32>(images.size());
|
image_count = static_cast<u32>(images.size());
|
||||||
|
@ -255,14 +284,9 @@ void Swapchain::Destroy() {
|
||||||
swapchain.reset();
|
swapchain.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Swapchain::HasFpsUnlockChanged() const {
|
|
||||||
return current_fps_unlocked != !Settings::values.use_speed_limit.GetValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Swapchain::NeedsPresentModeUpdate() const {
|
bool Swapchain::NeedsPresentModeUpdate() const {
|
||||||
// Mailbox present mode is the ideal for all scenarios. If it is not available,
|
const auto requested_mode = ChooseSwapPresentMode(has_imm, has_mailbox, has_fifo_relaxed);
|
||||||
// A different present mode is needed to support unlocked FPS above the monitor's refresh rate.
|
return present_mode != requested_mode;
|
||||||
return present_mode != VK_PRESENT_MODE_MAILBOX_KHR && HasFpsUnlockChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
|
|
@ -116,8 +116,6 @@ private:
|
||||||
|
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
bool HasFpsUnlockChanged() const;
|
|
||||||
|
|
||||||
bool NeedsPresentModeUpdate() const;
|
bool NeedsPresentModeUpdate() const;
|
||||||
|
|
||||||
const VkSurfaceKHR surface;
|
const VkSurfaceKHR surface;
|
||||||
|
@ -142,9 +140,11 @@ private:
|
||||||
VkExtent2D extent{};
|
VkExtent2D extent{};
|
||||||
VkPresentModeKHR present_mode{};
|
VkPresentModeKHR present_mode{};
|
||||||
VkSurfaceFormatKHR surface_format{};
|
VkSurfaceFormatKHR surface_format{};
|
||||||
|
bool has_imm{false};
|
||||||
|
bool has_mailbox{false};
|
||||||
|
bool has_fifo_relaxed{false};
|
||||||
|
|
||||||
bool current_srgb{};
|
bool current_srgb{};
|
||||||
bool current_fps_unlocked{};
|
|
||||||
bool is_outdated{};
|
bool is_outdated{};
|
||||||
bool is_suboptimal{};
|
bool is_suboptimal{};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue