From 21a91e8b0ae2e8d85e3cb997326c1b7ce0798baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 19 Jun 2020 23:34:37 +0200 Subject: [PATCH] external: fetch vkEnumerateInstanceVersion() in a static constructor. Version query. Such a simple and obvious thing and because they forgot to add such function to Vulkan 1.0, the only three possible ways to retrieve a version retrieval function are: 1. with a static constructor that could make a library crash even before main() is reached if the driver is *extra* shitty 2. with a init() function that would cause race conditions if ever called from multiple threads (which of course can happen because you need to know instance version in order to use the correct function pointers and route pNext fields) 3. with a init() function that internally uses std::mutexes and std::call_once and and atomics and whatnot and thus takes longer to compile than the rest of the engine Approach 2 chosen originally but the race condition countermeasures turned out to be extra annoying to use, so switched to approach 1 now. --- src/MagnumExternal/Vulkan/flextVk.cpp | 6 +----- src/MagnumExternal/Vulkan/flextVk.cpp.template | 16 ++-------------- src/MagnumExternal/Vulkan/flextVk.h | 7 +++---- src/MagnumExternal/Vulkan/flextVk.h.template | 7 +++---- 4 files changed, 9 insertions(+), 27 deletions(-) diff --git a/src/MagnumExternal/Vulkan/flextVk.cpp b/src/MagnumExternal/Vulkan/flextVk.cpp index 9162a3681..e8ddf1ae5 100644 --- a/src/MagnumExternal/Vulkan/flextVk.cpp +++ b/src/MagnumExternal/Vulkan/flextVk.cpp @@ -26,16 +26,12 @@ #include "flextVk.h" #include "flextVkGlobal.h" -VkResult(VKAPI_PTR *flextvkEnumerateInstanceVersion)(uint32_t*) = nullptr; +VkResult(VKAPI_PTR *flextvkEnumerateInstanceVersion)(uint32_t*) = reinterpret_cast(vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion")); FlextVkInstance flextVkInstance{}; FlextVkDevice flextVkDevice{}; -void flextVkInit() { - flextvkEnumerateInstanceVersion = reinterpret_cast(vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion")); -} - void flextVkInitInstance(VkInstance instance, FlextVkInstance* data) { data->EnumeratePhysicalDeviceGroupsKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceGroupsKHR")); data->GetPhysicalDeviceExternalFencePropertiesKHR = reinterpret_cast(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalFencePropertiesKHR")); diff --git a/src/MagnumExternal/Vulkan/flextVk.cpp.template b/src/MagnumExternal/Vulkan/flextVk.cpp.template index c78e3ae87..686261643 100644 --- a/src/MagnumExternal/Vulkan/flextVk.cpp.template +++ b/src/MagnumExternal/Vulkan/flextVk.cpp.template @@ -32,7 +32,8 @@ @for f in funcs: @if f.name in ['EnumerateInstanceVersion']: @f.returntype\ -(VKAPI_PTR *flextvk@f.name)(@f.param_type_list_string()) = nullptr; +(VKAPI_PTR *flextvk@f.name)(@f.param_type_list_string()) = reinterpret_cast<@f.returntype\ +(VKAPI_PTR*)(@f.param_type_list_string())>(vkGetInstanceProcAddr(nullptr, "vk@f.name")); @end @end @end @@ -42,19 +43,6 @@ FlextVkInstance flextVkInstance{}; FlextVkDevice flextVkDevice{}; -void flextVkInit() { - @for category,funcs in functions: - @if funcs: - @for f in funcs: - @if f.name in ['EnumerateInstanceVersion']: - flextvk@f.name = reinterpret_cast<@f.returntype\ -(VKAPI_PTR*)(@f.param_type_list_string())>(vkGetInstanceProcAddr(nullptr, "vk@f.name")); - @end - @end - @end - @end -} - void flextVkInitInstance(VkInstance instance, FlextVkInstance* data) { @for category,funcs in functions: @if funcs: diff --git a/src/MagnumExternal/Vulkan/flextVk.h b/src/MagnumExternal/Vulkan/flextVk.h index 1b1b44ea6..5d848b853 100644 --- a/src/MagnumExternal/Vulkan/flextVk.h +++ b/src/MagnumExternal/Vulkan/flextVk.h @@ -3994,13 +3994,12 @@ VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t*, VkL VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance, const char*); /* Global function pointers. These are not present in all Vulkan versions, so - they need to be loaded at runtime. */ + they need to be loaded at runtime. To avoid race conditions when calling + an init function manually, the function pointer is fetched in a static + constructor. */ extern FLEXTVK_EXPORT VkResult(VKAPI_PTR *flextvkEnumerateInstanceVersion)(uint32_t*); #define vkEnumerateInstanceVersion flextvkEnumerateInstanceVersion -/* Global function pointer initialization */ -void FLEXTVK_EXPORT flextVkInit(); - /* Per-instance function pointers */ struct FlextVkInstance { diff --git a/src/MagnumExternal/Vulkan/flextVk.h.template b/src/MagnumExternal/Vulkan/flextVk.h.template index 3bd801dfd..b47586404 100644 --- a/src/MagnumExternal/Vulkan/flextVk.h.template +++ b/src/MagnumExternal/Vulkan/flextVk.h.template @@ -107,7 +107,9 @@ VKAPI_ATTR @f.returntype VKAPI_CALL vk@f.name\ @end /* Global function pointers. These are not present in all Vulkan versions, so - they need to be loaded at runtime. */ + they need to be loaded at runtime. To avoid race conditions when calling + an init function manually, the function pointer is fetched in a static + constructor. */ @for cat,funcs in functions: @if funcs: @for f in funcs: @@ -120,9 +122,6 @@ extern FLEXTVK_EXPORT @f.returntype\ @end @end -/* Global function pointer initialization */ -void FLEXTVK_EXPORT flextVkInit(); - /* Per-instance function pointers */ struct FlextVkInstance { @for cat,funcs in functions: