Просмотр исходного кода

vk_swapchain: Handle outdated swapchains

Fixes pixelated presentation on Intel devices.
ReinUsesLisp 5 лет назад
Родитель
Сommit
f45f7b5c2a

+ 5 - 6
src/video_core/renderer_vulkan/renderer_vulkan.cpp

@@ -143,18 +143,17 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
         const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout();
         swapchain.Create(layout.width, layout.height, is_srgb);
     };
-    if (swapchain.NeedsRecreate() || swapchain.HasColorSpaceChanged(is_srgb)) {
+    if (swapchain.IsSubOptimal() || swapchain.HasColorSpaceChanged(is_srgb)) {
         recreate_swapchain();
     }
-    bool needs_recreate;
+    bool is_outdated;
     do {
-        needs_recreate = false;
         swapchain.AcquireNextImage();
-        if (swapchain.NeedsRecreate()) {
+        is_outdated = swapchain.IsOutDated();
+        if (is_outdated) {
             recreate_swapchain();
-            needs_recreate = true;
         }
-    } while (needs_recreate);
+    } while (is_outdated);
     if (has_been_recreated) {
         blit_screen.Recreate();
     }

+ 19 - 7
src/video_core/renderer_vulkan/vk_swapchain.cpp

@@ -65,7 +65,8 @@ VKSwapchain::VKSwapchain(VkSurfaceKHR surface_, const Device& device_, VKSchedul
 VKSwapchain::~VKSwapchain() = default;
 
 void VKSwapchain::Create(u32 width, u32 height, bool srgb) {
-    needs_recreate = false;
+    is_outdated = false;
+    is_suboptimal = false;
 
     const auto physical_device = device.GetPhysical();
     const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)};
@@ -85,11 +86,22 @@ void VKSwapchain::Create(u32 width, u32 height, bool srgb) {
 }
 
 void VKSwapchain::AcquireNextImage() {
-    const VkResult result =
-        device.GetLogical().AcquireNextImageKHR(*swapchain, std::numeric_limits<u64>::max(),
-                                                *present_semaphores[frame_index], {}, &image_index);
-    needs_recreate |= result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR;
-
+    const VkResult result = device.GetLogical().AcquireNextImageKHR(
+        *swapchain, std::numeric_limits<u64>::max(), *present_semaphores[frame_index],
+        VK_NULL_HANDLE, &image_index);
+    switch (result) {
+    case VK_SUCCESS:
+        break;
+    case VK_SUBOPTIMAL_KHR:
+        is_suboptimal = true;
+        break;
+    case VK_ERROR_OUT_OF_DATE_KHR:
+        is_outdated = true;
+        break;
+    default:
+        LOG_ERROR(Render_Vulkan, "vkAcquireNextImageKHR returned {}", vk::ToString(result));
+        break;
+    }
     scheduler.Wait(resource_ticks[image_index]);
     resource_ticks[image_index] = scheduler.CurrentTick();
 }
@@ -115,7 +127,7 @@ void VKSwapchain::Present(VkSemaphore render_semaphore) {
         LOG_DEBUG(Render_Vulkan, "Suboptimal swapchain");
         break;
     case VK_ERROR_OUT_OF_DATE_KHR:
-        needs_recreate = true;
+        is_outdated = true;
         break;
     default:
         LOG_CRITICAL(Render_Vulkan, "Failed to present with error {}", vk::ToString(result));

+ 10 - 4
src/video_core/renderer_vulkan/vk_swapchain.h

@@ -38,9 +38,14 @@ public:
         return current_srgb != is_srgb;
     }
 
-    /// Returns true when the image has to be recreated.
-    bool NeedsRecreate() const {
-        return needs_recreate;
+    /// Returns true when the swapchain is outdated.
+    bool IsOutDated() const {
+        return is_outdated;
+    }
+
+    /// Returns true when the swapchain is suboptimal.
+    bool IsSubOptimal() const {
+        return is_suboptimal;
     }
 
     VkExtent2D GetSize() const {
@@ -95,7 +100,8 @@ private:
     VkExtent2D extent{};
 
     bool current_srgb{};
-    bool needs_recreate{};
+    bool is_outdated{};
+    bool is_suboptimal{};
 };
 
 } // namespace Vulkan