]> git.sesse.net Git - pistorm/blob - raylib_pi4_test/external/glfw/src/vulkan.c
Update raylib files and Makefile for Pi 4 testing
[pistorm] / raylib_pi4_test / external / glfw / src / vulkan.c
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>
6 //
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.
10 //
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:
14 //
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.
19 //
20 // 2. Altered source versions must be plainly marked as such, and must not
21 //    be misrepresented as being the original software.
22 //
23 // 3. This notice may not be removed or altered from any source
24 //    distribution.
25 //
26 //========================================================================
27 // Please use C89 style variable declarations in this file because VS 2010
28 //========================================================================
29
30 #include "internal.h"
31
32 #include <assert.h>
33 #include <string.h>
34 #include <stdlib.h>
35
36 #define _GLFW_FIND_LOADER    1
37 #define _GLFW_REQUIRE_LOADER 2
38
39
40 //////////////////////////////////////////////////////////////////////////
41 //////                       GLFW internal API                      //////
42 //////////////////////////////////////////////////////////////////////////
43
44 GLFWbool _glfwInitVulkan(int mode)
45 {
46     VkResult err;
47     VkExtensionProperties* ep;
48     uint32_t i, count;
49
50     if (_glfw.vk.available)
51         return GLFW_TRUE;
52
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");
60     if (!_glfw.vk.handle)
61         _glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS();
62 #else
63     _glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
64 #endif
65     if (!_glfw.vk.handle)
66     {
67         if (mode == _GLFW_REQUIRE_LOADER)
68             _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
69
70         return GLFW_FALSE;
71     }
72
73     _glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
74         _glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
75     if (!_glfw.vk.GetInstanceProcAddr)
76     {
77         _glfwInputError(GLFW_API_UNAVAILABLE,
78                         "Vulkan: Loader does not export vkGetInstanceProcAddr");
79
80         _glfwTerminateVulkan();
81         return GLFW_FALSE;
82     }
83
84     _glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)
85         vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties");
86     if (!_glfw.vk.EnumerateInstanceExtensionProperties)
87     {
88         _glfwInputError(GLFW_API_UNAVAILABLE,
89                         "Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties");
90
91         _glfwTerminateVulkan();
92         return GLFW_FALSE;
93     }
94 #endif // _GLFW_VULKAN_STATIC
95
96     err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
97     if (err)
98     {
99         // NOTE: This happens on systems with a loader but without any Vulkan ICD
100         if (mode == _GLFW_REQUIRE_LOADER)
101         {
102             _glfwInputError(GLFW_API_UNAVAILABLE,
103                             "Vulkan: Failed to query instance extension count: %s",
104                             _glfwGetVulkanResultString(err));
105         }
106
107         _glfwTerminateVulkan();
108         return GLFW_FALSE;
109     }
110
111     ep = calloc(count, sizeof(VkExtensionProperties));
112
113     err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep);
114     if (err)
115     {
116         _glfwInputError(GLFW_API_UNAVAILABLE,
117                         "Vulkan: Failed to query instance extensions: %s",
118                         _glfwGetVulkanResultString(err));
119
120         free(ep);
121         _glfwTerminateVulkan();
122         return GLFW_FALSE;
123     }
124
125     for (i = 0;  i < count;  i++)
126     {
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;
145 #endif
146     }
147
148     free(ep);
149
150     _glfw.vk.available = GLFW_TRUE;
151
152     _glfwPlatformGetRequiredInstanceExtensions(_glfw.vk.extensions);
153
154     return GLFW_TRUE;
155 }
156
157 void _glfwTerminateVulkan(void)
158 {
159 #if !defined(_GLFW_VULKAN_STATIC)
160     if (_glfw.vk.handle)
161         _glfw_dlclose(_glfw.vk.handle);
162 #endif
163 }
164
165 const char* _glfwGetVulkanResultString(VkResult result)
166 {
167     switch (result)
168     {
169         case VK_SUCCESS:
170             return "Success";
171         case VK_NOT_READY:
172             return "A fence or query has not yet completed";
173         case VK_TIMEOUT:
174             return "A wait operation has not completed in the specified time";
175         case VK_EVENT_SET:
176             return "An event is signaled";
177         case VK_EVENT_RESET:
178             return "An event is unsignaled";
179         case VK_INCOMPLETE:
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";
215         default:
216             return "ERROR: UNKNOWN VULKAN ERROR";
217     }
218 }
219
220
221 //////////////////////////////////////////////////////////////////////////
222 //////                        GLFW public API                       //////
223 //////////////////////////////////////////////////////////////////////////
224
225 GLFWAPI int glfwVulkanSupported(void)
226 {
227     _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
228     return _glfwInitVulkan(_GLFW_FIND_LOADER);
229 }
230
231 GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
232 {
233     assert(count != NULL);
234
235     *count = 0;
236
237     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
238
239     if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
240         return NULL;
241
242     if (!_glfw.vk.extensions[0])
243         return NULL;
244
245     *count = 2;
246     return (const char**) _glfw.vk.extensions;
247 }
248
249 GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
250                                               const char* procname)
251 {
252     GLFWvkproc proc;
253     assert(procname != NULL);
254
255     _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
256
257     if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
258         return NULL;
259
260     proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
261 #if defined(_GLFW_VULKAN_STATIC)
262     if (!proc)
263     {
264         if (strcmp(procname, "vkGetInstanceProcAddr") == 0)
265             return (GLFWvkproc) vkGetInstanceProcAddr;
266     }
267 #else
268     if (!proc)
269         proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
270 #endif
271
272     return proc;
273 }
274
275 GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
276                                                      VkPhysicalDevice device,
277                                                      uint32_t queuefamily)
278 {
279     assert(instance != VK_NULL_HANDLE);
280     assert(device != VK_NULL_HANDLE);
281
282     _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
283
284     if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
285         return GLFW_FALSE;
286
287     if (!_glfw.vk.extensions[0])
288     {
289         _glfwInputError(GLFW_API_UNAVAILABLE,
290                         "Vulkan: Window surface creation extensions not found");
291         return GLFW_FALSE;
292     }
293
294     return _glfwPlatformGetPhysicalDevicePresentationSupport(instance,
295                                                              device,
296                                                              queuefamily);
297 }
298
299 GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
300                                          GLFWwindow* handle,
301                                          const VkAllocationCallbacks* allocator,
302                                          VkSurfaceKHR* surface)
303 {
304     _GLFWwindow* window = (_GLFWwindow*) handle;
305     assert(instance != VK_NULL_HANDLE);
306     assert(window != NULL);
307     assert(surface != NULL);
308
309     *surface = VK_NULL_HANDLE;
310
311     _GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
312
313     if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
314         return VK_ERROR_INITIALIZATION_FAILED;
315
316     if (!_glfw.vk.extensions[0])
317     {
318         _glfwInputError(GLFW_API_UNAVAILABLE,
319                         "Vulkan: Window surface creation extensions not found");
320         return VK_ERROR_EXTENSION_NOT_PRESENT;
321     }
322
323     if (window->context.client != GLFW_NO_API)
324     {
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;
328     }
329
330     return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface);
331 }
332