GPUDevice: Unload persistent libraries on shutdown

This commit is contained in:
Stenzek
2025-12-27 23:02:55 +10:00
parent 739b0734bc
commit 213d3efdf7
5 changed files with 37 additions and 37 deletions

View File

@@ -558,6 +558,8 @@ void System::CoreThreadShutdown()
Achievements::Shutdown();
GPUDevice::UnloadDynamicLibraries();
InputManager::CloseSources();
s_state.core_thread_handle = {};

View File

@@ -1394,14 +1394,11 @@ std::unique_ptr<GPUDevice> GPUDevice::CreateDeviceForAPI(RenderAPI api)
namespace dyn_libs {
static void CloseShaderc();
static void CloseSpirvCross();
static void CloseAll();
static std::mutex s_dyn_mutex;
static DynamicLibrary s_shaderc_library;
static DynamicLibrary s_spirv_cross_library;
static bool s_close_registered = false;
shaderc_compiler_t g_shaderc_compiler = nullptr;
// TODO: Merge all of these into a struct?
@@ -1446,17 +1443,17 @@ bool dyn_libs::OpenShaderc(Error* error)
return false;
}
if (!s_close_registered)
{
s_close_registered = true;
std::atexit(&dyn_libs::CloseAll);
}
return true;
}
void dyn_libs::CloseShaderc()
{
if (!s_shaderc_library.IsOpen())
{
DebugAssert(!g_shaderc_compiler);
return;
}
if (g_shaderc_compiler)
{
shaderc_compiler_release(g_shaderc_compiler);
@@ -1501,17 +1498,14 @@ bool dyn_libs::OpenSpirvCross(Error* error)
SPIRV_CROSS_MSL_FUNCTIONS(LOAD_FUNC)
#undef LOAD_FUNC
if (!s_close_registered)
{
s_close_registered = true;
std::atexit(&dyn_libs::CloseAll);
}
return true;
}
void dyn_libs::CloseSpirvCross()
{
if (!s_spirv_cross_library.IsOpen())
return;
#define UNLOAD_FUNC(F) F = nullptr;
SPIRV_CROSS_FUNCTIONS(UNLOAD_FUNC)
SPIRV_CROSS_HLSL_FUNCTIONS(UNLOAD_FUNC)
@@ -1521,12 +1515,6 @@ void dyn_libs::CloseSpirvCross()
s_spirv_cross_library.Close();
}
void dyn_libs::CloseAll()
{
CloseShaderc();
CloseSpirvCross();
}
#undef SPIRV_CROSS_HLSL_FUNCTIONS
#undef SPIRV_CROSS_MSL_FUNCTIONS
#undef SPIRV_CROSS_FUNCTIONS
@@ -2106,3 +2094,15 @@ std::unique_ptr<GPUShader> GPUDevice::TranspileAndCreateShaderFromSource(
return CreateShaderFromSource(stage, target_language, dest_source, entry_point, out_binary, error);
}
void GPUDevice::UnloadDynamicLibraries()
{
Assert(!g_gpu_device);
dyn_libs::CloseSpirvCross();
dyn_libs::CloseShaderc();
#ifdef ENABLE_VULKAN
VulkanLoader::DestroyVulkanInstance();
#endif
}

View File

@@ -868,6 +868,9 @@ public:
ALWAYS_INLINE static Statistics& GetStatistics() { return s_stats; }
static void ResetStatistics();
/// Releases dynamic libraries and other resources used by the GPU device system.
static void UnloadDynamicLibraries();
protected:
virtual bool CreateDeviceAndMainSwapChain(std::string_view adapter, CreateFlags create_flags, const WindowInfo& wi,
GPUVSyncMode vsync_mode, bool allow_present_throttle,

View File

@@ -66,8 +66,6 @@ VKAPI_ATTR static VkBool32 VKAPI_CALL DebugMessengerCallback(VkDebugUtilsMessage
namespace {
struct Locals
{
~Locals();
DynamicLibrary library;
VkInstance instance = VK_NULL_HANDLE;
VkDebugUtilsMessengerEXT debug_messenger_callback = VK_NULL_HANDLE;
@@ -88,20 +86,6 @@ ALIGN_TO_CACHE_LINE static Locals s_locals;
} // namespace VulkanLoader
VulkanLoader::Locals::~Locals()
{
// Called at process shutdown.
if (instance)
LockedDestroyVulkanInstance();
#ifdef ENABLE_SDL
if (library_loaded_from_sdl)
SDL_Vulkan_UnloadLibrary();
#endif
library.Close();
}
bool VulkanLoader::LoadVulkanLibrary(WindowInfoType wtype, Error* error)
{
#ifdef ENABLE_SDL
@@ -655,6 +639,14 @@ void VulkanLoader::ReleaseVulkanInstance()
LockedReleaseVulkanInstance();
}
void VulkanLoader::DestroyVulkanInstance()
{
const std::lock_guard lock(s_locals.mutex);
if (s_locals.instance != VK_NULL_HANDLE)
LockedDestroyVulkanInstance();
UnloadVulkanLibrary();
}
const VulkanLoader::OptionalExtensions& VulkanLoader::GetOptionalExtensions()
{
return s_locals.optional_extensions;

View File

@@ -39,6 +39,9 @@ VkInstance GetVulkanInstance();
/// Releases the shared Vulkan instance.
void ReleaseVulkanInstance();
/// Destroys the instance, if any, and unloads the Vulkan library.
void DestroyVulkanInstance();
/// Returns optional extensions for the current instance.
const OptionalExtensions& GetOptionalExtensions();