From 1f9b89116f2bad17f9dbd0017b38e0da181fa4c9 Mon Sep 17 00:00:00 2001 From: Exzap <13877693+Exzap@users.noreply.github.com> Date: Mon, 11 Mar 2024 21:55:58 +0100 Subject: [PATCH] Vulkan: Fix crash during shutdown if shaders are still compiling Make sure the async shader compiler threads are stopped before the shaders are deleted --- .../Renderer/Vulkan/RendererShaderVk.cpp | 23 +++++++++---------- .../Latte/Renderer/Vulkan/VulkanRenderer.cpp | 4 ++-- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp index 970f5517..437ef51d 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.cpp @@ -129,19 +129,18 @@ class _ShaderVkThreadPool public: void StartThreads() { - if (s_threads.empty()) - { - // create thread pool - m_shutdownThread.store(false); - const uint32 threadCount = 2; - for (uint32 i = 0; i < threadCount; ++i) - s_threads.emplace_back(&_ShaderVkThreadPool::CompilerThreadFunc, this); - } + if (m_threadsActive.exchange(true)) + return; + // create thread pool + const uint32 threadCount = 2; + for (uint32 i = 0; i < threadCount; ++i) + s_threads.emplace_back(&_ShaderVkThreadPool::CompilerThreadFunc, this); } void StopThreads() { - m_shutdownThread.store(true); + if (!m_threadsActive.exchange(false)) + return; for (uint32 i = 0; i < s_threads.size(); ++i) s_compilationQueueCount.increment(); for (auto& it : s_threads) @@ -156,7 +155,7 @@ public: void CompilerThreadFunc() { - while (!m_shutdownThread.load(std::memory_order::relaxed)) + while (m_threadsActive.load(std::memory_order::relaxed)) { s_compilationQueueCount.decrementWithWait(); s_compilationQueueMutex.lock(); @@ -181,7 +180,7 @@ public: } } - bool HasThreadsRunning() const { return !m_shutdownThread; } + bool HasThreadsRunning() const { return m_threadsActive; } public: std::vector s_threads; @@ -191,7 +190,7 @@ public: std::mutex s_compilationQueueMutex; private: - std::atomic m_shutdownThread; + std::atomic m_threadsActive; }ShaderVkThreadPool; RendererShaderVk::RendererShaderVk(ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& glslCode) diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp index 5285e4ac..876baa07 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp @@ -600,7 +600,7 @@ VulkanRenderer::~VulkanRenderer() SubmitCommandBuffer(); WaitDeviceIdle(); WaitCommandBufferFinished(GetCurrentCommandBufferId()); - // shut down compilation threads + // make sure compilation threads have been shut down RendererShaderVk::Shutdown(); // shut down pipeline save thread m_destructionRequested = true; @@ -1558,12 +1558,12 @@ void VulkanRenderer::Shutdown() Renderer::Shutdown(); SubmitCommandBuffer(); WaitDeviceIdle(); - if (m_imguiRenderPass != VK_NULL_HANDLE) { vkDestroyRenderPass(m_logicalDevice, m_imguiRenderPass, nullptr); m_imguiRenderPass = VK_NULL_HANDLE; } + RendererShaderVk::Shutdown(); } void VulkanRenderer::UnrecoverableError(const char* errMsg) const