Atlas - vulkan.c
Home / ext / glfw / src Lines: 1 | Size: 12912 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1//======================================================================== 2// GLFW 3.5 - www.glfw.org 3//------------------------------------------------------------------------ 4// Copyright (c) 2002-2006 Marcus Geelnard 5// Copyright (c) 2006-2018 Camilla Löwy <[email protected]> 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 28#include "internal.h" 29 30#include <assert.h> 31#include <string.h> 32#include <stdlib.h> 33 34#define _GLFW_FIND_LOADER 1 35#define _GLFW_REQUIRE_LOADER 2 36 37#if defined(__APPLE__) 38 39#include <CoreFoundation/CoreFoundation.h> 40 41static void* loadLocalVulkanLoaderMacOS(void) 42{ 43 CFBundleRef bundle = CFBundleGetMainBundle(); 44 if (!bundle) 45 return NULL; 46 47 CFURLRef frameworksUrl = CFBundleCopyPrivateFrameworksURL(bundle); 48 if (!frameworksUrl) 49 return NULL; 50 51 CFURLRef loaderUrl = CFURLCreateCopyAppendingPathComponent( 52 kCFAllocatorDefault, frameworksUrl, CFSTR("libvulkan.1.dylib"), false); 53 if (!loaderUrl) 54 { 55 CFRelease(frameworksUrl); 56 return NULL; 57 } 58 59 char path[PATH_MAX]; 60 void* handle = NULL; 61 62 if (CFURLGetFileSystemRepresentation(loaderUrl, true, (UInt8*) path, sizeof(path) - 1)) 63 handle = _glfwPlatformLoadModule(path); 64 65 CFRelease(loaderUrl); 66 CFRelease(frameworksUrl); 67 return handle; 68} 69 70#endif // __APPLE__ 71 72////////////////////////////////////////////////////////////////////////// 73////// GLFW internal API ////// 74////////////////////////////////////////////////////////////////////////// 75 76GLFWbool _glfwInitVulkan(int mode) 77{ 78 VkResult err; 79 VkExtensionProperties* ep; 80 PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; 81 uint32_t i, count; 82 83 if (_glfw.vk.available) 84 return GLFW_TRUE; 85 86 if (_glfw.hints.init.vulkanLoader) 87 _glfw.vk.GetInstanceProcAddr = _glfw.hints.init.vulkanLoader; 88 else 89 { 90#if defined(_GLFW_VULKAN_LIBRARY) 91 _glfw.vk.handle = _glfwPlatformLoadModule(_GLFW_VULKAN_LIBRARY); 92#elif defined(_WIN32) 93 _glfw.vk.handle = _glfwPlatformLoadModule("vulkan-1.dll"); 94#elif defined(__APPLE__) 95 _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib"); 96 if (!_glfw.vk.handle) 97 _glfw.vk.handle = loadLocalVulkanLoaderMacOS(); 98#elif defined(__OpenBSD__) || defined(__NetBSD__) 99 _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so"); 100#else 101 _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so.1"); 102#endif 103 if (!_glfw.vk.handle) 104 { 105 if (mode == _GLFW_REQUIRE_LOADER) 106 _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found"); 107 108 return GLFW_FALSE; 109 } 110 111 _glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) 112 _glfwPlatformGetModuleSymbol(_glfw.vk.handle, "vkGetInstanceProcAddr"); 113 if (!_glfw.vk.GetInstanceProcAddr) 114 { 115 _glfwInputError(GLFW_API_UNAVAILABLE, 116 "Vulkan: Loader does not export vkGetInstanceProcAddr"); 117 118 _glfwTerminateVulkan(); 119 return GLFW_FALSE; 120 } 121 } 122 123 vkEnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties) 124 vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties"); 125 if (!vkEnumerateInstanceExtensionProperties) 126 { 127 _glfwInputError(GLFW_API_UNAVAILABLE, 128 "Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties"); 129 130 _glfwTerminateVulkan(); 131 return GLFW_FALSE; 132 } 133 134 err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL); 135 if (err) 136 { 137 // NOTE: This happens on systems with a loader but without any Vulkan ICD 138 if (mode == _GLFW_REQUIRE_LOADER) 139 { 140 _glfwInputError(GLFW_API_UNAVAILABLE, 141 "Vulkan: Failed to query instance extension count: %s", 142 _glfwGetVulkanResultString(err)); 143 } 144 145 _glfwTerminateVulkan(); 146 return GLFW_FALSE; 147 } 148 149 ep = _glfw_calloc(count, sizeof(VkExtensionProperties)); 150 151 err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep); 152 if (err) 153 { 154 _glfwInputError(GLFW_API_UNAVAILABLE, 155 "Vulkan: Failed to query instance extensions: %s", 156 _glfwGetVulkanResultString(err)); 157 158 _glfw_free(ep); 159 _glfwTerminateVulkan(); 160 return GLFW_FALSE; 161 } 162 163 for (i = 0; i < count; i++) 164 { 165 if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0) 166 _glfw.vk.KHR_surface = GLFW_TRUE; 167 else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0) 168 _glfw.vk.KHR_win32_surface = GLFW_TRUE; 169 else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0) 170 _glfw.vk.MVK_macos_surface = GLFW_TRUE; 171 else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0) 172 _glfw.vk.EXT_metal_surface = GLFW_TRUE; 173 else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0) 174 _glfw.vk.KHR_xlib_surface = GLFW_TRUE; 175 else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0) 176 _glfw.vk.KHR_xcb_surface = GLFW_TRUE; 177 else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0) 178 _glfw.vk.KHR_wayland_surface = GLFW_TRUE; 179 else if (strcmp(ep[i].extensionName, "VK_EXT_headless_surface") == 0) 180 _glfw.vk.EXT_headless_surface = GLFW_TRUE; 181 } 182 183 _glfw_free(ep); 184 185 _glfw.vk.available = GLFW_TRUE; 186 187 _glfw.platform.getRequiredInstanceExtensions(_glfw.vk.extensions); 188 189 return GLFW_TRUE; 190} 191 192void _glfwTerminateVulkan(void) 193{ 194 _glfwPlatformFreeModule(_glfw.vk.handle); 195 _glfw.vk.handle = NULL; 196} 197 198const char* _glfwGetVulkanResultString(VkResult result) 199{ 200 switch (result) 201 { 202 case VK_SUCCESS: 203 return "Success"; 204 case VK_NOT_READY: 205 return "A fence or query has not yet completed"; 206 case VK_TIMEOUT: 207 return "A wait operation has not completed in the specified time"; 208 case VK_EVENT_SET: 209 return "An event is signaled"; 210 case VK_EVENT_RESET: 211 return "An event is unsignaled"; 212 case VK_INCOMPLETE: 213 return "A return array was too small for the result"; 214 case VK_ERROR_OUT_OF_HOST_MEMORY: 215 return "A host memory allocation has failed"; 216 case VK_ERROR_OUT_OF_DEVICE_MEMORY: 217 return "A device memory allocation has failed"; 218 case VK_ERROR_INITIALIZATION_FAILED: 219 return "Initialization of an object could not be completed for implementation-specific reasons"; 220 case VK_ERROR_DEVICE_LOST: 221 return "The logical or physical device has been lost"; 222 case VK_ERROR_MEMORY_MAP_FAILED: 223 return "Mapping of a memory object has failed"; 224 case VK_ERROR_LAYER_NOT_PRESENT: 225 return "A requested layer is not present or could not be loaded"; 226 case VK_ERROR_EXTENSION_NOT_PRESENT: 227 return "A requested extension is not supported"; 228 case VK_ERROR_FEATURE_NOT_PRESENT: 229 return "A requested feature is not supported"; 230 case VK_ERROR_INCOMPATIBLE_DRIVER: 231 return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible"; 232 case VK_ERROR_TOO_MANY_OBJECTS: 233 return "Too many objects of the type have already been created"; 234 case VK_ERROR_FORMAT_NOT_SUPPORTED: 235 return "A requested format is not supported on this device"; 236 case VK_ERROR_SURFACE_LOST_KHR: 237 return "A surface is no longer available"; 238 case VK_SUBOPTIMAL_KHR: 239 return "A swapchain no longer matches the surface properties exactly, but can still be used"; 240 case VK_ERROR_OUT_OF_DATE_KHR: 241 return "A surface has changed in such a way that it is no longer compatible with the swapchain"; 242 case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: 243 return "The display used by a swapchain does not use the same presentable image layout"; 244 case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: 245 return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API"; 246 case VK_ERROR_VALIDATION_FAILED_EXT: 247 return "A validation layer found an error"; 248 default: 249 return "ERROR: UNKNOWN VULKAN ERROR"; 250 } 251} 252 253 254////////////////////////////////////////////////////////////////////////// 255////// GLFW public API ////// 256////////////////////////////////////////////////////////////////////////// 257 258GLFWAPI int glfwVulkanSupported(void) 259{ 260 _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); 261 return _glfwInitVulkan(_GLFW_FIND_LOADER); 262} 263 264GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count) 265{ 266 assert(count != NULL); 267 268 *count = 0; 269 270 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 271 272 if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) 273 return NULL; 274 275 if (!_glfw.vk.extensions[0]) 276 return NULL; 277 278 *count = 2; 279 return (const char**) _glfw.vk.extensions; 280} 281 282GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, 283 const char* procname) 284{ 285 GLFWvkproc proc; 286 assert(procname != NULL); 287 288 _GLFW_REQUIRE_INIT_OR_RETURN(NULL); 289 290 if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) 291 return NULL; 292 293 // NOTE: Vulkan 1.0 and 1.1 vkGetInstanceProcAddr cannot return itself 294 if (strcmp(procname, "vkGetInstanceProcAddr") == 0) 295 return (GLFWvkproc) vkGetInstanceProcAddr; 296 297 proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname); 298 if (!proc) 299 { 300 if (_glfw.vk.handle) 301 proc = (GLFWvkproc) _glfwPlatformGetModuleSymbol(_glfw.vk.handle, procname); 302 } 303 304 return proc; 305} 306 307GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, 308 VkPhysicalDevice device, 309 uint32_t queuefamily) 310{ 311 _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); 312 313 assert(instance != VK_NULL_HANDLE); 314 assert(device != VK_NULL_HANDLE); 315 316 if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) 317 return GLFW_FALSE; 318 319 if (!_glfw.vk.extensions[0]) 320 { 321 _glfwInputError(GLFW_API_UNAVAILABLE, 322 "Vulkan: Window surface creation extensions not found"); 323 return GLFW_FALSE; 324 } 325 326 return _glfw.platform.getPhysicalDevicePresentationSupport(instance, 327 device, 328 queuefamily); 329} 330 331GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, 332 GLFWwindow* handle, 333 const VkAllocationCallbacks* allocator, 334 VkSurfaceKHR* surface) 335{ 336 assert(surface != NULL); 337 338 *surface = VK_NULL_HANDLE; 339 340 _GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED); 341 342 _GLFWwindow* window = (_GLFWwindow*) handle; 343 assert(window != NULL); 344 assert(instance != VK_NULL_HANDLE); 345 346 if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) 347 return VK_ERROR_INITIALIZATION_FAILED; 348 349 if (!_glfw.vk.extensions[0]) 350 { 351 _glfwInputError(GLFW_API_UNAVAILABLE, 352 "Vulkan: Window surface creation extensions not found"); 353 return VK_ERROR_EXTENSION_NOT_PRESENT; 354 } 355 356 if (window->context.client != GLFW_NO_API) 357 { 358 _glfwInputError(GLFW_INVALID_VALUE, 359 "Vulkan: Window surface creation requires the window to have the client API set to GLFW_NO_API"); 360 return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR; 361 } 362 363 return _glfw.platform.createWindowSurface(instance, window, allocator, surface); 364} 365 366[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.