From 2096e67bf94a22cad7d13b535d1f951d0ba888e5 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Fri, 3 Apr 2026 18:02:24 -0700 Subject: [PATCH] fix(rendering): prevent shutdown crash from deferred cleanup use-after-free MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During shutdown, VkContext::runDeferredCleanup() was executing lambdas that called vkFreeDescriptorSets on descriptor pools already destroyed by Renderer::shutdown(). This corrupted the validation layer's internal state, causing a SIGSEGV during process exit on AMD RADV. Clear the deferred queues without executing them — vkDestroyDevice reclaims all device-child resources anyway. Also guard against the double shutdown() call (explicit + destructor). --- src/rendering/vk_context.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/rendering/vk_context.cpp b/src/rendering/vk_context.cpp index 9c8cf36f..34db4058 100644 --- a/src/rendering/vk_context.cpp +++ b/src/rendering/vk_context.cpp @@ -106,14 +106,20 @@ bool VkContext::initialize(SDL_Window* window) { } void VkContext::shutdown() { + if (!device && !instance) return; // Already shut down or never initialized + LOG_WARNING("VkContext::shutdown - vkDeviceWaitIdle..."); if (device) { vkDeviceWaitIdle(device); } - // With the device idle, it is safe to run any deferred per-frame cleanup. + // Clear deferred cleanup queues WITHOUT executing them. By this point the + // sub-renderers (which own the descriptor pools/buffers these lambdas + // reference) have already been destroyed, so running them would call + // vkFreeDescriptorSets on invalid pools. vkDestroyDevice reclaims all + // device-child resources anyway. for (uint32_t fi = 0; fi < MAX_FRAMES_IN_FLIGHT; fi++) { - runDeferredCleanup(fi); + deferredCleanup_[fi].clear(); } LOG_WARNING("VkContext::shutdown - destroyImGuiResources...");