summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar lat9nq2023-05-01 20:31:22 -0400
committerGravatar lat9nq2023-05-02 21:52:43 -0400
commit952b2710920fdeef705a357762a7925483d27d20 (patch)
tree91cb395a879e6101b2a4f9c7a556629483afc1f5 /src
parentbootmanager: Remove inaccurate switch (diff)
downloadyuzu-952b2710920fdeef705a357762a7925483d27d20.tar.gz
yuzu-952b2710920fdeef705a357762a7925483d27d20.tar.xz
yuzu-952b2710920fdeef705a357762a7925483d27d20.zip
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.
Diffstat (limited to 'src')
-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 @@
14#include "video_core/renderer_vulkan/vk_swapchain.h" 14#include "video_core/renderer_vulkan/vk_swapchain.h"
15#include "video_core/vulkan_common/vulkan_device.h" 15#include "video_core/vulkan_common/vulkan_device.h"
16#include "video_core/vulkan_common/vulkan_wrapper.h" 16#include "video_core/vulkan_common/vulkan_wrapper.h"
17#include "vulkan/vulkan_core.h"
17 18
18namespace Vulkan { 19namespace Vulkan {
19 20
@@ -33,24 +34,47 @@ VkSurfaceFormatKHR ChooseSwapSurfaceFormat(vk::Span<VkSurfaceFormatKHR> formats)
33 return found != formats.end() ? *found : formats[0]; 34 return found != formats.end() ? *found : formats[0];
34} 35}
35 36
36VkPresentModeKHR ChooseSwapPresentMode(vk::Span<VkPresentModeKHR> modes) { 37static constexpr VkPresentModeKHR ChooseSwapPresentMode(bool has_imm, bool has_mailbox,
37 // Mailbox (triple buffering) doesn't lock the application like FIFO (vsync) 38 bool has_fifo_relaxed) {
39 // Mailbox doesn't lock the application like FIFO (vsync)
38 // FIFO present mode locks the framerate to the monitor's refresh rate 40 // FIFO present mode locks the framerate to the monitor's refresh rate
39 const bool has_mailbox = 41 Settings::VSyncMode setting = [has_imm, has_mailbox]() {
40 std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_MAILBOX_KHR) != modes.end(); 42 // Choose Mailbox or Immediate if unlocked and those modes are supported
41 const bool has_imm = 43 const auto mode = Settings::values.vsync_mode.GetValue();
42 std::find(modes.begin(), modes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR) != modes.end(); 44 if (Settings::values.use_speed_limit.GetValue()) {
43 const Settings::VSyncMode mode = Settings::values.vsync_mode.GetValue(); 45 return mode;
46 }
47 switch (mode) {
48 case Settings::VSyncMode::FIFO:
49 case Settings::VSyncMode::FIFORelaxed:
50 if (has_mailbox) {
51 return Settings::VSyncMode::Mailbox;
52 } else if (has_imm) {
53 return Settings::VSyncMode::Immediate;
54 }
55 [[fallthrough]];
56 default:
57 return mode;
58 }
59 }();
60 if ((setting == Settings::VSyncMode::Mailbox && !has_mailbox) ||
61 (setting == Settings::VSyncMode::Immediate && !has_imm) ||
62 (setting == Settings::VSyncMode::FIFORelaxed && !has_fifo_relaxed)) {
63 setting = Settings::VSyncMode::FIFO;
64 }
44 65
45 if (mode == Settings::VSyncMode::Immediate && has_imm) { 66 switch (setting) {
46 LOG_INFO(Render_Vulkan, "Using swap present mode Immediate"); 67 case Settings::VSyncMode::Immediate:
47 return VK_PRESENT_MODE_IMMEDIATE_KHR; 68 return VK_PRESENT_MODE_IMMEDIATE_KHR;
48 } else if (mode == Settings::VSyncMode::Mailbox && has_mailbox) { 69 case Settings::VSyncMode::Mailbox:
49 LOG_INFO(Render_Vulkan, "Using swap present mode Mailbox");
50 return VK_PRESENT_MODE_MAILBOX_KHR; 70 return VK_PRESENT_MODE_MAILBOX_KHR;
71 case Settings::VSyncMode::FIFO:
72 return VK_PRESENT_MODE_FIFO_KHR;
73 case Settings::VSyncMode::FIFORelaxed:
74 return VK_PRESENT_MODE_FIFO_RELAXED_KHR;
75 default:
76 return VK_PRESENT_MODE_FIFO_KHR;
51 } 77 }
52 LOG_INFO(Render_Vulkan, "Using swap present mode FIFO");
53 return VK_PRESENT_MODE_FIFO_KHR;
54} 78}
55 79
56VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, u32 width, u32 height) { 80VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, u32 width, u32 height) {
@@ -168,11 +192,17 @@ void Swapchain::Present(VkSemaphore render_semaphore) {
168void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bool srgb) { 192void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bool srgb) {
169 const auto physical_device{device.GetPhysical()}; 193 const auto physical_device{device.GetPhysical()};
170 const auto formats{physical_device.GetSurfaceFormatsKHR(surface)}; 194 const auto formats{physical_device.GetSurfaceFormatsKHR(surface)};
171 const auto present_modes{physical_device.GetSurfacePresentModesKHR(surface)}; 195 const auto present_modes = physical_device.GetSurfacePresentModesKHR(surface);
196 has_mailbox = std::find(present_modes.begin(), present_modes.end(),
197 VK_PRESENT_MODE_MAILBOX_KHR) != present_modes.end();
198 has_imm = std::find(present_modes.begin(), present_modes.end(),
199 VK_PRESENT_MODE_IMMEDIATE_KHR) != present_modes.end();
200 has_fifo_relaxed = std::find(present_modes.begin(), present_modes.end(),
201 VK_PRESENT_MODE_FIFO_RELAXED_KHR) != present_modes.end();
172 202
173 const VkCompositeAlphaFlagBitsKHR alpha_flags{ChooseAlphaFlags(capabilities)}; 203 const VkCompositeAlphaFlagBitsKHR alpha_flags{ChooseAlphaFlags(capabilities)};
174 surface_format = ChooseSwapSurfaceFormat(formats); 204 surface_format = ChooseSwapSurfaceFormat(formats);
175 present_mode = ChooseSwapPresentMode(present_modes); 205 present_mode = ChooseSwapPresentMode(has_imm, has_mailbox, has_fifo_relaxed);
176 206
177 u32 requested_image_count{capabilities.minImageCount + 1}; 207 u32 requested_image_count{capabilities.minImageCount + 1};
178 // Ensure Triple buffering if possible. 208 // Ensure Triple buffering if possible.
@@ -233,7 +263,6 @@ void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bo
233 263
234 extent = swapchain_ci.imageExtent; 264 extent = swapchain_ci.imageExtent;
235 current_srgb = srgb; 265 current_srgb = srgb;
236 current_fps_unlocked = !Settings::values.use_speed_limit.GetValue();
237 266
238 images = swapchain.GetImages(); 267 images = swapchain.GetImages();
239 image_count = static_cast<u32>(images.size()); 268 image_count = static_cast<u32>(images.size());
@@ -255,14 +284,9 @@ void Swapchain::Destroy() {
255 swapchain.reset(); 284 swapchain.reset();
256} 285}
257 286
258bool Swapchain::HasFpsUnlockChanged() const {
259 return current_fps_unlocked != !Settings::values.use_speed_limit.GetValue();
260}
261
262bool Swapchain::NeedsPresentModeUpdate() const { 287bool Swapchain::NeedsPresentModeUpdate() const {
263 // Mailbox present mode is the ideal for all scenarios. If it is not available, 288 const auto requested_mode = ChooseSwapPresentMode(has_imm, has_mailbox, has_fifo_relaxed);
264 // A different present mode is needed to support unlocked FPS above the monitor's refresh rate. 289 return present_mode != requested_mode;
265 return present_mode != VK_PRESENT_MODE_MAILBOX_KHR && HasFpsUnlockChanged();
266} 290}
267 291
268} // namespace Vulkan 292} // 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:
116 116
117 void Destroy(); 117 void Destroy();
118 118
119 bool HasFpsUnlockChanged() const;
120
121 bool NeedsPresentModeUpdate() const; 119 bool NeedsPresentModeUpdate() const;
122 120
123 const VkSurfaceKHR surface; 121 const VkSurfaceKHR surface;
@@ -142,9 +140,11 @@ private:
142 VkExtent2D extent{}; 140 VkExtent2D extent{};
143 VkPresentModeKHR present_mode{}; 141 VkPresentModeKHR present_mode{};
144 VkSurfaceFormatKHR surface_format{}; 142 VkSurfaceFormatKHR surface_format{};
143 bool has_imm{false};
144 bool has_mailbox{false};
145 bool has_fifo_relaxed{false};
145 146
146 bool current_srgb{}; 147 bool current_srgb{};
147 bool current_fps_unlocked{};
148 bool is_outdated{}; 148 bool is_outdated{};
149 bool is_suboptimal{}; 149 bool is_suboptimal{};
150}; 150};