diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_swapchain.cpp | 70 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_swapchain.h | 6 |
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 | ||
| 18 | namespace Vulkan { | 19 | namespace 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 | ||
| 36 | VkPresentModeKHR ChooseSwapPresentMode(vk::Span<VkPresentModeKHR> modes) { | 37 | static 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 | ||
| 56 | VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, u32 width, u32 height) { | 80 | VkExtent2D ChooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities, u32 width, u32 height) { |
| @@ -168,11 +192,17 @@ void Swapchain::Present(VkSemaphore render_semaphore) { | |||
| 168 | void Swapchain::CreateSwapchain(const VkSurfaceCapabilitiesKHR& capabilities, bool srgb) { | 192 | void 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 | ||
| 258 | bool Swapchain::HasFpsUnlockChanged() const { | ||
| 259 | return current_fps_unlocked != !Settings::values.use_speed_limit.GetValue(); | ||
| 260 | } | ||
| 261 | |||
| 262 | bool Swapchain::NeedsPresentModeUpdate() const { | 287 | bool 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 | }; |