Vulkan: Fix crash during shutdown if shaders are still compiling

Make sure the async shader compiler threads are stopped before the shaders are deleted
This commit is contained in:
Exzap 2024-03-11 21:55:58 +01:00
parent 40d1eaeb72
commit 1f9b89116f
2 changed files with 13 additions and 14 deletions

View File

@ -129,19 +129,18 @@ class _ShaderVkThreadPool
public: public:
void StartThreads() void StartThreads()
{ {
if (s_threads.empty()) if (m_threadsActive.exchange(true))
{ return;
// create thread pool // create thread pool
m_shutdownThread.store(false);
const uint32 threadCount = 2; const uint32 threadCount = 2;
for (uint32 i = 0; i < threadCount; ++i) for (uint32 i = 0; i < threadCount; ++i)
s_threads.emplace_back(&_ShaderVkThreadPool::CompilerThreadFunc, this); s_threads.emplace_back(&_ShaderVkThreadPool::CompilerThreadFunc, this);
} }
}
void StopThreads() void StopThreads()
{ {
m_shutdownThread.store(true); if (!m_threadsActive.exchange(false))
return;
for (uint32 i = 0; i < s_threads.size(); ++i) for (uint32 i = 0; i < s_threads.size(); ++i)
s_compilationQueueCount.increment(); s_compilationQueueCount.increment();
for (auto& it : s_threads) for (auto& it : s_threads)
@ -156,7 +155,7 @@ public:
void CompilerThreadFunc() void CompilerThreadFunc()
{ {
while (!m_shutdownThread.load(std::memory_order::relaxed)) while (m_threadsActive.load(std::memory_order::relaxed))
{ {
s_compilationQueueCount.decrementWithWait(); s_compilationQueueCount.decrementWithWait();
s_compilationQueueMutex.lock(); s_compilationQueueMutex.lock();
@ -181,7 +180,7 @@ public:
} }
} }
bool HasThreadsRunning() const { return !m_shutdownThread; } bool HasThreadsRunning() const { return m_threadsActive; }
public: public:
std::vector<std::thread> s_threads; std::vector<std::thread> s_threads;
@ -191,7 +190,7 @@ public:
std::mutex s_compilationQueueMutex; std::mutex s_compilationQueueMutex;
private: private:
std::atomic<bool> m_shutdownThread; std::atomic<bool> m_threadsActive;
}ShaderVkThreadPool; }ShaderVkThreadPool;
RendererShaderVk::RendererShaderVk(ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& glslCode) RendererShaderVk::RendererShaderVk(ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& glslCode)

View File

@ -600,7 +600,7 @@ VulkanRenderer::~VulkanRenderer()
SubmitCommandBuffer(); SubmitCommandBuffer();
WaitDeviceIdle(); WaitDeviceIdle();
WaitCommandBufferFinished(GetCurrentCommandBufferId()); WaitCommandBufferFinished(GetCurrentCommandBufferId());
// shut down compilation threads // make sure compilation threads have been shut down
RendererShaderVk::Shutdown(); RendererShaderVk::Shutdown();
// shut down pipeline save thread // shut down pipeline save thread
m_destructionRequested = true; m_destructionRequested = true;
@ -1558,12 +1558,12 @@ void VulkanRenderer::Shutdown()
Renderer::Shutdown(); Renderer::Shutdown();
SubmitCommandBuffer(); SubmitCommandBuffer();
WaitDeviceIdle(); WaitDeviceIdle();
if (m_imguiRenderPass != VK_NULL_HANDLE) if (m_imguiRenderPass != VK_NULL_HANDLE)
{ {
vkDestroyRenderPass(m_logicalDevice, m_imguiRenderPass, nullptr); vkDestroyRenderPass(m_logicalDevice, m_imguiRenderPass, nullptr);
m_imguiRenderPass = VK_NULL_HANDLE; m_imguiRenderPass = VK_NULL_HANDLE;
} }
RendererShaderVk::Shutdown();
} }
void VulkanRenderer::UnrecoverableError(const char* errMsg) const void VulkanRenderer::UnrecoverableError(const char* errMsg) const