GCC Code Coverage Report


Directory: ./
File: submodules/raylib/src/external/glfw/src/vulkan.c
Date: 2023-09-29 04:53:15
Exec Total Coverage
Lines: 0 140 0.0%
Branches: 0 92 0.0%

Line Branch Exec Source
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 PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties;
49 uint32_t i, count;
50
51 ✗ if (_glfw.vk.available)
52 return GLFW_TRUE;
53
54 ✗ if (_glfw.hints.init.vulkanLoader)
55 ✗ _glfw.vk.GetInstanceProcAddr = _glfw.hints.init.vulkanLoader;
56 else
57 {
58 #if defined(_GLFW_VULKAN_LIBRARY)
59 _glfw.vk.handle = _glfwPlatformLoadModule(_GLFW_VULKAN_LIBRARY);
60 #elif defined(_GLFW_WIN32)
61 _glfw.vk.handle = _glfwPlatformLoadModule("vulkan-1.dll");
62 #elif defined(_GLFW_COCOA)
63 _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib");
64 if (!_glfw.vk.handle)
65 _glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa();
66 #elif defined(__OpenBSD__) || defined(__NetBSD__)
67 _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so");
68 #else
69 ✗ _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so.1");
70 #endif
71 ✗ if (!_glfw.vk.handle)
72 {
73 ✗ if (mode == _GLFW_REQUIRE_LOADER)
74 ✗ _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
75
76 ✗ return GLFW_FALSE;
77 }
78
79 ✗ _glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
80 ✗ _glfwPlatformGetModuleSymbol(_glfw.vk.handle, "vkGetInstanceProcAddr");
81 ✗ if (!_glfw.vk.GetInstanceProcAddr)
82 {
83 ✗ _glfwInputError(GLFW_API_UNAVAILABLE,
84 "Vulkan: Loader does not export vkGetInstanceProcAddr");
85
86 ✗ _glfwTerminateVulkan();
87 ✗ return GLFW_FALSE;
88 }
89 }
90
91 vkEnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)
92 ✗ vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties");
93 ✗ if (!vkEnumerateInstanceExtensionProperties)
94 {
95 ✗ _glfwInputError(GLFW_API_UNAVAILABLE,
96 "Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties");
97
98 ✗ _glfwTerminateVulkan();
99 ✗ return GLFW_FALSE;
100 }
101
102 ✗ err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
103 ✗ if (err)
104 {
105 // NOTE: This happens on systems with a loader but without any Vulkan ICD
106 ✗ if (mode == _GLFW_REQUIRE_LOADER)
107 {
108 ✗ _glfwInputError(GLFW_API_UNAVAILABLE,
109 "Vulkan: Failed to query instance extension count: %s",
110 _glfwGetVulkanResultString(err));
111 }
112
113 ✗ _glfwTerminateVulkan();
114 ✗ return GLFW_FALSE;
115 }
116
117 ✗ ep = _glfw_calloc(count, sizeof(VkExtensionProperties));
118
119 ✗ err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep);
120 ✗ if (err)
121 {
122 ✗ _glfwInputError(GLFW_API_UNAVAILABLE,
123 "Vulkan: Failed to query instance extensions: %s",
124 _glfwGetVulkanResultString(err));
125
126 ✗ _glfw_free(ep);
127 ✗ _glfwTerminateVulkan();
128 ✗ return GLFW_FALSE;
129 }
130
131 ✗ for (i = 0; i < count; i++)
132 {
133 ✗ if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
134 ✗ _glfw.vk.KHR_surface = GLFW_TRUE;
135 ✗ else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
136 ✗ _glfw.vk.KHR_win32_surface = GLFW_TRUE;
137 ✗ else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
138 ✗ _glfw.vk.MVK_macos_surface = GLFW_TRUE;
139 ✗ else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0)
140 ✗ _glfw.vk.EXT_metal_surface = GLFW_TRUE;
141 ✗ else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
142 ✗ _glfw.vk.KHR_xlib_surface = GLFW_TRUE;
143 ✗ else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
144 ✗ _glfw.vk.KHR_xcb_surface = GLFW_TRUE;
145 ✗ else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
146 ✗ _glfw.vk.KHR_wayland_surface = GLFW_TRUE;
147 }
148
149 ✗ _glfw_free(ep);
150
151 ✗ _glfw.vk.available = GLFW_TRUE;
152
153 ✗ _glfw.platform.getRequiredInstanceExtensions(_glfw.vk.extensions);
154
155 ✗ return GLFW_TRUE;
156 }
157
158 ✗ void _glfwTerminateVulkan(void)
159 {
160 ✗ if (_glfw.vk.handle)
161 ✗ _glfwPlatformFreeModule(_glfw.vk.handle);
162 }
163
164 ✗ const char* _glfwGetVulkanResultString(VkResult result)
165 {
166 ✗ switch (result)
167 {
168 case VK_SUCCESS:
169 return "Success";
170 ✗ case VK_NOT_READY:
171 ✗ return "A fence or query has not yet completed";
172 ✗ case VK_TIMEOUT:
173 ✗ return "A wait operation has not completed in the specified time";
174 ✗ case VK_EVENT_SET:
175 ✗ return "An event is signaled";
176 ✗ case VK_EVENT_RESET:
177 ✗ return "An event is unsignaled";
178 ✗ case VK_INCOMPLETE:
179 ✗ return "A return array was too small for the result";
180 ✗ case VK_ERROR_OUT_OF_HOST_MEMORY:
181 ✗ return "A host memory allocation has failed";
182 ✗ case VK_ERROR_OUT_OF_DEVICE_MEMORY:
183 ✗ return "A device memory allocation has failed";
184 ✗ case VK_ERROR_INITIALIZATION_FAILED:
185 ✗ return "Initialization of an object could not be completed for implementation-specific reasons";
186 ✗ case VK_ERROR_DEVICE_LOST:
187 ✗ return "The logical or physical device has been lost";
188 ✗ case VK_ERROR_MEMORY_MAP_FAILED:
189 ✗ return "Mapping of a memory object has failed";
190 ✗ case VK_ERROR_LAYER_NOT_PRESENT:
191 ✗ return "A requested layer is not present or could not be loaded";
192 ✗ case VK_ERROR_EXTENSION_NOT_PRESENT:
193 ✗ return "A requested extension is not supported";
194 ✗ case VK_ERROR_FEATURE_NOT_PRESENT:
195 ✗ return "A requested feature is not supported";
196 ✗ case VK_ERROR_INCOMPATIBLE_DRIVER:
197 ✗ return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible";
198 ✗ case VK_ERROR_TOO_MANY_OBJECTS:
199 ✗ return "Too many objects of the type have already been created";
200 ✗ case VK_ERROR_FORMAT_NOT_SUPPORTED:
201 ✗ return "A requested format is not supported on this device";
202 ✗ case VK_ERROR_SURFACE_LOST_KHR:
203 ✗ return "A surface is no longer available";
204 ✗ case VK_SUBOPTIMAL_KHR:
205 ✗ return "A swapchain no longer matches the surface properties exactly, but can still be used";
206 ✗ case VK_ERROR_OUT_OF_DATE_KHR:
207 ✗ return "A surface has changed in such a way that it is no longer compatible with the swapchain";
208 ✗ case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
209 ✗ return "The display used by a swapchain does not use the same presentable image layout";
210 ✗ case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
211 ✗ return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API";
212 ✗ case VK_ERROR_VALIDATION_FAILED_EXT:
213 ✗ return "A validation layer found an error";
214 ✗ default:
215 ✗ return "ERROR: UNKNOWN VULKAN ERROR";
216 }
217 }
218
219
220 //////////////////////////////////////////////////////////////////////////
221 ////// GLFW public API //////
222 //////////////////////////////////////////////////////////////////////////
223
224 ✗ GLFWAPI int glfwVulkanSupported(void)
225 {
226 ✗ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
227 ✗ return _glfwInitVulkan(_GLFW_FIND_LOADER);
228 }
229
230 ✗ GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
231 {
232 assert(count != NULL);
233
234 ✗ *count = 0;
235
236 ✗ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
237
238 ✗ if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
239 return NULL;
240
241 ✗ if (!_glfw.vk.extensions[0])
242 return NULL;
243
244 ✗ *count = 2;
245 ✗ return (const char**) _glfw.vk.extensions;
246 }
247
248 ✗ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
249 const char* procname)
250 {
251 GLFWvkproc proc;
252 assert(procname != NULL);
253
254 ✗ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
255
256 ✗ if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
257 return NULL;
258
259 // NOTE: Vulkan 1.0 and 1.1 vkGetInstanceProcAddr cannot return itself
260 ✗ if (strcmp(procname, "vkGetInstanceProcAddr") == 0)
261 ✗ return (GLFWvkproc) vkGetInstanceProcAddr;
262
263 ✗ proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
264 ✗ if (!proc)
265 {
266 ✗ if (_glfw.vk.handle)
267 ✗ proc = (GLFWvkproc) _glfwPlatformGetModuleSymbol(_glfw.vk.handle, procname);
268 }
269
270 return proc;
271 }
272
273 ✗ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
274 VkPhysicalDevice device,
275 uint32_t queuefamily)
276 {
277 assert(instance != VK_NULL_HANDLE);
278 assert(device != VK_NULL_HANDLE);
279
280 ✗ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
281
282 ✗ if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
283 return GLFW_FALSE;
284
285 ✗ if (!_glfw.vk.extensions[0])
286 {
287 ✗ _glfwInputError(GLFW_API_UNAVAILABLE,
288 "Vulkan: Window surface creation extensions not found");
289 ✗ return GLFW_FALSE;
290 }
291
292 ✗ return _glfw.platform.getPhysicalDevicePresentationSupport(instance,
293 device,
294 queuefamily);
295 }
296
297 ✗ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
298 GLFWwindow* handle,
299 const VkAllocationCallbacks* allocator,
300 VkSurfaceKHR* surface)
301 {
302 _GLFWwindow* window = (_GLFWwindow*) handle;
303 assert(instance != VK_NULL_HANDLE);
304 assert(window != NULL);
305 assert(surface != NULL);
306
307 ✗ *surface = VK_NULL_HANDLE;
308
309 ✗ _GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
310
311 ✗ if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
312 return VK_ERROR_INITIALIZATION_FAILED;
313
314 ✗ if (!_glfw.vk.extensions[0])
315 {
316 ✗ _glfwInputError(GLFW_API_UNAVAILABLE,
317 "Vulkan: Window surface creation extensions not found");
318 ✗ return VK_ERROR_EXTENSION_NOT_PRESENT;
319 }
320
321 ✗ if (window->context.client != GLFW_NO_API)
322 {
323 ✗ _glfwInputError(GLFW_INVALID_VALUE,
324 "Vulkan: Window surface creation requires the window to have the client API set to GLFW_NO_API");
325 ✗ return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
326 }
327
328 ✗ return _glfw.platform.createWindowSurface(instance, window, allocator, surface);
329 }
330
331