vulkaninfo: dynamically load vulkan
authorCharles Giessen <charles@lunarg.com>
Wed, 19 Feb 2020 23:58:57 +0000 (16:58 -0700)
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>
Fri, 21 Feb 2020 23:48:11 +0000 (16:48 -0700)
This commit makes it so that vulkaninfo will not statically link to
the vulkan loader dll. This is to satisfy the Microsoft
ApiValidator requirements.

Change-Id: Ibac46dd13df9568e9a97ce1ba4e50613902848a1

.travis.yml
vulkaninfo/vulkaninfo.cpp
vulkaninfo/vulkaninfo.h

index e338b10..757b4f1 100644 (file)
@@ -103,10 +103,9 @@ script:
     if [[ "$VULKAN_BUILD_TARGET" == "LINUX" ]]; then
       # Run vulkaninfo as a test
       cd ${TRAVIS_BUILD_DIR}
-      LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${TRAVIS_BUILD_DIR}/external/Vulkan-Loader/build/install/lib/
       cd build/vulkaninfo
       ldd vulkaninfo
-      VK_ICD_FILENAMES=../icd/VkICD_mock_icd.json ./vulkaninfo
+      LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${TRAVIS_BUILD_DIR}/external/Vulkan-Loader/build/install/lib/ VK_ICD_FILENAMES=../icd/VkICD_mock_icd.json ./vulkaninfo
       cd ${TRAVIS_BUILD_DIR}
     fi
   - |
index a0b843a..4dc1dfe 100644 (file)
@@ -261,7 +261,7 @@ void DumpGroups(Printer &p, AppInstance &inst) {
         int group_id = 0;
         for (auto &group : groups) {
             ObjectWrapper obj(p, "Group " + std::to_string(group_id));
-            auto group_props = GetGroupProps(group);
+            auto group_props = GetGroupProps(inst, group);
             {
                 ObjectWrapper obj(p, "Properties");
                 {
@@ -647,7 +647,7 @@ void GpuDevDump(Printer &p, AppGpu &gpu) {
                     VkFormat fmt = static_cast<VkFormat>(fmt_counter);
 
                     VkFormatProperties props;
-                    vkGetPhysicalDeviceFormatProperties(gpu.phys_device, fmt, &props);
+                    gpu.inst.dll.vkGetPhysicalDeviceFormatProperties(gpu.phys_device, fmt, &props);
 
                     GpuDumpFormatProperty(p, fmt, props);
                 }
@@ -667,7 +667,7 @@ void GpuDevDumpJson(Printer &p, AppGpu &gpu) {
                 VkFormat fmt = static_cast<VkFormat>(fmt_counter);
 
                 VkFormatProperties props;
-                vkGetPhysicalDeviceFormatProperties(gpu.phys_device, fmt, &props);
+                gpu.inst.dll.vkGetPhysicalDeviceFormatProperties(gpu.phys_device, fmt, &props);
 
                 // don't print format properties that are unsupported
                 if ((props.linearTilingFeatures || props.optimalTilingFeatures || props.bufferFeatures) == 0) continue;
index 67fa7fc..ed0ed4e 100644 (file)
 #define strndup(p, n) strdup(p)
 #endif
 
-#ifdef _WIN32
+#if defined(_WIN32)
 #include <fcntl.h>
 #include <io.h>
+#include <windows.h>
 #endif  // _WIN32
 
+#if defined(__linux__) || defined(__APPLE__)
+#include <dlfcn.h>
+#endif
+
 #if defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_XCB_KHR)
 #include <X11/Xutil.h>
 #endif
@@ -230,7 +235,225 @@ auto GetVector(F &&f, Ts &&... ts) -> std::vector<T> {
 }
 
 // ----------- Instance Setup ------- //
+struct VkDll {
+    VkResult Initialize() {
+#if defined(__linux__)
+        library = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL);
+        if (!library) library = dlopen("libvulkan.so.1", RTLD_NOW | RTLD_LOCAL);
+#elif defined(__APPLE__)
+        library = dlopen("libvulkan.dylib", RTLD_NOW | RTLD_LOCAL);
+        if (!library) library = dlopen("libvulkan.1.dylib", RTLD_NOW | RTLD_LOCAL);
+        if (!library) library = dlopen("libMoltenVK.dylib", RTLD_NOW | RTLD_LOCAL);
+#elif defined(_WIN32)
+        library = LoadLibrary(TEXT("vulkan-1.dll"));
+#else
+        assert(false && "unsupported platform");
+#endif
+        if (library == 0) return VK_ERROR_INITIALIZATION_FAILED;
+        return VK_SUCCESS;
+    }
+    void Close() {
+#if defined(__linux__) || defined(__APPLE__)
+        dlclose(library);
+#elif defined(_WIN32)
+        FreeLibrary(library);
+#endif
+        library = 0;
+    }
+    // Function pointers, loaded from the dll
+    PFN_vkCreateInstance vkCreateInstance;
+    PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties;
+    PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties;
+    PFN_vkDestroyInstance vkDestroyInstance;
+    PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices;
+    PFN_vkGetPhysicalDeviceFeatures vkGetPhysicalDeviceFeatures;
+    PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties;
+    PFN_vkGetPhysicalDeviceImageFormatProperties vkGetPhysicalDeviceImageFormatProperties;
+    PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties;
+    PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties;
+    PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties;
+    PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
+    PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
+    PFN_vkCreateDevice vkCreateDevice;
+    PFN_vkDestroyDevice vkDestroyDevice;
+    PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties;
+    PFN_vkGetDeviceQueue vkGetDeviceQueue;
+    PFN_vkCreateImage vkCreateImage;
+    PFN_vkDestroyImage vkDestroyImage;
+    PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;
+    PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements;
+    PFN_vkGetImageSparseMemoryRequirements vkGetImageSparseMemoryRequirements;
+    PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion;
+    PFN_vkEnumeratePhysicalDeviceGroups vkEnumeratePhysicalDeviceGroups;
+    PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2;
+    PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2;
+    PFN_vkGetPhysicalDeviceFormatProperties2 vkGetPhysicalDeviceFormatProperties2;
+    PFN_vkGetPhysicalDeviceQueueFamilyProperties2 vkGetPhysicalDeviceQueueFamilyProperties2;
+    PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2;
+    PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR;
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+    PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR;
+#endif  // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+    PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR;
+#endif  // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+    PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR;
+#endif  // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+    PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR;
+#endif  // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+    PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR;
+#endif  // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+    PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR;
+#endif  // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+    PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR;
+#endif  // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+    PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR;
+#endif  // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+    PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR;
+#endif  // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+    PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK;
+#endif  // VK_USE_PLATFORM_MACOS_MVK
+#ifdef VK_USE_PLATFORM_METAL_EXT
+    PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT;
+#endif  // VK_USE_PLATFORM_METAL_EXT
+    void InitializeDispatchPointers() {
+        Load(vkCreateInstance, "vkCreateInstance");
+        Load(vkDestroyInstance, "vkDestroyInstance");
+        Load(vkEnumeratePhysicalDevices, "vkEnumeratePhysicalDevices");
+        Load(vkGetPhysicalDeviceFeatures, "vkGetPhysicalDeviceFeatures");
+        Load(vkGetPhysicalDeviceFormatProperties, "vkGetPhysicalDeviceFormatProperties");
+        Load(vkGetPhysicalDeviceImageFormatProperties, "vkGetPhysicalDeviceImageFormatProperties");
+        Load(vkGetPhysicalDeviceProperties, "vkGetPhysicalDeviceProperties");
+        Load(vkGetPhysicalDeviceQueueFamilyProperties, "vkGetPhysicalDeviceQueueFamilyProperties");
+        Load(vkGetPhysicalDeviceMemoryProperties, "vkGetPhysicalDeviceMemoryProperties");
+        Load(vkGetInstanceProcAddr, "vkGetInstanceProcAddr");
+        Load(vkGetDeviceProcAddr, "vkGetDeviceProcAddr");
+        Load(vkCreateDevice, "vkCreateDevice");
+        Load(vkDestroyDevice, "vkDestroyDevice");
+        Load(vkEnumerateInstanceExtensionProperties, "vkEnumerateInstanceExtensionProperties");
+        Load(vkEnumerateDeviceExtensionProperties, "vkEnumerateDeviceExtensionProperties");
+        Load(vkEnumerateInstanceLayerProperties, "vkEnumerateInstanceLayerProperties");
+        Load(vkGetDeviceQueue, "vkGetDeviceQueue");
+        Load(vkCreateImage, "vkCreateImage");
+        Load(vkDestroyImage, "vkDestroyImage");
+        Load(vkGetBufferMemoryRequirements, "vkGetBufferMemoryRequirements");
+        Load(vkGetImageMemoryRequirements, "vkGetImageMemoryRequirements");
+        Load(vkGetImageSparseMemoryRequirements, "vkGetImageSparseMemoryRequirements");
+        Load(vkEnumerateInstanceVersion, "vkEnumerateInstanceVersion");
+        Load(vkEnumeratePhysicalDeviceGroups, "vkEnumeratePhysicalDeviceGroups");
+        Load(vkGetPhysicalDeviceFeatures2, "vkGetPhysicalDeviceFeatures2");
+        Load(vkGetPhysicalDeviceProperties2, "vkGetPhysicalDeviceProperties2");
+        Load(vkGetPhysicalDeviceFormatProperties2, "vkGetPhysicalDeviceFormatProperties2");
+        Load(vkGetPhysicalDeviceQueueFamilyProperties2, "vkGetPhysicalDeviceQueueFamilyProperties2");
+        Load(vkGetPhysicalDeviceMemoryProperties2, "vkGetPhysicalDeviceMemoryProperties2");
+        Load(vkDestroySurfaceKHR, "vkDestroySurfaceKHR");
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+        Load(vkCreateXlibSurfaceKHR, "vkCreateXlibSurfaceKHR");
+#endif  // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+        Load(vkGetPhysicalDeviceXlibPresentationSupportKHR, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
+#endif  // VK_USE_PLATFORM_XLIB_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+        Load(vkCreateXcbSurfaceKHR, "vkCreateXcbSurfaceKHR");
+#endif  // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_XCB_KHR
+        Load(vkGetPhysicalDeviceXcbPresentationSupportKHR, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
+#endif  // VK_USE_PLATFORM_XCB_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+        Load(vkCreateWaylandSurfaceKHR, "vkCreateWaylandSurfaceKHR");
+#endif  // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+        Load(vkGetPhysicalDeviceWaylandPresentationSupportKHR, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
+#endif  // VK_USE_PLATFORM_WAYLAND_KHR
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+        Load(vkCreateAndroidSurfaceKHR, "vkCreateAndroidSurfaceKHR");
+#endif  // VK_USE_PLATFORM_ANDROID_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+        Load(vkCreateWin32SurfaceKHR, "vkCreateWin32SurfaceKHR");
+#endif  // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+        Load(vkGetPhysicalDeviceWin32PresentationSupportKHR, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
+#endif  // VK_USE_PLATFORM_WIN32_KHR
+#ifdef VK_USE_PLATFORM_MACOS_MVK
+        Load(vkCreateMacOSSurfaceMVK, "vkCreateMacOSSurfaceMVK");
+#endif  // VK_USE_PLATFORM_MACOS_MVK
+#ifdef VK_USE_PLATFORM_METAL_EXT
+        Load(vkCreateMetalSurfaceEXT, "vkCreateMetalSurfaceEXT");
+#endif  // VK_USE_PLATFORM_METAL_EXT
+    }
 
+   private:
+    template <typename T>
+    void Load(T &func_dest, const char *func_name) {
+#if defined(__linux__) || defined(__APPLE__)
+        func_dest = reinterpret_cast<T>(dlsym(library, func_name));
+#elif defined(_WIN32)
+        func_dest = reinterpret_cast<T>(GetProcAddress(library, func_name));
+#endif
+    }
+#if defined(__linux__) || defined(__APPLE__)
+    void *library;
+#elif defined(_WIN32)
+    HMODULE library;
+#endif
+};
+
+struct ExtensionFunctions {
+    // Extension pointers, loaded after instance is created
+    PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR;
+    PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
+    PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
+    PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;
+    PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR;
+    PFN_vkGetPhysicalDeviceSurfaceFormats2KHR vkGetPhysicalDeviceSurfaceFormats2KHR;
+    PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
+    PFN_vkGetPhysicalDeviceFormatProperties2KHR vkGetPhysicalDeviceFormatProperties2KHR;
+    PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR vkGetPhysicalDeviceQueueFamilyProperties2KHR;
+    PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR;
+    PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR;
+    PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR vkGetPhysicalDeviceSurfaceCapabilities2KHR;
+    PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT;
+    PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR;
+    PFN_vkGetPhysicalDeviceToolPropertiesEXT vkGetPhysicalDeviceToolPropertiesEXT;
+
+    void LoadInstanceExtensionDispatchPointers(PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr, VkInstance instance) {
+        this->instance = instance;
+        this->vkGetInstanceProcAddr = vkGetInstanceProcAddr;
+        Load(vkGetPhysicalDeviceSurfaceSupportKHR, "vkGetPhysicalDeviceSurfaceSupportKHR");
+        Load(vkGetPhysicalDeviceSurfaceCapabilitiesKHR, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR");
+        Load(vkGetPhysicalDeviceSurfaceFormatsKHR, "vkGetPhysicalDeviceSurfaceFormatsKHR");
+        Load(vkGetPhysicalDeviceSurfaceFormats2KHR, "vkGetPhysicalDeviceSurfaceFormats2KHR");
+        Load(vkGetPhysicalDeviceSurfacePresentModesKHR, "vkGetPhysicalDeviceSurfacePresentModesKHR");
+        Load(vkGetDeviceGroupPresentCapabilitiesKHR, "vkGetDeviceGroupPresentCapabilitiesKHR");
+        Load(vkGetPhysicalDeviceProperties2KHR, "vkGetPhysicalDeviceProperties2KHR");
+        Load(vkGetPhysicalDeviceFormatProperties2KHR, "vkGetPhysicalDeviceFormatProperties2KHR");
+        Load(vkGetPhysicalDeviceQueueFamilyProperties2KHR, "vkGetPhysicalDeviceQueueFamilyProperties2KHR");
+        Load(vkGetPhysicalDeviceFeatures2KHR, "vkGetPhysicalDeviceFeatures2KHR");
+        Load(vkGetPhysicalDeviceMemoryProperties2KHR, "vkGetPhysicalDeviceMemoryProperties2KHR");
+        Load(vkGetPhysicalDeviceSurfaceCapabilities2KHR, "vkGetPhysicalDeviceSurfaceCapabilities2KHR");
+        Load(vkGetPhysicalDeviceSurfaceCapabilities2EXT, "vkGetPhysicalDeviceSurfaceCapabilities2EXT");
+        Load(vkEnumeratePhysicalDeviceGroupsKHR, "vkEnumeratePhysicalDeviceGroupsKHR");
+        Load(vkGetPhysicalDeviceToolPropertiesEXT, "vkGetPhysicalDeviceToolPropertiesEXT");
+    }
+
+   private:
+    PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
+    VkInstance instance;
+    template <typename T>
+    void Load(T &dest, const char *name) {
+        dest = reinterpret_cast<T>(vkGetInstanceProcAddr(instance, name));
+    }
+};
 struct VkStructureHeader {
     VkStructureType sType;
     VkStructureHeader *pNext;
@@ -295,31 +518,20 @@ struct VulkanVersion {
 };
 
 struct AppInstance {
+    VkDll dll;
+
     VkInstance instance;
     uint32_t instance_version;
     VulkanVersion vk_version;
 
+    ExtensionFunctions ext_funcs;
+
     std::vector<LayerExtensionList> global_layers;
 
     std::vector<VkExtensionProperties> global_extensions;  // Instance Extensions
 
     std::vector<std::string> inst_extensions;
 
-    // Functions from vkGetInstanceProcAddress
-    PFN_vkGetPhysicalDeviceSurfaceSupportKHR vkGetPhysicalDeviceSurfaceSupportKHR;
-    PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
-    PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
-    PFN_vkGetPhysicalDeviceSurfaceFormats2KHR vkGetPhysicalDeviceSurfaceFormats2KHR;
-    PFN_vkGetPhysicalDeviceSurfacePresentModesKHR vkGetPhysicalDeviceSurfacePresentModesKHR;
-    PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
-    PFN_vkGetPhysicalDeviceFormatProperties2KHR vkGetPhysicalDeviceFormatProperties2KHR;
-    PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR vkGetPhysicalDeviceQueueFamilyProperties2KHR;
-    PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR;
-    PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR;
-    PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR vkGetPhysicalDeviceSurfaceCapabilities2KHR;
-    PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT;
-    PFN_vkGetPhysicalDeviceToolPropertiesEXT vkGetPhysicalDeviceToolPropertiesEXT;
-
     std::vector<SurfaceExtension> surface_extensions;
 
     int width = 256, height = 256;
@@ -353,13 +565,17 @@ struct AppInstance {
     ANativeWindow *window;
 #endif
     AppInstance() {
-        PFN_vkEnumerateInstanceVersion enumerate_instance_version =
-            reinterpret_cast<PFN_vkEnumerateInstanceVersion>(vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"));
+        if (dll.Initialize() != VK_SUCCESS) {
+            std::cerr << "Failed to initialize: Vulkan loader is not installed, not found, or failed to load.\n";
+            WAIT_FOR_CONSOLE_DESTROY;
+            exit(1);
+        }
+        dll.InitializeDispatchPointers();
 
-        if (!enumerate_instance_version) {
+        if (!dll.vkEnumerateInstanceVersion) {
             instance_version = VK_API_VERSION_1_0;
         } else {
-            const VkResult err = enumerate_instance_version(&instance_version);
+            const VkResult err = dll.vkEnumerateInstanceVersion(&instance_version);
             if (err) ERR_EXIT(err);
         }
 
@@ -385,7 +601,7 @@ struct AppInstance {
         const VkInstanceCreateInfo inst_info = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,  &dbg_info,       0, &app_info, 0, nullptr,
                                                 static_cast<uint32_t>(inst_exts.size()), inst_exts.data()};
 
-        VkResult err = vkCreateInstance(&inst_info, nullptr, &instance);
+        VkResult err = dll.vkCreateInstance(&inst_info, nullptr, &instance);
         if (err == VK_ERROR_INCOMPATIBLE_DRIVER) {
             std::cerr << "Cannot create Vulkan instance.\n";
             std::cerr << "This problem is often caused by a faulty installation of the Vulkan driver or attempting to use a GPU "
@@ -394,11 +610,13 @@ struct AppInstance {
         } else if (err) {
             ERR_EXIT(err);
         }
-
-        AppLoadInstanceCommands();
+        ext_funcs.LoadInstanceExtensionDispatchPointers(dll.vkGetInstanceProcAddr, instance);
     }
 
-    ~AppInstance() { vkDestroyInstance(instance, nullptr); }
+    ~AppInstance() {
+        if (dll.vkDestroyInstance) dll.vkDestroyInstance(instance, nullptr);
+        dll.Close();
+    }
 
     AppInstance(const AppInstance &) = delete;
     const AppInstance &operator=(const AppInstance &) = delete;
@@ -415,7 +633,7 @@ struct AppInstance {
     /* Gets a list of layer and instance extensions */
     void AppGetInstanceExtensions() {
         /* Scan layers */
-        auto global_layer_properties = GetVector<VkLayerProperties>(vkEnumerateInstanceLayerProperties);
+        auto global_layer_properties = GetVector<VkLayerProperties>(dll.vkEnumerateInstanceLayerProperties);
         global_layers.resize(global_layer_properties.size());
 
         for (size_t i = 0; i < global_layer_properties.size(); i++) {
@@ -434,34 +652,15 @@ struct AppInstance {
             inst_extensions.push_back(ext.extensionName);
         }
     }
-    void AppLoadInstanceCommands() {
-#define LOAD_INSTANCE_VK_CMD(cmd) cmd = reinterpret_cast<PFN_##cmd>(vkGetInstanceProcAddr(instance, #cmd))
-
-        LOAD_INSTANCE_VK_CMD(vkGetPhysicalDeviceSurfaceSupportKHR);
-        LOAD_INSTANCE_VK_CMD(vkGetPhysicalDeviceSurfaceCapabilitiesKHR);
-        LOAD_INSTANCE_VK_CMD(vkGetPhysicalDeviceSurfaceFormatsKHR);
-        LOAD_INSTANCE_VK_CMD(vkGetPhysicalDeviceSurfaceFormats2KHR);
-        LOAD_INSTANCE_VK_CMD(vkGetPhysicalDeviceSurfacePresentModesKHR);
-        LOAD_INSTANCE_VK_CMD(vkGetPhysicalDeviceProperties2KHR);
-        LOAD_INSTANCE_VK_CMD(vkGetPhysicalDeviceFormatProperties2KHR);
-        LOAD_INSTANCE_VK_CMD(vkGetPhysicalDeviceQueueFamilyProperties2KHR);
-        LOAD_INSTANCE_VK_CMD(vkGetPhysicalDeviceFeatures2KHR);
-        LOAD_INSTANCE_VK_CMD(vkGetPhysicalDeviceMemoryProperties2KHR);
-        LOAD_INSTANCE_VK_CMD(vkGetPhysicalDeviceSurfaceCapabilities2KHR);
-        LOAD_INSTANCE_VK_CMD(vkGetPhysicalDeviceSurfaceCapabilities2EXT);
-        LOAD_INSTANCE_VK_CMD(vkGetPhysicalDeviceToolPropertiesEXT);
-
-#undef LOAD_INSTANCE_VK_CMD
-    }
 
     void AddSurfaceExtension(SurfaceExtension ext) { surface_extensions.push_back(ext); }
 
-    static std::vector<VkExtensionProperties> AppGetGlobalLayerExtensions(char *layer_name) {
-        return GetVector<VkExtensionProperties>(vkEnumerateInstanceExtensionProperties, layer_name);
+    std::vector<VkExtensionProperties> AppGetGlobalLayerExtensions(char *layer_name) {
+        return GetVector<VkExtensionProperties>(dll.vkEnumerateInstanceExtensionProperties, layer_name);
     }
 
     std::vector<VkPhysicalDevice> FindPhysicalDevices() {
-        return GetVector<VkPhysicalDevice>(vkEnumeratePhysicalDevices, instance);
+        return GetVector<VkPhysicalDevice>(dll.vkEnumeratePhysicalDevices, instance);
     }
 };
 
@@ -531,7 +730,7 @@ static VkSurfaceKHR AppCreateWin32Surface(AppInstance &inst) {
     createInfo.hwnd = inst.h_wnd;
 
     VkSurfaceKHR surface;
-    VkResult err = vkCreateWin32SurfaceKHR(inst.instance, &createInfo, nullptr, &surface);
+    VkResult err = inst.dll.vkCreateWin32SurfaceKHR(inst.instance, &createInfo, nullptr, &surface);
     if (err) ERR_EXIT(err);
     return surface;
 }
@@ -544,7 +743,7 @@ static void AppDestroyWin32Window(AppInstance &inst) { CALL_PFN(DestroyWindow)(i
     defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_METAL_EXT) || defined(VK_USE_PLATFORM_WAYLAND_KHR) || \
     defined(VK_USE_PLATFORM_ANDROID_KHR)
 static void AppDestroySurface(AppInstance &inst, VkSurfaceKHR surface) {  // same for all platforms
-    vkDestroySurfaceKHR(inst.instance, surface, nullptr);
+    inst.dll.vkDestroySurfaceKHR(inst.instance, surface, nullptr);
 }
 #endif
 
@@ -599,7 +798,7 @@ static VkSurfaceKHR AppCreateXcbSurface(AppInstance &inst) {
     xcb_createInfo.window = inst.xcb_window;
 
     VkSurfaceKHR surface;
-    VkResult err = vkCreateXcbSurfaceKHR(inst.instance, &xcb_createInfo, nullptr, &surface);
+    VkResult err = inst.dll.vkCreateXcbSurfaceKHR(inst.instance, &xcb_createInfo, nullptr, &surface);
     if (err) ERR_EXIT(err);
     return surface;
 }
@@ -646,7 +845,7 @@ static VkSurfaceKHR AppCreateXlibSurface(AppInstance &inst) {
     createInfo.window = inst.xlib_window;
 
     VkSurfaceKHR surface;
-    VkResult err = vkCreateXlibSurfaceKHR(inst.instance, &createInfo, nullptr, &surface);
+    VkResult err = inst.dll.vkCreateXlibSurfaceKHR(inst.instance, &createInfo, nullptr, &surface);
     if (err) ERR_EXIT(err);
     return surface;
 }
@@ -676,7 +875,7 @@ static VkSurfaceKHR AppCreateMacOSSurface(AppInstance &inst) {
     createInfo.pView = inst.macos_window;
 
     VkSurfaceKHR surface;
-    VkResult err = vkCreateMacOSSurfaceMVK(inst.instance, &createInfo, nullptr, &surface);
+    VkResult err = inst.dll.vkCreateMacOSSurfaceMVK(inst.instance, &createInfo, nullptr, &surface);
     if (err) ERR_EXIT(err);
     return surface;
 }
@@ -703,7 +902,7 @@ static VkSurfaceKHR AppCreateMetalSurface(AppInstance &inst) {
     createInfo.pLayer = static_cast<CAMetalLayer *>(GetCAMetalLayerFromMetalView(inst.metal_window));
 
     VkSurfaceKHR surface;
-    VkResult err = vkCreateMetalSurfaceEXT(inst.instance, &createInfo, nullptr, &surface);
+    VkResult err = inst.dll.vkCreateMetalSurfaceEXT(inst.instance, &createInfo, nullptr, &surface);
     if (err) ERR_EXIT(err);
     return surface;
 }
@@ -742,7 +941,7 @@ static VkSurfaceKHR AppCreateWaylandSurface(AppInstance &inst) {
     createInfo.surface = inst.wayland_surface;
 
     VkSurfaceKHR surface;
-    VkResult err = vkCreateWaylandSurfaceKHR(inst.instance, &createInfo, nullptr, &surface);
+    VkResult err = inst.dll.vkCreateWaylandSurfaceKHR(inst.instance, &createInfo, nullptr, &surface);
     if (err) ERR_EXIT(err);
     return surface;
 }
@@ -761,7 +960,7 @@ static VkSurfaceKHR AppCreateAndroidSurface(AppInstance &inst) {
     createInfo.flags = 0;
     createInfo.window = (struct ANativeWindow *)(inst.window);
 
-    err = vkCreateAndroidSurfaceKHR(inst.inst, &createInfo, NULL, &inst.surface);
+    err = inst.dll.vkCreateAndroidSurfaceKHR(inst.inst, &createInfo, NULL, &inst.surface);
     EXIT_ERR(err);
 }
 static VkSurfaceKHR AppDestroyAndroidSurface(AppInstance &inst) {}
@@ -901,8 +1100,8 @@ class AppSurface {
         : inst(inst),
           phys_device(phys_device),
           surface_extension(surface_extension),
-          surf_present_modes(
-              GetVector<VkPresentModeKHR>(inst.vkGetPhysicalDeviceSurfacePresentModesKHR, phys_device, surface_extension.surface)) {
+          surf_present_modes(GetVector<VkPresentModeKHR>(inst.ext_funcs.vkGetPhysicalDeviceSurfacePresentModesKHR, phys_device,
+                                                         surface_extension.surface)) {
         const VkPhysicalDeviceSurfaceInfo2KHR surface_info2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR, nullptr,
                                                                surface_extension.surface};
 
@@ -910,16 +1109,16 @@ class AppSurface {
             VkSurfaceFormat2KHR init;
             init.sType = VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR;
             init.pNext = nullptr;
-            surf_formats2 =
-                GetVectorInit<VkSurfaceFormat2KHR>(inst.vkGetPhysicalDeviceSurfaceFormats2KHR, init, phys_device, &surface_info2);
+            surf_formats2 = GetVectorInit<VkSurfaceFormat2KHR>(inst.ext_funcs.vkGetPhysicalDeviceSurfaceFormats2KHR, init,
+                                                               phys_device, &surface_info2);
         } else {
-            surf_formats =
-                GetVector<VkSurfaceFormatKHR>(inst.vkGetPhysicalDeviceSurfaceFormatsKHR, phys_device, surface_extension.surface);
+            surf_formats = GetVector<VkSurfaceFormatKHR>(inst.ext_funcs.vkGetPhysicalDeviceSurfaceFormatsKHR, phys_device,
+                                                         surface_extension.surface);
         }
 
         if (inst.CheckExtensionEnabled(VK_KHR_SURFACE_EXTENSION_NAME)) {
-            VkResult err =
-                inst.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_device, surface_extension.surface, &surface_capabilities);
+            VkResult err = inst.ext_funcs.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(phys_device, surface_extension.surface,
+                                                                                    &surface_capabilities);
             if (err) ERR_EXIT(err);
         }
 
@@ -932,15 +1131,16 @@ class AppSurface {
             surface_info.pNext = nullptr;
             surface_info.surface = surface_extension.surface;
 
-            VkResult err = inst.vkGetPhysicalDeviceSurfaceCapabilities2KHR(phys_device, &surface_info, &surface_capabilities2_khr);
+            VkResult err =
+                inst.ext_funcs.vkGetPhysicalDeviceSurfaceCapabilities2KHR(phys_device, &surface_info, &surface_capabilities2_khr);
             if (err) ERR_EXIT(err);
         }
 
         if (inst.CheckExtensionEnabled(VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME)) {
             surface_capabilities2_ext.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT;
             surface_capabilities2_ext.pNext = nullptr;
-            VkResult err =
-                inst.vkGetPhysicalDeviceSurfaceCapabilities2EXT(phys_device, surface_extension.surface, &surface_capabilities2_ext);
+            VkResult err = inst.ext_funcs.vkGetPhysicalDeviceSurfaceCapabilities2EXT(phys_device, surface_extension.surface,
+                                                                                     &surface_capabilities2_ext);
             if (err) ERR_EXIT(err);
         }
     }
@@ -959,19 +1159,16 @@ class AppSurface {
 
 std::vector<VkPhysicalDeviceGroupProperties> GetGroups(AppInstance &inst) {
     if (inst.CheckExtensionEnabled(VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME)) {
-        PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR =
-            reinterpret_cast<PFN_vkEnumeratePhysicalDeviceGroupsKHR>(
-                vkGetInstanceProcAddr(inst.instance, "vkEnumeratePhysicalDeviceGroupsKHR"));
-        return GetVector<VkPhysicalDeviceGroupProperties>(vkEnumeratePhysicalDeviceGroupsKHR, inst.instance);
+        return GetVector<VkPhysicalDeviceGroupProperties>(inst.ext_funcs.vkEnumeratePhysicalDeviceGroupsKHR, inst.instance);
     }
     return {};
 }
 
-std::vector<VkPhysicalDeviceProperties> GetGroupProps(VkPhysicalDeviceGroupProperties group) {
+std::vector<VkPhysicalDeviceProperties> GetGroupProps(AppInstance &inst, VkPhysicalDeviceGroupProperties group) {
     std::vector<VkPhysicalDeviceProperties> props(group.physicalDeviceCount);
 
     for (uint32_t i = 0; i < group.physicalDeviceCount; ++i) {
-        vkGetPhysicalDeviceProperties(group.physicalDevices[i], &props[i]);
+        inst.dll.vkGetPhysicalDeviceProperties(group.physicalDevices[i], &props[i]);
     }
 
     return props;
@@ -995,12 +1192,12 @@ std::pair<bool, VkDeviceGroupPresentCapabilitiesKHR> GetGroupCapabilities(AppIns
 
     VkDevice logical_device = VK_NULL_HANDLE;
 
-    VkResult err = vkCreateDevice(group.physicalDevices[0], &device_ci, nullptr, &logical_device);
+    VkResult err = inst.dll.vkCreateDevice(group.physicalDevices[0], &device_ci, nullptr, &logical_device);
     if (err != VK_SUCCESS && err != VK_ERROR_EXTENSION_NOT_PRESENT) ERR_EXIT(err);
 
     if (err == VK_ERROR_EXTENSION_NOT_PRESENT) {
         VkDeviceGroupPresentCapabilitiesKHR group_capabilities = {VK_STRUCTURE_TYPE_DEVICE_GROUP_PRESENT_CAPABILITIES_KHR, nullptr};
-        vkDestroyDevice(logical_device, nullptr);
+        inst.dll.vkDestroyDevice(logical_device, nullptr);
         return std::pair<bool, VkDeviceGroupPresentCapabilitiesKHR>(false, group_capabilities);
     }
 
@@ -1008,13 +1205,10 @@ std::pair<bool, VkDeviceGroupPresentCapabilitiesKHR> GetGroupCapabilities(AppIns
 
     // If the KHR_device_group extension is present, write the capabilities of the logical device into a struct for later
     // output to user.
-    PFN_vkGetDeviceGroupPresentCapabilitiesKHR vkGetDeviceGroupPresentCapabilitiesKHR =
-        reinterpret_cast<PFN_vkGetDeviceGroupPresentCapabilitiesKHR>(
-            vkGetInstanceProcAddr(inst.instance, "vkGetDeviceGroupPresentCapabilitiesKHR"));
-    err = vkGetDeviceGroupPresentCapabilitiesKHR(logical_device, &group_capabilities);
+    err = inst.ext_funcs.vkGetDeviceGroupPresentCapabilitiesKHR(logical_device, &group_capabilities);
     if (err) ERR_EXIT(err);
 
-    vkDestroyDevice(logical_device, nullptr);
+    inst.dll.vkDestroyDevice(logical_device, nullptr);
 
     return std::pair<bool, VkDeviceGroupPresentCapabilitiesKHR>(true, group_capabilities);
 }
@@ -1087,7 +1281,7 @@ struct AppGpu {
 
     AppGpu(AppInstance &inst, uint32_t id, VkPhysicalDevice phys_device, pNextChainInfos chainInfos)
         : inst(inst), id(id), phys_device(phys_device) {
-        vkGetPhysicalDeviceProperties(phys_device, &props);
+        inst.dll.vkGetPhysicalDeviceProperties(phys_device, &props);
 
         // needs to find the minimum of the instance and device version, and use that to print the device info
         uint32_t gpu_version = props.apiVersion < inst.instance_version ? props.apiVersion : inst.instance_version;
@@ -1097,15 +1291,15 @@ struct AppGpu {
             props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
             buildpNextChain((VkStructureHeader *)&props2, chainInfos.phys_device_props2);
 
-            inst.vkGetPhysicalDeviceProperties2KHR(phys_device, &props2);
+            inst.ext_funcs.vkGetPhysicalDeviceProperties2KHR(phys_device, &props2);
         }
 
         /* get queue count */
-        vkGetPhysicalDeviceQueueFamilyProperties(phys_device, &queue_count, nullptr);
+        inst.dll.vkGetPhysicalDeviceQueueFamilyProperties(phys_device, &queue_count, nullptr);
 
         queue_props.resize(queue_count);
 
-        vkGetPhysicalDeviceQueueFamilyProperties(phys_device, &queue_count, queue_props.data());
+        inst.dll.vkGetPhysicalDeviceQueueFamilyProperties(phys_device, &queue_count, queue_props.data());
 
         if (inst.CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
             queue_props2.resize(queue_count);
@@ -1115,23 +1309,23 @@ struct AppGpu {
                 queue_props2[i].pNext = nullptr;
             }
 
-            inst.vkGetPhysicalDeviceQueueFamilyProperties2KHR(phys_device, &queue_count, queue_props2.data());
+            inst.ext_funcs.vkGetPhysicalDeviceQueueFamilyProperties2KHR(phys_device, &queue_count, queue_props2.data());
         }
 
-        vkGetPhysicalDeviceMemoryProperties(phys_device, &memory_props);
+        inst.dll.vkGetPhysicalDeviceMemoryProperties(phys_device, &memory_props);
 
-        vkGetPhysicalDeviceFeatures(phys_device, &features);
+        inst.dll.vkGetPhysicalDeviceFeatures(phys_device, &features);
 
         if (inst.CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
             memory_props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR;
             buildpNextChain((VkStructureHeader *)&memory_props2, chainInfos.phys_device_mem_props2);
 
-            inst.vkGetPhysicalDeviceMemoryProperties2KHR(phys_device, &memory_props2);
+            inst.ext_funcs.vkGetPhysicalDeviceMemoryProperties2KHR(phys_device, &memory_props2);
 
             features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
             buildpNextChain((VkStructureHeader *)&features2, chainInfos.phys_device_features2);
 
-            inst.vkGetPhysicalDeviceFeatures2KHR(phys_device, &features2);
+            inst.ext_funcs.vkGetPhysicalDeviceFeatures2KHR(phys_device, &features2);
         }
 
         device_extensions = AppGetPhysicalDeviceLayerExtensions(nullptr);
@@ -1147,7 +1341,7 @@ struct AppGpu {
         const VkDeviceCreateInfo device_ci = {
             VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, nullptr, 0, 1, &q_ci, 0, nullptr, 0, nullptr, &enabled_features};
 
-        VkResult err = vkCreateDevice(phys_device, &device_ci, nullptr, &dev);
+        VkResult err = inst.dll.vkCreateDevice(phys_device, &device_ci, nullptr, &dev);
         if (err) ERR_EXIT(err);
 
         const VkFormat color_format = VK_FORMAT_R8G8B8A8_UNORM;
@@ -1167,7 +1361,7 @@ struct AppGpu {
                 mem_type_res_support.image[tiling][fmt_i].transient_supported = true;
 
                 VkFormatProperties fmt_props;
-                vkGetPhysicalDeviceFormatProperties(phys_device, formats[fmt_i], &fmt_props);
+                inst.dll.vkGetPhysicalDeviceFormatProperties(phys_device, formats[fmt_i], &fmt_props);
                 if ((tiling == VK_IMAGE_TILING_OPTIMAL && fmt_props.optimalTilingFeatures == 0) ||
                     (tiling == VK_IMAGE_TILING_LINEAR && fmt_props.linearTilingFeatures == 0)) {
                     mem_type_res_support.image[tiling][fmt_i].regular_supported = false;
@@ -1212,8 +1406,9 @@ struct AppGpu {
                         }
 
                         VkImageFormatProperties img_props;
-                        err = vkGetPhysicalDeviceImageFormatProperties(phys_device, image_ci.format, image_ci.imageType,
-                                                                       image_ci.tiling, image_ci.usage, image_ci.flags, &img_props);
+                        err = inst.dll.vkGetPhysicalDeviceImageFormatProperties(phys_device, image_ci.format, image_ci.imageType,
+                                                                                image_ci.tiling, image_ci.usage, image_ci.flags,
+                                                                                &img_props);
 
                         uint32_t *memtypes;
                         bool *support;
@@ -1239,14 +1434,14 @@ struct AppGpu {
                             if (err) ERR_EXIT(err);
 
                             VkImage dummy_img;
-                            err = vkCreateImage(dev, &image_ci, nullptr, &dummy_img);
+                            err = inst.dll.vkCreateImage(dev, &image_ci, nullptr, &dummy_img);
                             if (err) ERR_EXIT(err);
 
                             VkMemoryRequirements mem_req;
-                            vkGetImageMemoryRequirements(dev, dummy_img, &mem_req);
+                            inst.dll.vkGetImageMemoryRequirements(dev, dummy_img, &mem_req);
                             *memtypes = mem_req.memoryTypeBits;
 
-                            vkDestroyImage(dev, dummy_img, nullptr);
+                            inst.dll.vkDestroyImage(dev, dummy_img, nullptr);
                         }
                     }
                 }
@@ -1306,7 +1501,7 @@ struct AppGpu {
         };
     }
     ~AppGpu() {
-        vkDestroyDevice(dev, nullptr);
+        inst.dll.vkDestroyDevice(dev, nullptr);
 
         if (inst.CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
             freepNextChain(static_cast<VkStructureHeader *>(features2.pNext));
@@ -1328,7 +1523,7 @@ struct AppGpu {
     }
 
     std::vector<VkExtensionProperties> AppGetPhysicalDeviceLayerExtensions(char *layer_name) {
-        return GetVector<VkExtensionProperties>(vkEnumerateDeviceExtensionProperties, phys_device, layer_name);
+        return GetVector<VkExtensionProperties>(inst.dll.vkEnumerateDeviceExtensionProperties, phys_device, layer_name);
     }
 
     // Helper function to determine whether a format range is currently supported.
@@ -1370,8 +1565,8 @@ struct AppQueueFamilyProperties {
         }
 
         for (auto &surface_ext : gpu.inst.surface_extensions) {
-            VkResult err = vkGetPhysicalDeviceSurfaceSupportKHR(gpu.phys_device, queue_index, surface_ext.surface,
-                                                                &surface_ext.supports_present);
+            VkResult err = gpu.inst.ext_funcs.vkGetPhysicalDeviceSurfaceSupportKHR(
+                gpu.phys_device, queue_index, surface_ext.surface, &surface_ext.supports_present);
             if (err) ERR_EXIT(err);
 
             const bool first = (surface_ext == gpu.inst.surface_extensions.at(0));
@@ -1385,8 +1580,8 @@ struct AppQueueFamilyProperties {
 };
 
 std::vector<VkPhysicalDeviceToolPropertiesEXT> GetToolingInfo(AppGpu &gpu) {
-    if (gpu.inst.vkGetPhysicalDeviceToolPropertiesEXT == nullptr) return {};
-    return GetVector<VkPhysicalDeviceToolPropertiesEXT>(gpu.inst.vkGetPhysicalDeviceToolPropertiesEXT, gpu.phys_device);
+    if (gpu.inst.ext_funcs.vkGetPhysicalDeviceToolPropertiesEXT == nullptr) return {};
+    return GetVector<VkPhysicalDeviceToolPropertiesEXT>(gpu.inst.ext_funcs.vkGetPhysicalDeviceToolPropertiesEXT, gpu.phys_device);
 }
 
 // --------- Format Properties ----------//
@@ -1412,12 +1607,12 @@ struct hash<PropFlags> {
 }  // namespace std
 
 // Used to sort the formats into buckets by their properties.
-std::unordered_map<PropFlags, std::vector<VkFormat>> FormatPropMap(AppGpu &gpu) {
-    std::unordered_map<PropFlags, std::vector<VkFormat>> map;
+std::unordered_map<PropFlags, std::vector<VkFormat> > FormatPropMap(AppGpu &gpu) {
+    std::unordered_map<PropFlags, std::vector<VkFormat> > map;
     for (auto fmtRange : gpu.supported_format_ranges) {
         for (int32_t fmt = fmtRange.first_format; fmt <= fmtRange.last_format; ++fmt) {
             VkFormatProperties props;
-            vkGetPhysicalDeviceFormatProperties(gpu.phys_device, static_cast<VkFormat>(fmt), &props);
+            gpu.inst.dll.vkGetPhysicalDeviceFormatProperties(gpu.phys_device, static_cast<VkFormat>(fmt), &props);
 
             PropFlags pf = {props.linearTilingFeatures, props.optimalTilingFeatures, props.bufferFeatures};
 
@@ -1432,6 +1627,6 @@ VkFormatProperties2 GetFormatProperties2(AppGpu &gpu, VkFormat format, pNextChai
     props.sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2;
     buildpNextChain((VkStructureHeader *)&props, chainInfos.format_properties2);
 
-    gpu.inst.vkGetPhysicalDeviceFormatProperties2KHR(gpu.phys_device, format, &props);
+    gpu.inst.ext_funcs.vkGetPhysicalDeviceFormatProperties2KHR(gpu.phys_device, format, &props);
     return props;
 }