github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/external/glfw/src/vulkan.c (about) 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