123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- //========================================================================
- // GLFW 3.4 - www.glfw.org
- //------------------------------------------------------------------------
- // Copyright (c) 2002-2006 Marcus Geelnard
- // Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
- //
- // This software is provided 'as-is', without any express or implied
- // warranty. In no event will the authors be held liable for any damages
- // arising from the use of this software.
- //
- // Permission is granted to anyone to use this software for any purpose,
- // including commercial applications, and to alter it and redistribute it
- // freely, subject to the following restrictions:
- //
- // 1. The origin of this software must not be misrepresented; you must not
- // claim that you wrote the original software. If you use this software
- // in a product, an acknowledgment in the product documentation would
- // be appreciated but is not required.
- //
- // 2. Altered source versions must be plainly marked as such, and must not
- // be misrepresented as being the original software.
- //
- // 3. This notice may not be removed or altered from any source
- // distribution.
- //
- //========================================================================
- // Please use C89 style variable declarations in this file because VS 2010
- //========================================================================
- #include "internal.h"
- #include <assert.h>
- #include <string.h>
- #include <stdlib.h>
- #define _GLFW_FIND_LOADER 1
- #define _GLFW_REQUIRE_LOADER 2
- //////////////////////////////////////////////////////////////////////////
- ////// GLFW internal API //////
- //////////////////////////////////////////////////////////////////////////
- bool _glfwInitVulkan(int mode)
- {
- VkResult err;
- VkExtensionProperties* ep;
- uint32_t i, count;
- if (_glfw.vk.available)
- return true;
- #if !defined(_GLFW_VULKAN_STATIC)
- #if defined(_GLFW_VULKAN_LIBRARY)
- _glfw.vk.handle = _glfw_dlopen(_GLFW_VULKAN_LIBRARY);
- #elif defined(_GLFW_WIN32)
- _glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
- #elif defined(_GLFW_COCOA)
- _glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
- if (!_glfw.vk.handle)
- _glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS();
- #else
- _glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
- #endif
- if (!_glfw.vk.handle)
- {
- if (mode == _GLFW_REQUIRE_LOADER)
- _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
- return false;
- }
- *(void **) &_glfw.vk.GetInstanceProcAddr =
- _glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
- if (!_glfw.vk.GetInstanceProcAddr)
- {
- _glfwInputError(GLFW_API_UNAVAILABLE,
- "Vulkan: Loader does not export vkGetInstanceProcAddr");
- _glfwTerminateVulkan();
- return false;
- }
- _glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)
- vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties");
- if (!_glfw.vk.EnumerateInstanceExtensionProperties)
- {
- _glfwInputError(GLFW_API_UNAVAILABLE,
- "Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties");
- _glfwTerminateVulkan();
- return false;
- }
- #endif // _GLFW_VULKAN_STATIC
- err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
- if (err)
- {
- // NOTE: This happens on systems with a loader but without any Vulkan ICD
- if (mode == _GLFW_REQUIRE_LOADER)
- {
- _glfwInputError(GLFW_API_UNAVAILABLE,
- "Vulkan: Failed to query instance extension count: %s",
- _glfwGetVulkanResultString(err));
- }
- _glfwTerminateVulkan();
- return false;
- }
- ep = calloc(count, sizeof(VkExtensionProperties));
- err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep);
- if (err)
- {
- _glfwInputError(GLFW_API_UNAVAILABLE,
- "Vulkan: Failed to query instance extensions: %s",
- _glfwGetVulkanResultString(err));
- free(ep);
- _glfwTerminateVulkan();
- return false;
- }
- for (i = 0; i < count; i++)
- {
- if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
- _glfw.vk.KHR_surface = true;
- #if defined(_GLFW_WIN32)
- else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
- _glfw.vk.KHR_win32_surface = true;
- #elif defined(_GLFW_COCOA)
- else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
- _glfw.vk.MVK_macos_surface = true;
- else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0)
- _glfw.vk.EXT_metal_surface = true;
- #elif defined(_GLFW_X11)
- else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
- _glfw.vk.KHR_xlib_surface = true;
- else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
- _glfw.vk.KHR_xcb_surface = true;
- #elif defined(_GLFW_WAYLAND)
- else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
- _glfw.vk.KHR_wayland_surface = true;
- #endif
- }
- free(ep);
- _glfw.vk.available = true;
- _glfwPlatformGetRequiredInstanceExtensions(_glfw.vk.extensions);
- return true;
- }
- void _glfwTerminateVulkan(void)
- {
- #if !defined(_GLFW_VULKAN_STATIC)
- if (_glfw.vk.handle)
- _glfw_dlclose(_glfw.vk.handle);
- #endif
- }
- const char* _glfwGetVulkanResultString(VkResult result)
- {
- switch (result)
- {
- case VK_SUCCESS:
- return "Success";
- case VK_NOT_READY:
- return "A fence or query has not yet completed";
- case VK_TIMEOUT:
- return "A wait operation has not completed in the specified time";
- case VK_EVENT_SET:
- return "An event is signaled";
- case VK_EVENT_RESET:
- return "An event is unsignaled";
- case VK_INCOMPLETE:
- return "A return array was too small for the result";
- case VK_ERROR_OUT_OF_HOST_MEMORY:
- return "A host memory allocation has failed";
- case VK_ERROR_OUT_OF_DEVICE_MEMORY:
- return "A device memory allocation has failed";
- case VK_ERROR_INITIALIZATION_FAILED:
- return "Initialization of an object could not be completed for implementation-specific reasons";
- case VK_ERROR_DEVICE_LOST:
- return "The logical or physical device has been lost";
- case VK_ERROR_MEMORY_MAP_FAILED:
- return "Mapping of a memory object has failed";
- case VK_ERROR_LAYER_NOT_PRESENT:
- return "A requested layer is not present or could not be loaded";
- case VK_ERROR_EXTENSION_NOT_PRESENT:
- return "A requested extension is not supported";
- case VK_ERROR_FEATURE_NOT_PRESENT:
- return "A requested feature is not supported";
- case VK_ERROR_INCOMPATIBLE_DRIVER:
- return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible";
- case VK_ERROR_TOO_MANY_OBJECTS:
- return "Too many objects of the type have already been created";
- case VK_ERROR_FORMAT_NOT_SUPPORTED:
- return "A requested format is not supported on this device";
- case VK_ERROR_SURFACE_LOST_KHR:
- return "A surface is no longer available";
- case VK_SUBOPTIMAL_KHR:
- return "A swapchain no longer matches the surface properties exactly, but can still be used";
- case VK_ERROR_OUT_OF_DATE_KHR:
- return "A surface has changed in such a way that it is no longer compatible with the swapchain";
- case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
- return "The display used by a swapchain does not use the same presentable image layout";
- case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
- return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API";
- case VK_ERROR_VALIDATION_FAILED_EXT:
- return "A validation layer found an error";
- default:
- return "ERROR: UNKNOWN VULKAN ERROR";
- }
- }
- //////////////////////////////////////////////////////////////////////////
- ////// GLFW public API //////
- //////////////////////////////////////////////////////////////////////////
- GLFWAPI int glfwVulkanSupported(void)
- {
- _GLFW_REQUIRE_INIT_OR_RETURN(false);
- return _glfwInitVulkan(_GLFW_FIND_LOADER);
- }
- GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
- {
- assert(count != NULL);
- *count = 0;
- _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
- if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
- return NULL;
- if (!_glfw.vk.extensions[0])
- return NULL;
- *count = 2;
- return (const char**) _glfw.vk.extensions;
- }
- GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
- const char* procname)
- {
- GLFWvkproc proc;
- assert(procname != NULL);
- _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
- if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
- return NULL;
- proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
- #if defined(_GLFW_VULKAN_STATIC)
- if (!proc)
- {
- if (strcmp(procname, "vkGetInstanceProcAddr") == 0)
- return (GLFWvkproc) vkGetInstanceProcAddr;
- }
- #else
- if (!proc)
- *(void **) &proc = _glfw_dlsym(_glfw.vk.handle, procname);
- #endif
- return proc;
- }
- GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
- VkPhysicalDevice device,
- uint32_t queuefamily)
- {
- assert(instance != VK_NULL_HANDLE);
- assert(device != VK_NULL_HANDLE);
- _GLFW_REQUIRE_INIT_OR_RETURN(false);
- if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
- return false;
- if (!_glfw.vk.extensions[0])
- {
- _glfwInputError(GLFW_API_UNAVAILABLE,
- "Vulkan: Window surface creation extensions not found");
- return false;
- }
- return _glfwPlatformGetPhysicalDevicePresentationSupport(instance,
- device,
- queuefamily);
- }
- GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
- GLFWwindow* handle,
- const VkAllocationCallbacks* allocator,
- VkSurfaceKHR* surface)
- {
- _GLFWwindow* window = (_GLFWwindow*) handle;
- assert(instance != VK_NULL_HANDLE);
- assert(window != NULL);
- assert(surface != NULL);
- *surface = VK_NULL_HANDLE;
- _GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
- if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
- return VK_ERROR_INITIALIZATION_FAILED;
- if (!_glfw.vk.extensions[0])
- {
- _glfwInputError(GLFW_API_UNAVAILABLE,
- "Vulkan: Window surface creation extensions not found");
- return VK_ERROR_EXTENSION_NOT_PRESENT;
- }
- if (window->context.client != GLFW_NO_API)
- {
- _glfwInputError(GLFW_INVALID_VALUE,
- "Vulkan: Window surface creation requires the window to have the client API set to GLFW_NO_API");
- return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
- }
- return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface);
- }
|