import std;
import vulkan_raii;
class VulkanLoader {
public:
static bool initialize() {
try {
// First, try to use the system-installed Vulkan loader
if (try_system_loader()) {
std::cout << "Using system-installed Vulkan loader" << std::endl;
return true;
}
// If that fails, try to use the bundled loader
if (try_bundled_loader()) {
std::cout << "Using bundled Vulkan loader" << std::endl;
return true;
}
// If both approaches fail, report an error
std::cerr << "Failed to initialize Vulkan loader" << std::endl;
return false;
} catch (const std::exception& e) {
std::cerr << "Error initializing Vulkan loader: " << e.what() << std::endl;
return false;
}
}
private:
static bool try_system_loader() {
try {
// Create a Vulkan instance to test if the system loader works
vk::raii::Context context;
vk::ApplicationInfo app_info{};
app_info.setApiVersion(VK_API_VERSION_1_2);
vk::InstanceCreateInfo create_info{};
create_info.setPApplicationInfo(&app_info);
vk::raii::Instance instance(context, create_info);
return true;
} catch (...) {
return false;
}
}
static bool try_bundled_loader() {
try {
// Set the path to the bundled Vulkan loader
#if defined(_WIN32)
std::string loader_path = get_executable_path() + "\\vulkan-1.dll";
SetDllDirectoryA(get_executable_path().c_str());
#elif defined(__linux__)
std::string loader_path = get_executable_path() + "/libvulkan.so.1";
setenv("LD_LIBRARY_PATH", get_executable_path().c_str(), 1);
#elif defined(__APPLE__)
std::string loader_path = get_executable_path() + "/../Frameworks/libMoltenVK.dylib";
setenv("DYLD_LIBRARY_PATH", (get_executable_path() + "/../Frameworks").c_str(), 1);
#endif
// Check if the bundled loader exists
if (!std::filesystem::exists(loader_path)) {
return false;
}
// Try to create a Vulkan instance using the bundled loader
vk::raii::Context context;
vk::ApplicationInfo app_info{};
app_info.setApiVersion(VK_API_VERSION_1_2);
vk::InstanceCreateInfo create_info{};
create_info.setPApplicationInfo(&app_info);
vk::raii::Instance instance(context, create_info);
return true;
} catch (...) {
return false;
}
}
static std::string get_executable_path() {
#if defined(_WIN32)
char path[MAX_PATH];
GetModuleFileNameA(NULL, path, MAX_PATH);
std::string exe_path(path);
return exe_path.substr(0, exe_path.find_last_of("\\/"));
#elif defined(__linux__)
char result[PATH_MAX];
ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
std::string exe_path(result, (count > 0) ? count : 0);
return exe_path.substr(0, exe_path.find_last_of("/"));
#elif defined(__APPLE__)
char path[PATH_MAX];
uint32_t size = sizeof(path);
if (_NSGetExecutablePath(path, &size) == 0) {
std::string exe_path(path);
return exe_path.substr(0, exe_path.find_last_of("/"));
}
return "";
#endif
}
};