diff --git a/README.md b/README.md index d1396af4..ed8a0def 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,7 @@ information on what to include when reporting a bug. ## Changelog + - Added `glfwInitVulkan` to init Vulkan with a custom loader (#1374) - Added `GLFW_PLATFORM` init hint for runtime platform selection (#1958) - Added `GLFW_ANY_PLATFORM`, `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` and `GLFW_PLATFORM_NULL` symbols to diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index efd54e0c..7266b323 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -6081,6 +6081,29 @@ GLFWAPI int glfwExtensionSupported(const char* extension); */ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); +/*! @brief Initializes the Vulkan support with the given Vulkan loader + * function. + * + * The passed pointer must be a valid vkGetInstanceProcAddr function + * retrieved from the Vulkan loader. Calling this funciton is optional, and + * GLFW attempts to locate the Vulkan loader automatically if this function is + * not called explicitely. + * + * @return `GLFW_TRUE` if initializing Vulkan was successful, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.3. + * + * @ingroup vulkan + */ +GLFWAPI int glfwInitVulkan(void* getInstanceProcAddr); + /*! @brief Returns whether the Vulkan loader and an ICD have been found. * * This function returns whether the Vulkan loader and any minimally functional diff --git a/src/vulkan.c b/src/vulkan.c index 51789249..87613642 100644 --- a/src/vulkan.c +++ b/src/vulkan.c @@ -35,6 +35,7 @@ #define _GLFW_FIND_LOADER 1 #define _GLFW_REQUIRE_LOADER 2 +#define _GLFW_SKIP_LOADER 3 ////////////////////////////////////////////////////////////////////////// @@ -51,27 +52,30 @@ GLFWbool _glfwInitVulkan(int mode) return GLFW_TRUE; #if !defined(_GLFW_VULKAN_STATIC) + if (mode != _GLFW_SKIP_LOADER) { #if defined(_GLFW_VULKAN_LIBRARY) - _glfw.vk.handle = _glfwPlatformLoadModule(_GLFW_VULKAN_LIBRARY); + _glfw.vk.handle = _glfwPlatformLoadModule(_GLFW_VULKAN_LIBRARY); #elif defined(_GLFW_WIN32) - _glfw.vk.handle = _glfwPlatformLoadModule("vulkan-1.dll"); + _glfw.vk.handle = _glfwPlatformLoadModule("vulkan-1.dll"); #elif defined(_GLFW_COCOA) - _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib"); - if (!_glfw.vk.handle) - _glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa(); + _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib"); + if (!_glfw.vk.handle) + _glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa(); #else - _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so.1"); + _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so.1"); #endif - if (!_glfw.vk.handle) - { - if (mode == _GLFW_REQUIRE_LOADER) - _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found"); + if (!_glfw.vk.handle) + { + if (mode == _GLFW_REQUIRE_LOADER) + _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found"); - return GLFW_FALSE; - } + return GLFW_FALSE; + } + + _glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) + _glfwPlatformGetModuleSymbol(_glfw.vk.handle, "vkGetInstanceProcAddr"); + } // mode != _GLFW_SKIP_LOADER - _glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) - _glfwPlatformGetModuleSymbol(_glfw.vk.handle, "vkGetInstanceProcAddr"); if (!_glfw.vk.GetInstanceProcAddr) { _glfwInputError(GLFW_API_UNAVAILABLE, @@ -217,6 +221,16 @@ const char* _glfwGetVulkanResultString(VkResult result) ////// GLFW public API ////// ////////////////////////////////////////////////////////////////////////// +GLFWAPI int glfwInitVulkan(void* getInstanceProcAddr) { + _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); +#if !defined(_GLFW_VULKAN_STATIC) + _glfw.vk.GetInstanceProcAddr = getInstanceProcAddr; + return _glfwInitVulkan(_GLFW_SKIP_LOADER); +#else + return GLFW_TRUE; +#endif +} + GLFWAPI int glfwVulkanSupported(void) { _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);