vk_swapchain: Handle outdated swapchains

Fixes pixelated presentation on Intel devices.
This commit is contained in:
ReinUsesLisp 2021-06-03 17:42:24 -03:00 committed by ameerj
parent 562af30181
commit f45f7b5c2a
3 changed files with 34 additions and 17 deletions

View File

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

View File

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

View File

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