set(CMAKE_C_FLAGS_DEBUG " ")
separate_arguments(LOCAL_C_FLAGS_REL WINDOWS_COMMAND ${CMAKE_C_FLAGS_RELEASE})
- add_library(loader-norm OBJECT ${NORMAL_LOADER_SRCS} dirent_on_windows.c)
- add_dependencies(loader-norm generate_helper_files loader_gen_files)
-
- target_compile_options(loader-norm PUBLIC "$<$<CONFIG:DEBUG>:${LOCAL_C_FLAGS_DBG}>")
- add_library(loader-opt OBJECT ${OPT_LOADER_SRCS})
- add_dependencies(loader-opt generate_helper_files loader_gen_files loader_asm_gen_files)
-
- target_compile_options(loader-opt PUBLIC "$<$<CONFIG:DEBUG>:${LOCAL_C_FLAGS_REL}>")
- add_library(${API_LOWERCASE}-${MAJOR} SHARED $<TARGET_OBJECTS:loader-opt> $<TARGET_OBJECTS:loader-norm> ${CMAKE_CURRENT_BINARY_DIR}/${API_LOWERCASE}-${MAJOR}.def ${CMAKE_CURRENT_SOURCE_DIR}/loader.rc)
- add_library(VKstatic.${MAJOR} STATIC $<TARGET_OBJECTS:loader-opt> $<TARGET_OBJECTS:loader-norm>)
+ add_library(loader-norm-dy OBJECT ${NORMAL_LOADER_SRCS} dirent_on_windows.c)
+ add_dependencies(loader-norm-dy generate_helper_files loader_gen_files)
+ target_compile_definitions(loader-norm-dy PUBLIC LOADER_DYNAMIC_LIB)
+ target_compile_options(loader-norm-dy PUBLIC "$<$<CONFIG:DEBUG>:${LOCAL_C_FLAGS_DBG}>")
+
+ add_library(loader-opt-dy OBJECT ${OPT_LOADER_SRCS})
+ add_dependencies(loader-opt-dy generate_helper_files loader_gen_files loader_asm_gen_files)
+ target_compile_definitions(loader-opt-dy PUBLIC LOADER_DYNAMIC_LIB)
+ target_compile_options(loader-opt-dy PUBLIC "$<$<CONFIG:DEBUG>:${LOCAL_C_FLAGS_REL}>")
+
+ add_library(loader-norm-st OBJECT ${NORMAL_LOADER_SRCS} dirent_on_windows.c)
+ add_dependencies(loader-norm-st generate_helper_files loader_gen_files)
+ target_compile_options(loader-norm-st PUBLIC "$<$<CONFIG:DEBUG>:${LOCAL_C_FLAGS_DBG}>")
+
+ add_library(loader-opt-st OBJECT ${OPT_LOADER_SRCS})
+ add_dependencies(loader-opt-st generate_helper_files loader_gen_files loader_asm_gen_files)
+ target_compile_options(loader-opt-st PUBLIC "$<$<CONFIG:DEBUG>:${LOCAL_C_FLAGS_REL}>")
+
+ add_library(${API_LOWERCASE}-${MAJOR} SHARED $<TARGET_OBJECTS:loader-opt-dy> $<TARGET_OBJECTS:loader-norm-dy> ${CMAKE_CURRENT_BINARY_DIR}/${API_LOWERCASE}-${MAJOR}.def ${CMAKE_CURRENT_SOURCE_DIR}/loader.rc)
+ add_library(VKstatic.${MAJOR} STATIC $<TARGET_OBJECTS:loader-opt-st> $<TARGET_OBJECTS:loader-norm-st>)
# Suppress conflicting libs warning for debug builds.
set_target_properties(${API_LOWERCASE}-${MAJOR} PROPERTIES LINK_FLAGS_DEBUG /ignore:4098)
set_target_properties(VKstatic.${MAJOR} PROPERTIES OUTPUT_NAME VKstatic.${MAJOR})
add_library(${API_LOWERCASE} SHARED ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS})
add_dependencies(${API_LOWERCASE} generate_helper_files loader_gen_files loader_asm_gen_files)
+ target_compile_definitions(${API_LOWERCASE} PUBLIC -DLOADER_DYNAMIC_LIB)
set_target_properties(${API_LOWERCASE} PROPERTIES SOVERSION "1" VERSION "1.0.${vk_header_version}")
target_link_libraries(${API_LOWERCASE} -ldl -lpthread -lm)
loader_platform_thread_mutex loader_lock;
loader_platform_thread_mutex loader_json_lock;
+LOADER_PLATFORM_THREAD_ONCE_DECLARATION(once_init);
+
void *loader_instance_heap_alloc(const struct loader_instance *instance, size_t size, VkSystemAllocationScope alloc_scope) {
void *pMemory = NULL;
#if (DEBUG_DISABLE_APP_ALLOCATORS == 1)
struct loader_layer_list instance_layer_list;
tls_instance = NULL;
+ LOADER_PLATFORM_THREAD_ONCE(&once_init, loader_initialize);
+
uint32_t copy_size;
// Get layer libraries
return result;
}
-#if defined(_WIN32)
+#if defined(_WIN32) && defined(LOADER_DYNAMIC_LIB)
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) {
switch (reason) {
case DLL_PROCESS_ATTACH:
}
return TRUE;
}
-#else
+#elif !defined(_WIN32)
__attribute__((constructor)) void loader_init_library() { loader_initialize(); }
__attribute__((destructor)) void loader_free_library() { loader_release(); }
// Global variables used across files
extern struct loader_struct loader;
extern THREAD_LOCAL_DECL struct loader_instance *tls_instance;
+#if defined(_WIN32) && !defined(LOADER_DYNAMIC_LIB)
+extern LOADER_PLATFORM_THREAD_ONCE_DEFINITION(once_init);
+#endif
extern loader_platform_thread_mutex loader_lock;
extern loader_platform_thread_mutex loader_json_lock;
uint32_t *pPropertyCount,
VkExtensionProperties *pProperties) {
tls_instance = NULL;
+ LOADER_PLATFORM_THREAD_ONCE(&once_init, loader_initialize);
// We know we need to call at least the terminator
VkResult res = VK_SUCCESS;
LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
VkLayerProperties *pProperties) {
tls_instance = NULL;
+ LOADER_PLATFORM_THREAD_ONCE(&once_init, loader_initialize);
// We know we need to call at least the terminator
VkResult res = VK_SUCCESS;
bool loaderLocked = false;
VkResult res = VK_ERROR_INITIALIZATION_FAILED;
+ LOADER_PLATFORM_THREAD_ONCE(&once_init, loader_initialize);
+
// Fail if the requested Vulkan apiVersion is > 1.0 since the loader only supports 1.0.
// Having pCreateInfo == NULL, pCreateInfo->pApplication == NULL, or
// pCreateInfo->pApplicationInfo->apiVersion == 0 all indicate that the application is
// Threads:
typedef pthread_t loader_platform_thread;
#define THREAD_LOCAL_DECL __thread
-static inline void loader_platform_thread_once(pthread_once_t *ctl, void (*func)(void)) {
- assert(func != NULL);
- assert(ctl != NULL);
- pthread_once(ctl, func);
-}
+
+// The once init functionality is not used on Linux
+#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var)
+#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var)
+#define LOADER_PLATFORM_THREAD_ONCE(ctl, func)
// Thread IDs:
typedef pthread_t loader_platform_thread_id;
// Threads:
typedef HANDLE loader_platform_thread;
#define THREAD_LOCAL_DECL __declspec(thread)
+
+// The once init functionality is not used when building a DLL on Windows. This is because there is no way to clean up the
+// resources allocated by anything allocated by once init. This isn't a problem for static libraries, but it is for dynamic
+// ones. When building a DLL, we use DllMain() instead to allow properly cleaning up resources.
+#if defined(LOADER_DYNAMIC_LIB)
+#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var)
+#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var)
+#define LOADER_PLATFORM_THREAD_ONCE(ctl, func)
+#else
#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) INIT_ONCE var = INIT_ONCE_STATIC_INIT;
#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) INIT_ONCE var;
+#define LOADER_PLATFORM_THREAD_ONCE(ctl, func) loader_platform_thread_once_fn(ctl, func)
static BOOL CALLBACK InitFuncWrapper(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) {
void (*func)(void) = (void (*)(void))Parameter;
func();
return TRUE;
}
-
-static void loader_platform_thread_once(void *ctl, void (*func)(void)) {
+static void loader_platform_thread_once_fn(void *ctl, void (*func)(void)) {
assert(func != NULL);
assert(ctl != NULL);
InitOnceExecuteOnce((PINIT_ONCE)ctl, InitFuncWrapper, func, NULL);
}
+#endif
// Thread IDs:
typedef DWORD loader_platform_thread_id;