From 8c2ef035fb69c60de544d27ed769a430681dabfa Mon Sep 17 00:00:00 2001 From: DaeKwang Ryu Date: Wed, 5 Oct 2016 13:50:57 +0900 Subject: [PATCH] dlopen vulkan library To avoid runtime error, Use dlopen. Change-Id: I1b86d52e0948af6c160874fa6155ad048aeb1ff4 --- CMakeLists.txt | 1 - configure | 1 - configure.in | 1 - packaging/SDL2.spec | 4 +-- src/video/SDL_sysvideo.h | 14 +++++++- src/video/SDL_video.c | 9 +++++- src/video/tizen/SDL_tizenvideo.c | 1 + src/video/tizen/SDL_tizenvulkan.c | 61 ++++++++++++++++++++++++++++++++--- src/video/tizen/SDL_tizenvulkan.h | 9 +++++- src/video/wayland/SDL_waylandvideo.c | 1 + src/video/wayland/SDL_waylandvulkan.c | 60 +++++++++++++++++++++++++++++++--- src/video/wayland/SDL_waylandvulkan.h | 9 +++++- src/video/x11/SDL_x11video.c | 1 + src/video/x11/SDL_x11vulkan.c | 60 +++++++++++++++++++++++++++++++--- src/video/x11/SDL_x11vulkan.h | 9 +++++- 15 files changed, 219 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0218ba4..914aabb 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1296,7 +1296,6 @@ elseif(TIZEN) set(SDL_VIDEO_VULKAN 1) set(HAVE_VIDEO_VULKAN TRUE) set(SDL_CFLAGS "${SDL_CFLAGS} -I/usr/include") - list(APPEND SDL_LIBS "-lvulkan") endif() endif() endif() diff --git a/configure b/configure index cf1cdf5..2fd13cf 100755 --- a/configure +++ b/configure @@ -21583,7 +21583,6 @@ $as_echo "$video_vulkan" >&6; } $as_echo "#define SDL_VIDEO_VULKAN 1" >>confdefs.h SUMMARY_video="${SUMMARY_video} vulkan" - EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lvulkan" fi fi } diff --git a/configure.in b/configure.in index 9ef9850..b41befc 100644 --- a/configure.in +++ b/configure.in @@ -2218,7 +2218,6 @@ CheckVulkanTizen() if test x$video_vulkan = xyes; then AC_DEFINE(SDL_VIDEO_VULKAN, 1, [ ]) SUMMARY_video="${SUMMARY_video} vulkan" - EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lvulkan" fi fi } diff --git a/packaging/SDL2.spec b/packaging/SDL2.spec index 54c7d62..764f482 100755 --- a/packaging/SDL2.spec +++ b/packaging/SDL2.spec @@ -42,8 +42,8 @@ BuildRequires: pkgconfig(libdrm) BuildRequires: binutils-devel BuildRequires: which BuildRequires: autoconf -#BuildRequires: Vulkan-LoaderAndValidationLayers -#BuildRequires: Vulkan-LoaderAndValidationLayers-devel +BuildRequires: Vulkan-LoaderAndValidationLayers +BuildRequires: Vulkan-LoaderAndValidationLayers-devel BuildRequires: pkgconfig(ecore) BuildRequires: pkgconfig(ecore-wayland) diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index ad73f70..041cb34 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -344,8 +344,20 @@ struct SDL_VideoDevice /* The function used to dispose of this structure */ void (*free) (_THIS); - SDL_bool (*vulkan_GetInstanceExtensions) (const char* driver, unsigned int* count, char** names); + /* * * */ + /* Data used by the Vulkan drivers */ + struct { + int driver_loaded; + } vk_config; + + SDL_bool (*vulkan_GetInstanceExtensions) (_THIS, const char* driver, unsigned int* count, char** names); SDL_bool (*vulkan_CreateSurface) (_THIS, SDL_Window* window, SDL_vulkanInstance instance, SDL_vulkanSurface* surface); + int (*vulkan_LoadLibrary) (_THIS, const char *path); + +#if SDL_VIDEO_VULKAN + struct SDL_vulkan_Data *vk_data; +#endif + #if __TIZEN__ void (*GetWindowSize) (_THIS, SDL_Window * window, int *w, int *h); #endif diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index bb2819d..c67a5b5 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -519,6 +519,9 @@ SDL_VideoInit(const char *driver_name) _this->current_glwin_tls = SDL_TLSCreate(); _this->current_glctx_tls = SDL_TLSCreate(); + /* Set vk_config to default values */ + _this->vk_config.driver_loaded = 0; + /* Initialize the video subsystem */ if (_this->VideoInit(_this) < 0) { SDL_VideoQuit(); @@ -1369,6 +1372,10 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) SDL_SetError("No Vulkan support in video driver"); return NULL; } + + if (_this->vulkan_LoadLibrary(_this, NULL) < 0) { + return NULL; + } } if ((flags & SDL_WINDOW_OPENGL) && (flags & SDL_WINDOW_VULKAN)) { @@ -3744,7 +3751,7 @@ SDL_Vulkan_GetInstanceExtensions(SDL_Window* window, unsigned int* count, char** return SDL_FALSE; } - return _this->vulkan_GetInstanceExtensions(driver, count, names); + return _this->vulkan_GetInstanceExtensions(_this, driver, count, names); } SDL_bool diff --git a/src/video/tizen/SDL_tizenvideo.c b/src/video/tizen/SDL_tizenvideo.c index e77503b..7e6dd88 100644 --- a/src/video/tizen/SDL_tizenvideo.c +++ b/src/video/tizen/SDL_tizenvideo.c @@ -143,6 +143,7 @@ Tizen_CreateDevice(int devindex) #if SDL_VIDEO_VULKAN device->vulkan_GetInstanceExtensions = Tizen_vulkan_GetInstanceExtensions; device->vulkan_CreateSurface = Tizen_vulkan_CreateSurface; + device->vulkan_LoadLibrary = Tizen_vulkan_LoadLibrary; #endif device->GetWindowSize = Tizen_GetWindowSize; diff --git a/src/video/tizen/SDL_tizenvulkan.c b/src/video/tizen/SDL_tizenvulkan.c index f9e3948..f582f5a 100644 --- a/src/video/tizen/SDL_tizenvulkan.c +++ b/src/video/tizen/SDL_tizenvulkan.c @@ -52,8 +52,17 @@ #include "SDL_tizenvideo.h" #include "SDL_tizenvulkan.h" +#define DEFAULT_VULKAN "libvulkan.so" + +#define LOAD_FUNC(NAME) \ +_this->vk_data->NAME = SDL_LoadFunction(_this->vk_data->vk_dll_handle, #NAME); \ +if (!_this->vk_data->NAME) \ +{ \ + return SDL_SetError("Could not retrieve Vulkan function " #NAME); \ +} + SDL_bool -Tizen_vulkan_GetInstanceExtensions(const char* driver, unsigned int* count, char** names) +Tizen_vulkan_GetInstanceExtensions(_THIS, const char* driver, unsigned int* count, char** names) { uint32_t instance_extension_count = 0; uint32_t enabled_extension_count = 0; @@ -64,7 +73,7 @@ Tizen_vulkan_GetInstanceExtensions(const char* driver, unsigned int* count, char return SDL_FALSE; } - err = vkEnumerateInstanceExtensionProperties(NULL, &instance_extension_count, NULL); + err = _this->vk_data->vkEnumerateInstanceExtensionProperties(NULL, &instance_extension_count, NULL); if (err < 0) { SDL_SetError("Fail to get Instance extension"); return SDL_FALSE; @@ -74,7 +83,7 @@ Tizen_vulkan_GetInstanceExtensions(const char* driver, unsigned int* count, char uint32_t i; VkExtensionProperties *instance_extensions = malloc(sizeof(VkExtensionProperties) * instance_extension_count); - err = vkEnumerateInstanceExtensionProperties( + err = _this->vk_data->vkEnumerateInstanceExtensionProperties( NULL, &instance_extension_count, instance_extensions); for (i = 0; i < instance_extension_count; i++) { if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME,instance_extensions[i].extensionName)) { @@ -119,7 +128,7 @@ Tizen_vulkan_CreateSurface(_THIS, SDL_Window* window, SDL_vulkanInstance instanc createInfo.display = video_data->display; createInfo.surface = wmdata->surface; - ret = vkCreateWaylandSurfaceKHR((VkInstance)instance, &createInfo, NULL, (VkSurfaceKHR*)surface); + ret = _this->vk_data->vkCreateWaylandSurfaceKHR((VkInstance)instance, &createInfo, NULL, (VkSurfaceKHR*)surface); if (ret != VK_SUCCESS) { SDL_SetError("fail to vkCreateWaylandSurfaceKHR : %i", (int)ret); return SDL_FALSE; @@ -133,4 +142,48 @@ Tizen_vulkan_CreateSurface(_THIS, SDL_Window* window, SDL_vulkanInstance instanc } } + +int +Tizen_vulkan_LoadLibrary(_THIS, const char *vk_path) +{ + void *vk_dll_handle = NULL; + char *path = NULL; + + if (_this->vk_config.driver_loaded) { + return 0; + } + + _this->vk_data = (struct SDL_vulkan_Data *) SDL_calloc(1, sizeof(SDL_vulkan_Data)); + if (!_this->vk_data) { + return SDL_OutOfMemory(); + } + + if (!vk_path) { + vk_dll_handle = SDL_LoadObject(vk_path); + } + + if (!vk_dll_handle) { + path = SDL_getenv("SDL_VIDEO_VULKAN_DRIVER"); + + if (!path) { + path = DEFAULT_VULKAN; + } + + vk_dll_handle = SDL_LoadObject(path); + } + + _this->vk_data->vk_dll_handle = vk_dll_handle; + + if (vk_dll_handle == NULL) { + return SDL_SetError("Could not initialize Vulkan library"); + } + + LOAD_FUNC(vkEnumerateInstanceExtensionProperties); + LOAD_FUNC(vkCreateWaylandSurfaceKHR); + + _this->vk_config.driver_loaded = 1; + + return 0; +} + #endif diff --git a/src/video/tizen/SDL_tizenvulkan.h b/src/video/tizen/SDL_tizenvulkan.h index 0fe118b..4710f58 100644 --- a/src/video/tizen/SDL_tizenvulkan.h +++ b/src/video/tizen/SDL_tizenvulkan.h @@ -29,7 +29,14 @@ #include #include "../SDL_sysvideo.h" -extern SDL_bool Tizen_vulkan_GetInstanceExtensions(const char* driver, unsigned int* count, char** names); +typedef struct SDL_vulkan_Data{ + void *vk_dll_handle; + VkResult (VKAPI_PTR *vkEnumerateInstanceExtensionProperties) (const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties); + VkResult (VKAPI_PTR *vkCreateWaylandSurfaceKHR) (VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +} SDL_vulkan_Data; + +extern SDL_bool Tizen_vulkan_GetInstanceExtensions(_THIS, const char* driver, unsigned int* count, char** names); extern SDL_bool Tizen_vulkan_CreateSurface(_THIS, SDL_Window* window, SDL_vulkanInstance instance, SDL_vulkanSurface* surface); +extern int Tizen_vulkan_LoadLibrary(_THIS, const char *vk_path); #endif #endif /* _SDL_tizenvulkan_h */ diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index bcdbbb6..b634867 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -129,6 +129,7 @@ Wayland_CreateDevice(int devindex) #if SDL_VIDEO_VULKAN device->vulkan_GetInstanceExtensions = Wayland_vulkan_GetInstanceExtensions; device->vulkan_CreateSurface = Wayland_vulkan_CreateSurface; + device->vulkan_LoadLibrary = Wayland_vulkan_LoadLibrary; #endif return device; } diff --git a/src/video/wayland/SDL_waylandvulkan.c b/src/video/wayland/SDL_waylandvulkan.c index 28c00e7..00987b3 100644 --- a/src/video/wayland/SDL_waylandvulkan.c +++ b/src/video/wayland/SDL_waylandvulkan.c @@ -28,8 +28,17 @@ #include "SDL_waylandvideo.h" #include "SDL_waylandvulkan.h" +#define DEFAULT_VULKAN "libvulkan.so" + +#define LOAD_FUNC(NAME) \ +_this->vk_data->NAME = SDL_LoadFunction(_this->vk_data->vk_dll_handle, #NAME); \ +if (!_this->vk_data->NAME) \ +{ \ + return SDL_SetError("Could not retrieve Vulkan function " #NAME); \ +} + SDL_bool -Wayland_vulkan_GetInstanceExtensions(const char* driver, unsigned int* count, char** names) +Wayland_vulkan_GetInstanceExtensions(_THIS, const char* driver, unsigned int* count, char** names) { uint32_t instance_extension_count = 0; uint32_t enabled_extension_count = 0; @@ -40,7 +49,7 @@ Wayland_vulkan_GetInstanceExtensions(const char* driver, unsigned int* count, ch return SDL_FALSE; } - err = vkEnumerateInstanceExtensionProperties(NULL, &instance_extension_count, NULL); + err = _this->vk_data->vkEnumerateInstanceExtensionProperties(NULL, &instance_extension_count, NULL); if (err < 0) { SDL_SetError("Fail to get Instance extension"); return SDL_FALSE; @@ -50,7 +59,7 @@ Wayland_vulkan_GetInstanceExtensions(const char* driver, unsigned int* count, ch uint32_t i; VkExtensionProperties *instance_extensions = malloc(sizeof(VkExtensionProperties) * instance_extension_count); - err = vkEnumerateInstanceExtensionProperties( + err = _this->vk_data->vkEnumerateInstanceExtensionProperties( NULL, &instance_extension_count, instance_extensions); for (i = 0; i < instance_extension_count; i++) { if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME,instance_extensions[i].extensionName)) { @@ -94,7 +103,7 @@ Wayland_vulkan_CreateSurface(_THIS, SDL_Window* window, SDL_vulkanInstance insta createInfo.display = video_data->display; createInfo.surface = wmdata->surface; - ret = vkCreateWaylandSurfaceKHR((VkInstance)instance, &createInfo, NULL, (VkSurfaceKHR*)surface); + ret = _this->vk_data->vkCreateWaylandSurfaceKHR((VkInstance)instance, &createInfo, NULL, (VkSurfaceKHR*)surface); if (ret != VK_SUCCESS) { SDL_SetError("fail to vkCreateWaylandSurfaceKHR : %i", (int)ret); return SDL_FALSE; @@ -108,4 +117,47 @@ Wayland_vulkan_CreateSurface(_THIS, SDL_Window* window, SDL_vulkanInstance insta } } +int +Wayland_vulkan_LoadLibrary(_THIS, const char *vk_path) +{ + void *vk_dll_handle = NULL; + char *path = NULL; + + if (_this->vk_config.driver_loaded) { + return 0; + } + + _this->vk_data = (struct SDL_vulkan_Data *) SDL_calloc(1, sizeof(SDL_vulkan_Data)); + if (!_this->vk_data) { + return SDL_OutOfMemory(); + } + + if (!vk_path) { + vk_dll_handle = SDL_LoadObject(vk_path); + } + + if (!vk_dll_handle) { + path = SDL_getenv("SDL_VIDEO_VULKAN_DRIVER"); + + if (!path) { + path = DEFAULT_VULKAN; + } + + vk_dll_handle = SDL_LoadObject(path); + } + + _this->vk_data->vk_dll_handle = vk_dll_handle; + + if (vk_dll_handle == NULL) { + return SDL_SetError("Could not initialize Vulkan library"); + } + + LOAD_FUNC(vkEnumerateInstanceExtensionProperties); + LOAD_FUNC(vkCreateWaylandSurfaceKHR); + + _this->vk_config.driver_loaded = 1; + + return 0; +} + #endif diff --git a/src/video/wayland/SDL_waylandvulkan.h b/src/video/wayland/SDL_waylandvulkan.h index f972d70..94068f5 100644 --- a/src/video/wayland/SDL_waylandvulkan.h +++ b/src/video/wayland/SDL_waylandvulkan.h @@ -28,8 +28,15 @@ #include #include "../SDL_sysvideo.h" -extern SDL_bool Wayland_vulkan_GetInstanceExtensions(const char* driver, unsigned int* count, char** names); +typedef struct SDL_vulkan_Data{ + void *vk_dll_handle; + VkResult (VKAPI_PTR *vkEnumerateInstanceExtensionProperties) (const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties); + VkResult (VKAPI_PTR *vkCreateWaylandSurfaceKHR) (VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +} SDL_vulkan_Data; + +extern SDL_bool Wayland_vulkan_GetInstanceExtensions(_THIS, const char* driver, unsigned int* count, char** names); extern SDL_bool Wayland_vulkan_CreateSurface(_THIS, SDL_Window* window, SDL_vulkanInstance instance, SDL_vulkanSurface* surface); +extern int Wayland_vulkan_LoadLibrary(_THIS, const char *vk_path); #endif #endif /* _SDL_waylandvulkan_h */ diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index b3a1c4e..d156efe 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -284,6 +284,7 @@ X11_CreateDevice(int devindex) #if SDL_VIDEO_VULKAN device->vulkan_GetInstanceExtensions = X11_vulkan_GetInstanceExtensions; device->vulkan_CreateSurface = X11_vulkan_CreateSurface; + device->vulkan_LoadLibrary = X11_vulkan_LoadLibrary; #endif return device; diff --git a/src/video/x11/SDL_x11vulkan.c b/src/video/x11/SDL_x11vulkan.c index b4e7ac4..0363a1e 100644 --- a/src/video/x11/SDL_x11vulkan.c +++ b/src/video/x11/SDL_x11vulkan.c @@ -30,8 +30,17 @@ #include "SDL_x11video.h" #include "SDL_x11vulkan.h" +#define DEFAULT_VULKAN "libvulkan.so" + +#define LOAD_FUNC(NAME) \ +_this->vk_data->NAME = SDL_LoadFunction(_this->vk_data->vk_dll_handle, #NAME); \ +if (!_this->vk_data->NAME) \ +{ \ + return SDL_SetError("Could not retrieve Vulkan function " #NAME); \ +} + SDL_bool -X11_vulkan_GetInstanceExtensions(const char* driver, unsigned int* count, char** names) +X11_vulkan_GetInstanceExtensions(_THIS, const char* driver, unsigned int* count, char** names) { uint32_t instance_extension_count = 0; uint32_t enabled_extension_count = 0; @@ -44,7 +53,7 @@ X11_vulkan_GetInstanceExtensions(const char* driver, unsigned int* count, char** return SDL_FALSE; } - err = vkEnumerateInstanceExtensionProperties(NULL, &instance_extension_count, NULL); + err = _this->vkEnumerateInstanceExtensionProperties(NULL, &instance_extension_count, NULL); if (err < 0) { SDL_SetError("Fail to get Instance extension"); return SDL_FALSE; @@ -54,7 +63,7 @@ X11_vulkan_GetInstanceExtensions(const char* driver, unsigned int* count, char** uint32_t i; VkExtensionProperties *instance_extensions = malloc(sizeof(VkExtensionProperties) * instance_extension_count); - err = vkEnumerateInstanceExtensionProperties( + err = _this->vkEnumerateInstanceExtensionProperties( NULL, &instance_extension_count, instance_extensions); for (i = 0; i < instance_extension_count; i++) { if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME,instance_extensions[i].extensionName)) { @@ -96,7 +105,7 @@ X11_vulkan_CreateSurface(_THIS, SDL_Window* window, SDL_vulkanInstance instance, createInfo.connection = XGetXCBConnection(wminfo.info.x11.display); createInfo.window = wminfo.info.x11.window; - ret = vkCreateXcbSurfaceKHR((VkInstance)instance, &createInfo, NULL, (VkSurfaceKHR*)surface); + ret = _this->vkCreateXcbSurfaceKHR((VkInstance)instance, &createInfo, NULL, (VkSurfaceKHR*)surface); if (ret != VK_SUCCESS) { SDL_SetError("fail to vkCreateXcbSurfaceKHR : %i", (int)ret); return SDL_FALSE; @@ -110,4 +119,47 @@ X11_vulkan_CreateSurface(_THIS, SDL_Window* window, SDL_vulkanInstance instance, } } +int +X11_vulkan_LoadLibrary(_THIS, const char *vk_path) +{ + void *vk_dll_handle = NULL; + char *path = NULL; + + if (_this->vk_config.driver_loaded) { + return 0; + } + + _this->vk_data = (struct SDL_vulkan_Data *) SDL_calloc(1, sizeof(SDL_vulkan_Data)); + if (!_this->vk_data) { + return SDL_OutOfMemory(); + } + + if (!vk_path) { + vk_dll_handle = SDL_LoadObject(vk_path); + } + + if (!vk_dll_handle) { + path = SDL_getenv("SDL_VIDEO_VULKAN_DRIVER"); + + if (!path) { + path = DEFAULT_VULKAN; + } + + vk_dll_handle = SDL_LoadObject(path); + } + + _this->vk_data->vk_dll_handle = vk_dll_handle; + + if (vk_dll_handle == NULL) { + return SDL_SetError("Could not initialize Vulkan library"); + } + + LOAD_FUNC(vkEnumerateInstanceExtensionProperties); + LOAD_FUNC(vkCreateWaylandSurfaceKHR); + + _this->vk_config.driver_loaded = 1; + + return 0; +} + #endif diff --git a/src/video/x11/SDL_x11vulkan.h b/src/video/x11/SDL_x11vulkan.h index 0b65aa3..8d9305f 100644 --- a/src/video/x11/SDL_x11vulkan.h +++ b/src/video/x11/SDL_x11vulkan.h @@ -24,8 +24,15 @@ #define _SDL_x11vulkan_h #if SDL_VIDEO_VULKAN -extern SDL_bool X11_vulkan_GetInstanceExtensions(const char* driver, unsigned int* count, char** names); +typedef struct SDL_vulkan_Data{ + void *vk_dll_handle; + VkResult (VKAPI_PTR *vkEnumerateInstanceExtensionProperties) (const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties); + VkResult (VKAPI_PTR *vkCreateWaylandSurfaceKHR) (VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); +} SDL_vulkan_Data; + +extern SDL_bool X11_vulkan_GetInstanceExtensions(_THIS, const char* driver, unsigned int* count, char** names); extern SDL_bool X11_vulkan_CreateSurface(_THIS, SDL_Window* window,SDL_vulkanInstance instance, SDL_vulkanSurface* surface); +extern int X11_vulkan_LoadLibrary(_THIS, const char *vk_path); #endif #endif /* _SDL_x11vulkan_h */ -- 2.7.4