66#include <string.h>
77#include <vulkan/vulkan.h>
88
9+ #ifdef _WIN32
10+ # include <windows.h>
11+ # define SENTRY_LIBRARY_HANDLE HMODULE
12+ # define SENTRY_LOAD_LIBRARY (name ) LoadLibraryA(name)
13+ # define SENTRY_GET_PROC_ADDRESS (handle , name ) GetProcAddress(handle, name)
14+ # define SENTRY_FREE_LIBRARY (handle ) FreeLibrary(handle)
15+ #elif defined(__APPLE__ )
16+ # include <dlfcn.h>
17+ # define SENTRY_LIBRARY_HANDLE void *
18+ # define SENTRY_LOAD_LIBRARY (name ) dlopen(name, RTLD_LAZY)
19+ # define SENTRY_GET_PROC_ADDRESS (handle , name ) dlsym(handle, name)
20+ # define SENTRY_FREE_LIBRARY (handle ) dlclose(handle)
21+ #else
22+ # include <dlfcn.h>
23+ # define SENTRY_LIBRARY_HANDLE void *
24+ # define SENTRY_LOAD_LIBRARY (name ) dlopen(name, RTLD_LAZY)
25+ # define SENTRY_GET_PROC_ADDRESS (handle , name ) dlsym(handle, name)
26+ # define SENTRY_FREE_LIBRARY (handle ) dlclose(handle)
27+ #endif
28+
29+ // Dynamic function pointers
30+ static PFN_vkCreateInstance pfn_vkCreateInstance = NULL ;
31+ static PFN_vkDestroyInstance pfn_vkDestroyInstance = NULL ;
32+ static PFN_vkEnumeratePhysicalDevices pfn_vkEnumeratePhysicalDevices = NULL ;
33+ static PFN_vkGetPhysicalDeviceProperties pfn_vkGetPhysicalDeviceProperties
34+ = NULL ;
35+ static PFN_vkGetPhysicalDeviceMemoryProperties
36+ pfn_vkGetPhysicalDeviceMemoryProperties
37+ = NULL ;
38+
39+ static SENTRY_LIBRARY_HANDLE vulkan_library = NULL ;
40+
41+ static bool
42+ load_vulkan_library (void )
43+ {
44+ if (vulkan_library != NULL ) {
45+ return true;
46+ }
47+
48+ #ifdef _WIN32
49+ vulkan_library = SENTRY_LOAD_LIBRARY ("vulkan-1.dll" );
50+ #elif defined(__APPLE__ )
51+ vulkan_library = SENTRY_LOAD_LIBRARY ("libvulkan.1.dylib" );
52+ if (!vulkan_library ) {
53+ vulkan_library = SENTRY_LOAD_LIBRARY ("libvulkan.dylib" );
54+ }
55+ if (!vulkan_library ) {
56+ vulkan_library
57+ = SENTRY_LOAD_LIBRARY ("/usr/local/lib/libvulkan.1.dylib" );
58+ }
59+ #else
60+ vulkan_library = SENTRY_LOAD_LIBRARY ("libvulkan.so.1" );
61+ if (!vulkan_library ) {
62+ vulkan_library = SENTRY_LOAD_LIBRARY ("libvulkan.so" );
63+ }
64+ #endif
65+
66+ if (!vulkan_library ) {
67+ SENTRY_DEBUG ("Failed to load Vulkan library" );
68+ return false;
69+ }
70+
71+ // Load function pointers
72+ pfn_vkCreateInstance = (PFN_vkCreateInstance )SENTRY_GET_PROC_ADDRESS (
73+ vulkan_library , "vkCreateInstance" );
74+ pfn_vkDestroyInstance = (PFN_vkDestroyInstance )SENTRY_GET_PROC_ADDRESS (
75+ vulkan_library , "vkDestroyInstance" );
76+ pfn_vkEnumeratePhysicalDevices
77+ = (PFN_vkEnumeratePhysicalDevices )SENTRY_GET_PROC_ADDRESS (
78+ vulkan_library , "vkEnumeratePhysicalDevices" );
79+ pfn_vkGetPhysicalDeviceProperties
80+ = (PFN_vkGetPhysicalDeviceProperties )SENTRY_GET_PROC_ADDRESS (
81+ vulkan_library , "vkGetPhysicalDeviceProperties" );
82+ pfn_vkGetPhysicalDeviceMemoryProperties
83+ = (PFN_vkGetPhysicalDeviceMemoryProperties )SENTRY_GET_PROC_ADDRESS (
84+ vulkan_library , "vkGetPhysicalDeviceMemoryProperties" );
85+
86+ if (!pfn_vkCreateInstance || !pfn_vkDestroyInstance
87+ || !pfn_vkEnumeratePhysicalDevices || !pfn_vkGetPhysicalDeviceProperties
88+ || !pfn_vkGetPhysicalDeviceMemoryProperties ) {
89+ SENTRY_DEBUG ("Failed to load required Vulkan functions" );
90+ SENTRY_FREE_LIBRARY (vulkan_library );
91+ vulkan_library = NULL ;
92+ return false;
93+ }
94+
95+ SENTRY_DEBUG ("Successfully loaded Vulkan library and functions" );
96+ return true;
97+ }
98+
99+ static void
100+ unload_vulkan_library (void )
101+ {
102+ if (vulkan_library != NULL ) {
103+ SENTRY_FREE_LIBRARY (vulkan_library );
104+ vulkan_library = NULL ;
105+ pfn_vkCreateInstance = NULL ;
106+ pfn_vkDestroyInstance = NULL ;
107+ pfn_vkEnumeratePhysicalDevices = NULL ;
108+ pfn_vkGetPhysicalDeviceProperties = NULL ;
109+ pfn_vkGetPhysicalDeviceMemoryProperties = NULL ;
110+ }
111+ }
112+
9113static VkInstance
10114create_vulkan_instance (void )
11115{
@@ -22,7 +126,7 @@ create_vulkan_instance(void)
22126 create_info .pApplicationInfo = & app_info ;
23127
24128 VkInstance instance = VK_NULL_HANDLE ;
25- VkResult result = vkCreateInstance (& create_info , NULL , & instance );
129+ VkResult result = pfn_vkCreateInstance (& create_info , NULL , & instance );
26130 if (result != VK_SUCCESS ) {
27131 SENTRY_DEBUGF ("Failed to create Vulkan instance: %d" , result );
28132 return VK_NULL_HANDLE ;
@@ -37,8 +141,8 @@ create_gpu_info_from_device(VkPhysicalDevice device)
37141 VkPhysicalDeviceProperties properties ;
38142 VkPhysicalDeviceMemoryProperties memory_properties ;
39143
40- vkGetPhysicalDeviceProperties (device , & properties );
41- vkGetPhysicalDeviceMemoryProperties (device , & memory_properties );
144+ pfn_vkGetPhysicalDeviceProperties (device , & properties );
145+ pfn_vkGetPhysicalDeviceMemoryProperties (device , & memory_properties );
42146
43147 sentry_gpu_info_t * gpu_info = sentry_malloc (sizeof (sentry_gpu_info_t ));
44148 if (!gpu_info ) {
@@ -75,46 +179,57 @@ create_gpu_info_from_device(VkPhysicalDevice device)
75179sentry_gpu_list_t *
76180sentry__get_gpu_info (void )
77181{
182+ if (!load_vulkan_library ()) {
183+ return NULL ;
184+ }
185+
78186 VkInstance instance = create_vulkan_instance ();
79187 if (instance == VK_NULL_HANDLE ) {
188+ unload_vulkan_library ();
80189 return NULL ;
81190 }
82191
83192 uint32_t device_count = 0 ;
84- VkResult result = vkEnumeratePhysicalDevices (instance , & device_count , NULL );
193+ VkResult result
194+ = pfn_vkEnumeratePhysicalDevices (instance , & device_count , NULL );
85195 if (result != VK_SUCCESS || device_count == 0 ) {
86196 SENTRY_DEBUGF ("Failed to enumerate Vulkan devices: %d" , result );
87- vkDestroyInstance (instance , NULL );
197+ pfn_vkDestroyInstance (instance , NULL );
198+ unload_vulkan_library ();
88199 return NULL ;
89200 }
90201
91202 VkPhysicalDevice * devices
92203 = sentry_malloc (sizeof (VkPhysicalDevice ) * device_count );
93204 if (!devices ) {
94- vkDestroyInstance (instance , NULL );
205+ pfn_vkDestroyInstance (instance , NULL );
206+ unload_vulkan_library ();
95207 return NULL ;
96208 }
97209
98- result = vkEnumeratePhysicalDevices (instance , & device_count , devices );
210+ result = pfn_vkEnumeratePhysicalDevices (instance , & device_count , devices );
99211 if (result != VK_SUCCESS ) {
100212 SENTRY_DEBUGF ("Failed to get Vulkan physical devices: %d" , result );
101213 sentry_free (devices );
102- vkDestroyInstance (instance , NULL );
214+ pfn_vkDestroyInstance (instance , NULL );
215+ unload_vulkan_library ();
103216 return NULL ;
104217 }
105218
106219 sentry_gpu_list_t * gpu_list = sentry_malloc (sizeof (sentry_gpu_list_t ));
107220 if (!gpu_list ) {
108221 sentry_free (devices );
109- vkDestroyInstance (instance , NULL );
222+ pfn_vkDestroyInstance (instance , NULL );
223+ unload_vulkan_library ();
110224 return NULL ;
111225 }
112226
113227 gpu_list -> gpus = sentry_malloc (sizeof (sentry_gpu_info_t * ) * device_count );
114228 if (!gpu_list -> gpus ) {
115229 sentry_free (gpu_list );
116230 sentry_free (devices );
117- vkDestroyInstance (instance , NULL );
231+ pfn_vkDestroyInstance (instance , NULL );
232+ unload_vulkan_library ();
118233 return NULL ;
119234 }
120235
@@ -129,13 +244,17 @@ sentry__get_gpu_info(void)
129244 }
130245
131246 sentry_free (devices );
132- vkDestroyInstance (instance , NULL );
247+ pfn_vkDestroyInstance (instance , NULL );
133248
134249 if (gpu_list -> count == 0 ) {
135250 sentry_free (gpu_list -> gpus );
136251 sentry_free (gpu_list );
252+ unload_vulkan_library ();
137253 return NULL ;
138254 }
139255
256+ // Clean up the dynamically loaded Vulkan library since we're done with it
257+ unload_vulkan_library ();
258+
140259 return gpu_list ;
141260}
0 commit comments