Browse Source

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 <functional> 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.
pull/234/head
Vladimír Vondruš 6 years ago
parent
commit
21a91e8b0a
  1. 6
      src/MagnumExternal/Vulkan/flextVk.cpp
  2. 16
      src/MagnumExternal/Vulkan/flextVk.cpp.template
  3. 7
      src/MagnumExternal/Vulkan/flextVk.h
  4. 7
      src/MagnumExternal/Vulkan/flextVk.h.template

6
src/MagnumExternal/Vulkan/flextVk.cpp vendored

@ -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<VkResult(VKAPI_PTR*)(uint32_t*)>(vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"));
FlextVkInstance flextVkInstance{};
FlextVkDevice flextVkDevice{};
void flextVkInit() {
flextvkEnumerateInstanceVersion = reinterpret_cast<VkResult(VKAPI_PTR*)(uint32_t*)>(vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"));
}
void flextVkInitInstance(VkInstance instance, FlextVkInstance* data) {
data->EnumeratePhysicalDeviceGroupsKHR = reinterpret_cast<VkResult(VKAPI_PTR*)(VkInstance, uint32_t*, VkPhysicalDeviceGroupProperties*)>(vkGetInstanceProcAddr(instance, "vkEnumeratePhysicalDeviceGroupsKHR"));
data->GetPhysicalDeviceExternalFencePropertiesKHR = reinterpret_cast<void(VKAPI_PTR*)(VkPhysicalDevice, const VkPhysicalDeviceExternalFenceInfo*, VkExternalFenceProperties*)>(vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceExternalFencePropertiesKHR"));

16
src/MagnumExternal/Vulkan/flextVk.cpp.template vendored

@ -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:

7
src/MagnumExternal/Vulkan/flextVk.h vendored

@ -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 {

7
src/MagnumExternal/Vulkan/flextVk.h.template vendored

@ -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:

Loading…
Cancel
Save