Skip to content

Commit cc5903d

Browse files
committed
Use Vulkan headers, dynamically load
1 parent 10eea34 commit cc5903d

File tree

7 files changed

+144
-23
lines changed

7 files changed

+144
-23
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ jobs:
196196
if: ${{ runner.os == 'Linux' && matrix.os != 'ubuntu-22.04' && !env['TEST_X86'] && !matrix.container }}
197197
run: |
198198
sudo apt update
199-
sudo apt install cmake clang-19 llvm g++-12 valgrind zlib1g-dev libcurl4-openssl-dev
199+
sudo apt install cmake clang-19 llvm g++-12 valgrind zlib1g-dev libcurl4-openssl-dev libvulkan-dev
200200
# Install kcov from source
201201
sudo apt-get install binutils-dev libssl-dev libelf-dev libstdc++-12-dev libdw-dev libiberty-dev
202202
git clone https://github.com/SimonKagstrom/kcov.git

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,6 @@
1414
[submodule "external/benchmark"]
1515
path = external/benchmark
1616
url = https://github.com/google/benchmark.git
17+
[submodule "external/vulkan-headers"]
18+
path = external/vulkan-headers
19+
url = https://github.com/KhronosGroup/Vulkan-Headers.git

CMakeLists.txt

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,10 @@ endif()
101101

102102
option(SENTRY_WITH_GPU_INFO "Build with GPU information gathering support" ${SENTRY_GPU_INFO_DEFAULT})
103103

104-
# Vulkan SDK for GPU info (when enabled)
104+
# GPU info enabled - no longer requires Vulkan SDK (uses headers submodule + dynamic linking)
105105
if(SENTRY_WITH_GPU_INFO)
106-
find_package(Vulkan QUIET)
107-
if(NOT Vulkan_FOUND)
108-
message(WARNING "Vulkan SDK not found, disabling GPU information gathering")
109-
set(SENTRY_WITH_GPU_INFO OFF CACHE BOOL "Build with GPU information gathering support" FORCE)
110-
else()
111-
message(STATUS "Vulkan SDK found: ${Vulkan_LIBRARY}")
112-
endif()
106+
add_subdirectory(external/vulkan-headers)
107+
message(STATUS "GPU information gathering enabled (using vulkan-headers submodule)")
113108
endif()
114109

115110
option(SENTRY_BUILD_TESTS "Build sentry-native tests" "${SENTRY_MAIN_PROJECT}")
@@ -591,9 +586,9 @@ if(NOT XBOX)
591586
endif()
592587
endif()
593588

594-
# handle Vulkan for GPU info
589+
# handle Vulkan headers for GPU info
595590
if(SENTRY_WITH_GPU_INFO)
596-
target_link_libraries(sentry PRIVATE Vulkan::Vulkan)
591+
target_link_libraries(sentry PRIVATE Vulkan::Headers)
597592
endif()
598593

599594
# apply platform libraries to sentry library

external/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,4 @@ target_include_directories(breakpad_client
197197
PUBLIC
198198
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>"
199199
)
200+

external/vulkan-headers

Submodule vulkan-headers added at 2efaa55

src/gpu/sentry_gpu_vulkan.c

Lines changed: 130 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,110 @@
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+
9113
static VkInstance
10114
create_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)
75179
sentry_gpu_list_t *
76180
sentry__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
}

src/gpu/sentry_gpu_vulkan.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ extern "C" {
1313
* sentry__free_gpu_list, or NULL if no GPU information could be obtained.
1414
*/
1515
sentry_gpu_list_t *sentry__get_gpu_info(void);
16-
#endif
16+
1717

1818
#ifdef __cplusplus
1919
}
2020
#endif
21+
22+
#endif

0 commit comments

Comments
 (0)