vk_swapchain: Handle outdated swapchains
Fixes pixelated presentation on Intel devices.
This commit is contained in:
parent
562af30181
commit
f45f7b5c2a
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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
|
||||||
|
|
Reference in New Issue