blob: 2876155ca1a3d61bc4caebe853267c2b691c771f [file]
/*
* Copyright (c) 2025-2026 The Khronos Group Inc.
* Copyright (c) 2025-2026 Valve Corporation
* Copyright (c) 2025-2026 LunarG, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Author: Charles Giessen <charles@lunarg.com>
*
*/
#pragma once
// Need to include relevant system headers to open the dynamic library
#if defined(WIN32)
#include <windows.h>
#elif defined(__APPLE__)
#include <stdlib.h>
#include <dlfcn.h>
#else
#include <dlfcn.h>
#endif
// We are providing storage for all functions, make sure the vulkan headers doesn't conflate with ours.
#if !defined(VK_NO_PROTOTYPES)
#define VK_NO_PROTOTYPES
#endif
#include <vulkan/vulkan.h>
void* vulkan_library;
// Global Functions
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties;
PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties;
PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion;
PFN_vkCreateInstance vkCreateInstance;
// Per-platform Instance functions
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR;
#endif
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR;
#endif
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR;
#endif
#if defined(VK_USE_PLATFORM_XLIB_KHR)
PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR;
#endif
#if defined(VK_USE_PLATFORM_XCB_KHR)
PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR;
#endif
#if defined(VK_USE_PLATFORM_METAL_EXT)
PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT;
#endif
#if defined(VK_USE_PLATFORM_MACOS_MVK)
PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK;
#endif
#if defined(VK_USE_PLATFORM_SCREEN_QNX)
PFN_vkCreateScreenSurfaceQNX vkCreateScreenSurfaceQNX;
#endif
#if defined(VK_USE_PLATFORM_DISPLAY)
PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR;
#endif
#if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
PFN_vkCreateDirectFBSurfaceEXT vkCreateDirectFBSurfaceEXT;
#endif
#if defined(VK_USE_PLATFORM_GGP)
PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP;
#endif
// Instance functions
PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
PFN_vkCreateDevice vkCreateDevice;
PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
PFN_vkDestroyInstance vkDestroyInstance;
PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR;
PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties;
PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR;
PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR;
PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR;
PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR;
PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR;
PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures;
PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties;
PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;
PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties;
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;
PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR;
PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR vkGetPhysicalDeviceVideoCapabilitiesKHR;
PFN_vkGetPhysicalDeviceSurfaceFormats2KHR vkGetPhysicalDeviceSurfaceFormats2KHR;
PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR vkGetPhysicalDeviceSurfaceCapabilities2KHR;
PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR vkGetPhysicalDeviceVideoFormatPropertiesKHR;
PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR;
PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR;
PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties;
PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR;
PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR;
PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR vkGetPhysicalDeviceQueueFamilyProperties2KHR;
PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices;
PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT;
PFN_vkGetPhysicalDeviceToolPropertiesEXT vkGetPhysicalDeviceToolPropertiesEXT;
PFN_vkGetPhysicalDeviceFormatProperties2KHR vkGetPhysicalDeviceFormatProperties2KHR;
PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR;
PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsKHR vkGetPhysicalDeviceCalibrateableTimeDomainsKHR;
PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR vkGetPhysicalDeviceFragmentShadingRatesKHR;
PFN_vkGetPhysicalDeviceMultisamplePropertiesEXT vkGetPhysicalDeviceMultisamplePropertiesEXT;
// Device functions
PFN_vkCreateImage vkCreateImage;
PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements;
PFN_vkDestroyImage vkDestroyImage;
PFN_vkDestroyDevice vkDestroyDevice;
#define LOAD_INSTANCE_FUNCTION(instance, function) function = (PFN_##function)vkGetInstanceProcAddr(instance, #function)
static VkResult load_vulkan_library() {
vulkan_library = NULL;
#if defined(WIN32)
HMODULE library = LoadLibraryA("vulkan-1.dll");
if (library == NULL) return VK_ERROR_INITIALIZATION_FAILED;
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)(void (*)(void))GetProcAddress(library, "vkGetInstanceProcAddr");
#elif defined(__APPLE__)
void* library = dlopen("libvulkan.dylib", RTLD_NOW | RTLD_LOCAL);
if (library == NULL) {
library = dlopen("libvulkan.1.dylib", RTLD_NOW | RTLD_LOCAL);
}
if (library == NULL && getenv("DYLD_FALLBACK_LIBRARY_PATH") == NULL) {
library = dlopen("/usr/local/lib/libvulkan.dylib", RTLD_NOW | RTLD_LOCAL);
if (library == NULL) {
library = dlopen("/usr/local/lib/libvulkan.1.dylib", RTLD_NOW | RTLD_LOCAL);
}
}
if (library == NULL) {
return VK_ERROR_INITIALIZATION_FAILED;
}
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)dlsym(library, "vkGetInstanceProcAddr");
#else // Assume everything else supports dlopen
void* library = dlopen("libvulkan.so.1", RTLD_NOW | RTLD_LOCAL);
if (library == NULL) library = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL);
if (library == NULL) {
return VK_ERROR_INITIALIZATION_FAILED;
}
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)dlsym(library, "vkGetInstanceProcAddr");
#endif
if (vkGetInstanceProcAddr == NULL) {
return VK_ERROR_INITIALIZATION_FAILED;
}
vulkan_library = library;
LOAD_INSTANCE_FUNCTION(NULL, vkEnumerateInstanceExtensionProperties);
LOAD_INSTANCE_FUNCTION(NULL, vkEnumerateInstanceLayerProperties);
LOAD_INSTANCE_FUNCTION(NULL, vkEnumerateInstanceVersion);
LOAD_INSTANCE_FUNCTION(NULL, vkCreateInstance);
return VK_SUCCESS;
}
static void unload_vulkan_library() {
if (vulkan_library != NULL) {
#if defined(WIN32)
FreeLibrary((HMODULE)vulkan_library);
#else
dlclose(vulkan_library);
#endif
vulkan_library = NULL;
}
}
static void load_vulkan_instance_functions(VkInstance instance) {
#if defined(VK_USE_PLATFORM_WIN32_KHR)
LOAD_INSTANCE_FUNCTION(instance, vkCreateWin32SurfaceKHR);
#endif
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
LOAD_INSTANCE_FUNCTION(instance, vkCreateWaylandSurfaceKHR);
#endif
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
LOAD_INSTANCE_FUNCTION(instance, vkCreateAndroidSurfaceKHR);
#endif
#if defined(VK_USE_PLATFORM_XLIB_KHR)
LOAD_INSTANCE_FUNCTION(instance, vkCreateXlibSurfaceKHR);
#endif
#if defined(VK_USE_PLATFORM_XCB_KHR)
LOAD_INSTANCE_FUNCTION(instance, vkCreateXcbSurfaceKHR);
#endif
#if defined(VK_USE_PLATFORM_METAL_EXT)
LOAD_INSTANCE_FUNCTION(instance, vkCreateMetalSurfaceEXT);
#endif
#if defined(VK_USE_PLATFORM_MACOS_MVK)
LOAD_INSTANCE_FUNCTION(instance, vkCreateMacOSSurfaceMVK);
#endif
#if defined(VK_USE_PLATFORM_SCREEN_QNX)
LOAD_INSTANCE_FUNCTION(instance, vkCreateScreenSurfaceQNX);
#endif
#if defined(VK_USE_PLATFORM_DISPLAY)
LOAD_INSTANCE_FUNCTION(instance, vkCreateDisplayPlaneSurfaceKHR);
#endif
#if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
LOAD_INSTANCE_FUNCTION(instance, vkCreateDirectFBSurfaceEXT);
#endif
#if defined(VK_USE_PLATFORM_GGP)
LOAD_INSTANCE_FUNCTION(instance, vkCreateStreamDescriptorSurfaceGGP);
#endif
LOAD_INSTANCE_FUNCTION(instance, vkCreateDebugReportCallbackEXT);
LOAD_INSTANCE_FUNCTION(instance, vkCreateDevice);
LOAD_INSTANCE_FUNCTION(instance, vkDestroyDebugReportCallbackEXT);
LOAD_INSTANCE_FUNCTION(instance, vkDestroyInstance);
LOAD_INSTANCE_FUNCTION(instance, vkDestroySurfaceKHR);
LOAD_INSTANCE_FUNCTION(instance, vkEnumerateDeviceExtensionProperties);
LOAD_INSTANCE_FUNCTION(instance, vkGetDisplayModePropertiesKHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetDisplayPlaneCapabilitiesKHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetDisplayPlaneSupportedDisplaysKHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceDisplayPlanePropertiesKHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceDisplayPropertiesKHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceFeatures);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceFormatProperties);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceMemoryProperties);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceProperties);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceQueueFamilyProperties);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceSurfaceFormatsKHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceSurfacePresentModesKHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceSurfaceSupportKHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceVideoCapabilitiesKHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceSurfaceFormats2KHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceSurfaceCapabilities2KHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceVideoFormatPropertiesKHR);
LOAD_INSTANCE_FUNCTION(instance, vkEnumeratePhysicalDeviceGroupsKHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetDeviceGroupPresentCapabilitiesKHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceImageFormatProperties);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceProperties2KHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceMemoryProperties2KHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceFeatures2KHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceQueueFamilyProperties2KHR);
LOAD_INSTANCE_FUNCTION(instance, vkEnumeratePhysicalDevices);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceSurfaceCapabilities2EXT);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceToolPropertiesEXT);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceFormatProperties2KHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceCalibrateableTimeDomainsKHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceFragmentShadingRatesKHR);
LOAD_INSTANCE_FUNCTION(instance, vkGetPhysicalDeviceMultisamplePropertiesEXT);
// Load device functions using vkGetInstanceProcAddr, vulkaninfo doesn't care about the extra indirection it causes
LOAD_INSTANCE_FUNCTION(instance, vkCreateImage);
LOAD_INSTANCE_FUNCTION(instance, vkGetImageMemoryRequirements);
LOAD_INSTANCE_FUNCTION(instance, vkDestroyImage);
LOAD_INSTANCE_FUNCTION(instance, vkDestroyDevice);
}
#undef LOAD_INSTANCE_FUNCTION