renderer_vulkan: Fix swapchain resizing

This commit is contained in:
GPUCode
2022-10-27 18:13:07 +03:00
parent f9274f8b9a
commit 72f8d520c9
3 changed files with 20 additions and 25 deletions

View File

@ -919,21 +919,18 @@ void RendererVulkan::SwapBuffers() {
PrepareRendertarget();
const auto RecreateSwapchain = [&] {
renderpass_cache.ExitRenderpass();
scheduler.Finish();
const Layout::FramebufferLayout layout = render_window.GetFramebufferLayout();
swapchain.Create(layout.width, layout.height);
};
if (swapchain.NeedsRecreation()) {
RecreateSwapchain();
}
do {
scheduler.WaitWorker();
swapchain.AcquireNextImage();
if (swapchain.NeedsRecreation()) {
RecreateSwapchain();
}
scheduler.WaitWorker();
swapchain.AcquireNextImage();
} while (swapchain.NeedsRecreation());
scheduler.Record([layout](vk::CommandBuffer render_cmdbuf, vk::CommandBuffer) {

View File

@ -19,6 +19,12 @@ Swapchain::Swapchain(const Instance& instance, Scheduler& scheduler, RenderpassC
FindPresentFormat();
SetPresentMode();
renderpass_cache.CreatePresentRenderpass(surface_format.format);
vk::Device device = instance.GetDevice();
for (u32 i = 0; i < PREFERRED_IMAGE_COUNT; i++) {
image_acquired.push_back(device.createSemaphore({}));
present_ready.push_back(device.createSemaphore({}));
}
}
Swapchain::~Swapchain() {
@ -60,13 +66,15 @@ void Swapchain::Create(u32 width, u32 height) {
.pQueueFamilyIndices = queue_family_indices.data(),
.preTransform = transform,
.presentMode = present_mode,
.clipped = true};
.clipped = true,
.oldSwapchain = swapchain};
vk::Device device = instance.GetDevice();
vk::SwapchainKHR new_swapchain = device.createSwapchainKHR(swapchain_info);
device.waitIdle();
Destroy();
swapchain = device.createSwapchainKHR(swapchain_info);
swapchain = new_swapchain;
SetupImages();
resource_ticks.clear();
@ -75,14 +83,11 @@ void Swapchain::Create(u32 width, u32 height) {
MICROPROFILE_DEFINE(Vulkan_Acquire, "Vulkan", "Swapchain Acquire", MP_RGB(185, 66, 245));
void Swapchain::AcquireNextImage() {
if (NeedsRecreation()) [[unlikely]] {
return;
}
MICROPROFILE_SCOPE(Vulkan_Acquire);
vk::Device device = instance.GetDevice();
vk::Result result = device.acquireNextImageKHR(swapchain, UINT64_MAX, image_acquired[frame_index],
VK_NULL_HANDLE, &image_index);
switch (result) {
case vk::Result::eSuccess:
break;
@ -103,10 +108,6 @@ void Swapchain::AcquireNextImage() {
MICROPROFILE_DEFINE(Vulkan_Present, "Vulkan", "Swapchain Present", MP_RGB(66, 185, 245));
void Swapchain::Present() {
if (NeedsRecreation()) [[unlikely]] {
return;
}
scheduler.Record([this, index = image_index](vk::CommandBuffer, vk::CommandBuffer) {
const vk::PresentInfoKHR present_info = {.waitSemaphoreCount = 1,
.pWaitSemaphores = &present_ready[index],
@ -119,7 +120,7 @@ void Swapchain::Present() {
[[maybe_unused]] vk::Result result = present_queue.presentKHR(present_info);
} catch (vk::OutOfDateKHRError& err) {
is_outdated = true;
} catch (vk::SystemError& err) {
} catch (...) {
LOG_CRITICAL(Render_Vulkan, "Swapchain presentation failed");
UNREACHABLE();
}
@ -187,9 +188,10 @@ void Swapchain::SetSurfaceProperties(u32 width, u32 height) {
}
// Select number of images in swap chain, we prefer one buffer in the background to work on
image_count = capabilities.minImageCount + 1;
image_count = PREFERRED_IMAGE_COUNT;
if (capabilities.maxImageCount > 0) {
image_count = std::min(image_count, capabilities.maxImageCount);
image_count = std::clamp(PREFERRED_IMAGE_COUNT, capabilities.minImageCount + 1,
capabilities.maxImageCount);
}
// Prefer identity transform if possible
@ -211,8 +213,6 @@ void Swapchain::Destroy() {
device.destroyFramebuffer(framebuffer);
}
frame_index = 0;
image_acquired.clear();
framebuffers.clear();
image_views.clear();
}
@ -222,9 +222,6 @@ void Swapchain::SetupImages() {
images = device.getSwapchainImagesKHR(swapchain);
for (const vk::Image image : images) {
image_acquired.push_back(device.createSemaphore({}));
present_ready.push_back(device.createSemaphore({}));
const vk::ImageViewCreateInfo view_info = {
.image = image,
.viewType = vk::ImageViewType::e2D,

View File

@ -15,6 +15,7 @@ class Scheduler;
class RenderpassCache;
class Swapchain {
static constexpr u32 PREFERRED_IMAGE_COUNT = 8;
public:
Swapchain(const Instance& instance, Scheduler& scheduler,
RenderpassCache& renderpass_cache);
@ -46,7 +47,7 @@ public:
/// Returns the current framebuffe
[[nodiscard]] vk::Framebuffer GetFramebuffer() const {
return framebuffers[frame_index];
return framebuffers[image_index];
}
/// Returns the swapchain format