1 //========================================================================
2 // GLFW 3.4 - www.glfw.org
3 //------------------------------------------------------------------------
4 // Copyright (c) 2002-2006 Marcus Geelnard
5 // Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
7 // This software is provided 'as-is', without any express or implied
8 // warranty. In no event will the authors be held liable for any damages
9 // arising from the use of this software.
11 // Permission is granted to anyone to use this software for any purpose,
12 // including commercial applications, and to alter it and redistribute it
13 // freely, subject to the following restrictions:
15 // 1. The origin of this software must not be misrepresented; you must not
16 // claim that you wrote the original software. If you use this software
17 // in a product, an acknowledgment in the product documentation would
18 // be appreciated but is not required.
20 // 2. Altered source versions must be plainly marked as such, and must not
21 // be misrepresented as being the original software.
23 // 3. This notice may not be removed or altered from any source
26 //========================================================================
27 // Please use C89 style variable declarations in this file because VS 2010
28 //========================================================================
36 #define _GLFW_FIND_LOADER 1
37 #define _GLFW_REQUIRE_LOADER 2
40 //////////////////////////////////////////////////////////////////////////
41 ////// GLFW internal API //////
42 //////////////////////////////////////////////////////////////////////////
44 GLFWbool _glfwInitVulkan(int mode)
47 VkExtensionProperties* ep;
50 if (_glfw.vk.available)
53 #if !defined(_GLFW_VULKAN_STATIC)
54 #if defined(_GLFW_VULKAN_LIBRARY)
55 _glfw.vk.handle = _glfw_dlopen(_GLFW_VULKAN_LIBRARY);
56 #elif defined(_GLFW_WIN32)
57 _glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
58 #elif defined(_GLFW_COCOA)
59 _glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
61 _glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS();
63 _glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
67 if (mode == _GLFW_REQUIRE_LOADER)
68 _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
73 _glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
74 _glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
75 if (!_glfw.vk.GetInstanceProcAddr)
77 _glfwInputError(GLFW_API_UNAVAILABLE,
78 "Vulkan: Loader does not export vkGetInstanceProcAddr");
80 _glfwTerminateVulkan();
84 _glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)
85 vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties");
86 if (!_glfw.vk.EnumerateInstanceExtensionProperties)
88 _glfwInputError(GLFW_API_UNAVAILABLE,
89 "Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties");
91 _glfwTerminateVulkan();
94 #endif // _GLFW_VULKAN_STATIC
96 err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
99 // NOTE: This happens on systems with a loader but without any Vulkan ICD
100 if (mode == _GLFW_REQUIRE_LOADER)
102 _glfwInputError(GLFW_API_UNAVAILABLE,
103 "Vulkan: Failed to query instance extension count: %s",
104 _glfwGetVulkanResultString(err));
107 _glfwTerminateVulkan();
111 ep = calloc(count, sizeof(VkExtensionProperties));
113 err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep);
116 _glfwInputError(GLFW_API_UNAVAILABLE,
117 "Vulkan: Failed to query instance extensions: %s",
118 _glfwGetVulkanResultString(err));
121 _glfwTerminateVulkan();
125 for (i = 0; i < count; i++)
127 if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
128 _glfw.vk.KHR_surface = GLFW_TRUE;
129 #if defined(_GLFW_WIN32)
130 else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
131 _glfw.vk.KHR_win32_surface = GLFW_TRUE;
132 #elif defined(_GLFW_COCOA)
133 else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
134 _glfw.vk.MVK_macos_surface = GLFW_TRUE;
135 else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0)
136 _glfw.vk.EXT_metal_surface = GLFW_TRUE;
137 #elif defined(_GLFW_X11)
138 else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
139 _glfw.vk.KHR_xlib_surface = GLFW_TRUE;
140 else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
141 _glfw.vk.KHR_xcb_surface = GLFW_TRUE;
142 #elif defined(_GLFW_WAYLAND)
143 else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
144 _glfw.vk.KHR_wayland_surface = GLFW_TRUE;
150 _glfw.vk.available = GLFW_TRUE;
152 _glfwPlatformGetRequiredInstanceExtensions(_glfw.vk.extensions);
157 void _glfwTerminateVulkan(void)
159 #if !defined(_GLFW_VULKAN_STATIC)
161 _glfw_dlclose(_glfw.vk.handle);
165 const char* _glfwGetVulkanResultString(VkResult result)
172 return "A fence or query has not yet completed";
174 return "A wait operation has not completed in the specified time";
176 return "An event is signaled";
178 return "An event is unsignaled";
180 return "A return array was too small for the result";
181 case VK_ERROR_OUT_OF_HOST_MEMORY:
182 return "A host memory allocation has failed";
183 case VK_ERROR_OUT_OF_DEVICE_MEMORY:
184 return "A device memory allocation has failed";
185 case VK_ERROR_INITIALIZATION_FAILED:
186 return "Initialization of an object could not be completed for implementation-specific reasons";
187 case VK_ERROR_DEVICE_LOST:
188 return "The logical or physical device has been lost";
189 case VK_ERROR_MEMORY_MAP_FAILED:
190 return "Mapping of a memory object has failed";
191 case VK_ERROR_LAYER_NOT_PRESENT:
192 return "A requested layer is not present or could not be loaded";
193 case VK_ERROR_EXTENSION_NOT_PRESENT:
194 return "A requested extension is not supported";
195 case VK_ERROR_FEATURE_NOT_PRESENT:
196 return "A requested feature is not supported";
197 case VK_ERROR_INCOMPATIBLE_DRIVER:
198 return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible";
199 case VK_ERROR_TOO_MANY_OBJECTS:
200 return "Too many objects of the type have already been created";
201 case VK_ERROR_FORMAT_NOT_SUPPORTED:
202 return "A requested format is not supported on this device";
203 case VK_ERROR_SURFACE_LOST_KHR:
204 return "A surface is no longer available";
205 case VK_SUBOPTIMAL_KHR:
206 return "A swapchain no longer matches the surface properties exactly, but can still be used";
207 case VK_ERROR_OUT_OF_DATE_KHR:
208 return "A surface has changed in such a way that it is no longer compatible with the swapchain";
209 case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
210 return "The display used by a swapchain does not use the same presentable image layout";
211 case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
212 return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API";
213 case VK_ERROR_VALIDATION_FAILED_EXT:
214 return "A validation layer found an error";
216 return "ERROR: UNKNOWN VULKAN ERROR";
221 //////////////////////////////////////////////////////////////////////////
222 ////// GLFW public API //////
223 //////////////////////////////////////////////////////////////////////////
225 GLFWAPI int glfwVulkanSupported(void)
227 _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
228 return _glfwInitVulkan(_GLFW_FIND_LOADER);
231 GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
233 assert(count != NULL);
237 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
239 if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
242 if (!_glfw.vk.extensions[0])
246 return (const char**) _glfw.vk.extensions;
249 GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
250 const char* procname)
253 assert(procname != NULL);
255 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
257 if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
260 proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
261 #if defined(_GLFW_VULKAN_STATIC)
264 if (strcmp(procname, "vkGetInstanceProcAddr") == 0)
265 return (GLFWvkproc) vkGetInstanceProcAddr;
269 proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
275 GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
276 VkPhysicalDevice device,
277 uint32_t queuefamily)
279 assert(instance != VK_NULL_HANDLE);
280 assert(device != VK_NULL_HANDLE);
282 _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
284 if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
287 if (!_glfw.vk.extensions[0])
289 _glfwInputError(GLFW_API_UNAVAILABLE,
290 "Vulkan: Window surface creation extensions not found");
294 return _glfwPlatformGetPhysicalDevicePresentationSupport(instance,
299 GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
301 const VkAllocationCallbacks* allocator,
302 VkSurfaceKHR* surface)
304 _GLFWwindow* window = (_GLFWwindow*) handle;
305 assert(instance != VK_NULL_HANDLE);
306 assert(window != NULL);
307 assert(surface != NULL);
309 *surface = VK_NULL_HANDLE;
311 _GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
313 if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
314 return VK_ERROR_INITIALIZATION_FAILED;
316 if (!_glfw.vk.extensions[0])
318 _glfwInputError(GLFW_API_UNAVAILABLE,
319 "Vulkan: Window surface creation extensions not found");
320 return VK_ERROR_EXTENSION_NOT_PRESENT;
323 if (window->context.client != GLFW_NO_API)
325 _glfwInputError(GLFW_INVALID_VALUE,
326 "Vulkan: Window surface creation requires the window to have the client API set to GLFW_NO_API");
327 return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
330 return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface);