From 1523fafce05c4d39400d1c27de6ffd0a9f42cf11 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Fri, 17 Jun 2022 16:17:58 +0200 Subject: [PATCH] vk: fix crash when resizing window in boxart mode --- core/rend/gui.cpp | 6 +++++- core/rend/vulkan/vulkan_context.cpp | 11 ++++++++++- core/rend/vulkan/vulkan_context.h | 1 + core/rend/vulkan/vulkan_driver.h | 22 ++++++++++++++++------ 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/core/rend/gui.cpp b/core/rend/gui.cpp index 75f3a654e..ec3368124 100644 --- a/core/rend/gui.cpp +++ b/core/rend/gui.cpp @@ -2402,7 +2402,11 @@ static void gui_display_content() u8 *imgData = loadImage(art->boxartPath, width, height); if (imgData != nullptr) { - textureId = imguiDriver->updateTexture(art->boxartPath, imgData, width, height); + try { + textureId = imguiDriver->updateTexture(art->boxartPath, imgData, width, height); + } catch (const std::exception&) { + // vulkan can throw during resizing + } free(imgData); } } diff --git a/core/rend/vulkan/vulkan_context.cpp b/core/rend/vulkan/vulkan_context.cpp index 969e7424d..5f664330c 100644 --- a/core/rend/vulkan/vulkan_context.cpp +++ b/core/rend/vulkan/vulkan_context.cpp @@ -278,6 +278,7 @@ bool VulkanContext::InitInstance(const char** extensions, uint32_t extensions_co void VulkanContext::InitImgui() { + imguiDriver.reset(); imguiDriver = std::unique_ptr(new VulkanDriver()); ImGui_ImplVulkan_InitInfo initInfo{}; initInfo.Instance = (VkInstance)*instance; @@ -751,13 +752,21 @@ bool VulkanContext::init() return InitDevice(); } -void VulkanContext::NewFrame() +bool VulkanContext::recreateSwapChainIfNeeded() { if (resized || HasSurfaceDimensionChanged()) { CreateSwapChain(); lastFrameView = vk::ImageView(); + return true; } + else + return false; +} + +void VulkanContext::NewFrame() +{ + recreateSwapChainIfNeeded(); if (!IsValid()) throw InvalidVulkanContext(); device->acquireNextImageKHR(*swapChain, UINT64_MAX, *imageAcquiredSemaphores[currentSemaphore], nullptr, ¤tImage); diff --git a/core/rend/vulkan/vulkan_context.h b/core/rend/vulkan/vulkan_context.h index 4ffde2bfb..cee9b8fd2 100644 --- a/core/rend/vulkan/vulkan_context.h +++ b/core/rend/vulkan/vulkan_context.h @@ -109,6 +109,7 @@ public: vk::SubmitInfo(0, nullptr, nullptr, bufferCount, buffers), fence); } bool hasPerPixel() override { return fragmentStoresAndAtomics; } + bool recreateSwapChainIfNeeded(); #ifdef VK_DEBUG void setObjectName(u64 object, VkDebugReportObjectTypeEXT objectType, const std::string& name) diff --git a/core/rend/vulkan/vulkan_driver.h b/core/rend/vulkan/vulkan_driver.h index 4abb88193..b3774c19b 100644 --- a/core/rend/vulkan/vulkan_driver.h +++ b/core/rend/vulkan/vulkan_driver.h @@ -41,7 +41,11 @@ public: try { bool rendering = context->IsRendering(); if (!rendering) + { + if (context->recreateSwapChainIfNeeded()) + return; context->NewFrame(); + } vk::CommandBuffer vmuCmdBuffer{}; if (!rendering || newFrameStarted) { @@ -50,8 +54,10 @@ public: context->PresentLastFrame(); context->DrawOverlay(settings.display.uiScale, true, false); } - // Record Imgui Draw Data and draw funcs into command buffer - ImGui_ImplVulkan_RenderDrawData(drawData, (VkCommandBuffer)getCommandBuffer()); + if (!justStarted) + // Record Imgui Draw Data and draw funcs into command buffer + ImGui_ImplVulkan_RenderDrawData(drawData, (VkCommandBuffer)getCommandBuffer()); + justStarted = false; if (!rendering || newFrameStarted) context->EndFrame(vmuCmdBuffer); newFrameStarted = false; @@ -60,7 +66,7 @@ public: } void present() override { - getContext()->Present(); + getContext()->Present(); // may destroy this driver } ImTextureID getTexture(const std::string& name) override { @@ -118,15 +124,19 @@ private: vk::CommandBuffer getCommandBuffer() { - if (!getContext()->IsRendering()) + VulkanContext *context = getContext(); + if (!context->IsRendering()) { - getContext()->NewFrame(); + if (context->recreateSwapChainIfNeeded()) + throw InvalidVulkanContext(); + context->NewFrame(); newFrameStarted = true; } - return getContext()->GetCurrentCommandBuffer(); + return context->GetCurrentCommandBuffer(); } std::unordered_map textures; vk::UniqueSampler linearSampler; bool newFrameStarted = false; + bool justStarted = true; };