From 7e0a72309a1c5ac28dc6d7e4dc78ccd87ca641fd Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Sun, 5 Nov 2023 14:46:03 -0800 Subject: [PATCH] Implement volkFinalize function (#153) This is normally not necessary to call if the instance survives until the application shutdown, but it might be useful in some cases where a clean and complete instance recreation is needed, or if the application wants to tear down the Vulkan instance and then create an OpenGL instance while making sure the Vulkan DLLs are unloaded. --- volk.c | 33 +++++++++++++++++++++++++++++++++ volk.h | 5 +++++ 2 files changed, 38 insertions(+) diff --git a/volk.c b/volk.c index fc89854..cd02e42 100644 --- a/volk.c +++ b/volk.c @@ -24,8 +24,10 @@ extern "C" { #ifdef _WIN32 __declspec(dllimport) HMODULE __stdcall LoadLibraryA(LPCSTR); __declspec(dllimport) FARPROC __stdcall GetProcAddress(HMODULE, LPCSTR); +__declspec(dllimport) int __stdcall FreeLibrary(HMODULE); #endif +static void* loadedModule = NULL; static VkInstance loadedInstance = VK_NULL_HANDLE; static VkDevice loadedDevice = VK_NULL_HANDLE; @@ -44,6 +46,14 @@ static PFN_vkVoidFunction vkGetDeviceProcAddrStub(void* context, const char* nam return vkGetDeviceProcAddr((VkDevice)context, name); } +static PFN_vkVoidFunction nullProcAddrStub(void* context, const char* name) +{ + (void)context; + (void)name; + + return NULL; +} + VkResult volkInitialize(void) { #if defined(_WIN32) @@ -73,6 +83,7 @@ VkResult volkInitialize(void) vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)dlsym(module, "vkGetInstanceProcAddr"); #endif + loadedModule = module; volkGenLoadLoader(NULL, vkGetInstanceProcAddrStub); return VK_SUCCESS; @@ -82,9 +93,31 @@ void volkInitializeCustom(PFN_vkGetInstanceProcAddr handler) { vkGetInstanceProcAddr = handler; + loadedModule = NULL; volkGenLoadLoader(NULL, vkGetInstanceProcAddrStub); } +void volkFinalize(void) +{ + if (loadedModule) + { +#if defined(_WIN32) + FreeLibrary((HMODULE)loadedModule); +#else + dlclose(loadedModule); +#endif + } + + vkGetInstanceProcAddr = NULL; + volkGenLoadLoader(NULL, nullProcAddrStub); + volkGenLoadInstance(NULL, nullProcAddrStub); + volkGenLoadDevice(NULL, nullProcAddrStub); + + loadedModule = NULL; + loadedInstance = VK_NULL_HANDLE; + loadedDevice = VK_NULL_HANDLE; +} + uint32_t volkGetInstanceVersion(void) { #if defined(VK_VERSION_1_1) diff --git a/volk.h b/volk.h index cb1d65f..474bcfa 100644 --- a/volk.h +++ b/volk.h @@ -81,6 +81,11 @@ VkResult volkInitialize(void); */ void volkInitializeCustom(PFN_vkGetInstanceProcAddr handler); +/** + * Finalize library by unloading Vulkan loader and resetting global symbols to NULL. + */ +void volkFinalize(void); + /** * Get Vulkan instance version supported by the Vulkan loader, or 0 if Vulkan isn't supported *