1 /// Translated from C to D 2 module glfw3.vulkan; 3 4 extern(C): @nogc: nothrow: __gshared: 5 //======================================================================== 6 // GLFW 3.3 - www.glfw.org 7 //------------------------------------------------------------------------ 8 // Copyright (c) 2002-2006 Marcus Geelnard 9 // Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org> 10 // 11 // This software is provided 'as-is', without any express or implied 12 // warranty. In no event will the authors be held liable for any damages 13 // arising from the use of this software. 14 // 15 // Permission is granted to anyone to use this software for any purpose, 16 // including commercial applications, and to alter it and redistribute it 17 // freely, subject to the following restrictions: 18 // 19 // 1. The origin of this software must not be misrepresented; you must not 20 // claim that you wrote the original software. If you use this software 21 // in a product, an acknowledgment in the product documentation would 22 // be appreciated but is not required. 23 // 24 // 2. Altered source versions must be plainly marked as such, and must not 25 // be misrepresented as being the original software. 26 // 27 // 3. This notice may not be removed or altered from any source 28 // distribution. 29 // 30 //======================================================================== 31 // Please use C89 style variable declarations in this file because VS 2010 32 //======================================================================== 33 34 import glfw3.internal; 35 36 import core.stdc.assert_; 37 import core.stdc.string; 38 import core.stdc.stdlib; 39 40 enum _GLFW_FIND_LOADER = 1; 41 enum _GLFW_REQUIRE_LOADER = 2; 42 43 44 ////////////////////////////////////////////////////////////////////////// 45 ////// GLFW internal API ////// 46 ////////////////////////////////////////////////////////////////////////// 47 48 GLFWbool _glfwInitVulkan(int mode) { 49 VkResult err; 50 VkExtensionProperties* ep; 51 uint i;uint count; 52 53 if (_glfw.vk.available) 54 return GLFW_TRUE; 55 56 version (_GLFW_VULKAN_STATIC) {} else { 57 version (_GLFW_WIN32) { 58 _glfw.vk.handle = _glfw_dlopen("vulkan-1.dll"); 59 } else version (_GLFW_COCOA) { 60 _glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib"); 61 if (!_glfw.vk.handle) 62 _glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS(); 63 } else { 64 _glfw.vk.handle = _glfw_dlopen("libvulkan.so.1"); 65 } 66 if (!_glfw.vk.handle) 67 { 68 if (mode == _GLFW_REQUIRE_LOADER) 69 _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found"); 70 71 return GLFW_FALSE; 72 } 73 74 _glfw.vk.GetInstanceProcAddr = cast(PFN_vkGetInstanceProcAddr) 75 _glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr"); 76 if (!_glfw.vk.GetInstanceProcAddr) 77 { 78 _glfwInputError(GLFW_API_UNAVAILABLE, 79 "Vulkan: Loader does not export vkGetInstanceProcAddr"); 80 81 _glfwTerminateVulkan(); 82 return GLFW_FALSE; 83 } 84 85 _glfw.vk.EnumerateInstanceExtensionProperties = cast(PFN_vkEnumerateInstanceExtensionProperties) 86 _glfw.vk.GetInstanceProcAddr(null, "vkEnumerateInstanceExtensionProperties"); 87 if (!_glfw.vk.EnumerateInstanceExtensionProperties) 88 { 89 _glfwInputError(GLFW_API_UNAVAILABLE, 90 "Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties"); 91 92 _glfwTerminateVulkan(); 93 return GLFW_FALSE; 94 } 95 } // _GLFW_VULKAN_STATIC 96 97 err = _glfw.vk.EnumerateInstanceExtensionProperties(null, &count, null); 98 if (err) 99 { 100 // NOTE: This happens on systems with a loader but without any Vulkan ICD 101 if (mode == _GLFW_REQUIRE_LOADER) 102 { 103 _glfwInputError(GLFW_API_UNAVAILABLE, 104 "Vulkan: Failed to query instance extension count: %s", 105 _glfwGetVulkanResultString(err)); 106 } 107 108 _glfwTerminateVulkan(); 109 return GLFW_FALSE; 110 } 111 112 ep = cast(VkExtensionProperties*) calloc(count, VkExtensionProperties.sizeof); 113 114 err = _glfw.vk.EnumerateInstanceExtensionProperties(null, &count, ep); 115 if (err) 116 { 117 _glfwInputError(GLFW_API_UNAVAILABLE, 118 "Vulkan: Failed to query instance extensions: %s", 119 _glfwGetVulkanResultString(err)); 120 121 free(ep); 122 _glfwTerminateVulkan(); 123 return GLFW_FALSE; 124 } 125 126 for (i = 0; i < count; i++) 127 { 128 if (strcmp(ep[i].extensionName.ptr, "VK_KHR_surface") == 0) { 129 _glfw.vk.KHR_surface = GLFW_TRUE; 130 } else { 131 version (_GLFW_WIN32) { 132 if (strcmp(ep[i].extensionName.ptr, "VK_KHR_win32_surface") == 0) { 133 _glfw.vk.KHR_win32_surface = GLFW_TRUE; 134 } 135 } else version (_GLFW_COCOA) { 136 if (strcmp(ep[i].extensionName.ptr, "VK_MVK_macos_surface") == 0) 137 _glfw.vk.MVK_macos_surface = GLFW_TRUE; 138 else if (strcmp(ep[i].extensionName.ptr, "VK_EXT_metal_surface") == 0) 139 _glfw.vk.EXT_metal_surface = GLFW_TRUE; 140 } else version (_GLFW_X11) { 141 if (strcmp(ep[i].extensionName.ptr, "VK_KHR_xlib_surface") == 0) 142 _glfw.vk.KHR_xlib_surface = GLFW_TRUE; 143 else if (strcmp(ep[i].extensionName.ptr, "VK_KHR_xcb_surface") == 0) 144 _glfw.vk.KHR_xcb_surface = GLFW_TRUE; 145 } else version (_GLFW_WAYLAND) { 146 if (strcmp(ep[i].extensionName.ptr, "VK_KHR_wayland_surface") == 0) 147 _glfw.vk.KHR_wayland_surface = GLFW_TRUE; 148 } 149 } 150 } 151 152 free(ep); 153 154 _glfw.vk.available = GLFW_TRUE; 155 156 _glfwPlatformGetRequiredInstanceExtensions(_glfw.vk.extensions.ptr); 157 158 return GLFW_TRUE; 159 } 160 161 void _glfwTerminateVulkan() { 162 version(_GLFW_VULKAN_STATIC) {} else { 163 if (_glfw.vk.handle) 164 _glfw_dlclose(_glfw.vk.handle); 165 } 166 } 167 168 const(char)* _glfwGetVulkanResultString(VkResult result) { 169 switch (result) 170 { 171 case VkResult.VK_SUCCESS: 172 return "Success"; 173 case VkResult.VK_NOT_READY: 174 return "A fence or query has not yet completed"; 175 case VkResult.VK_TIMEOUT: 176 return "A wait operation has not completed in the specified time"; 177 case VkResult.VK_EVENT_SET: 178 return "An event is signaled"; 179 case VkResult.VK_EVENT_RESET: 180 return "An event is unsignaled"; 181 case VkResult.VK_INCOMPLETE: 182 return "A return array was too small for the result"; 183 case VkResult.VK_ERROR_OUT_OF_HOST_MEMORY: 184 return "A host memory allocation has failed"; 185 case VkResult.VK_ERROR_OUT_OF_DEVICE_MEMORY: 186 return "A device memory allocation has failed"; 187 case VkResult.VK_ERROR_INITIALIZATION_FAILED: 188 return "Initialization of an object could not be completed for implementation-specific reasons"; 189 case VkResult.VK_ERROR_DEVICE_LOST: 190 return "The logical or physical device has been lost"; 191 case VkResult.VK_ERROR_MEMORY_MAP_FAILED: 192 return "Mapping of a memory object has failed"; 193 case VkResult.VK_ERROR_LAYER_NOT_PRESENT: 194 return "A requested layer is not present or could not be loaded"; 195 case VkResult.VK_ERROR_EXTENSION_NOT_PRESENT: 196 return "A requested extension is not supported"; 197 case VkResult.VK_ERROR_FEATURE_NOT_PRESENT: 198 return "A requested feature is not supported"; 199 case VkResult.VK_ERROR_INCOMPATIBLE_DRIVER: 200 return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible"; 201 case VkResult.VK_ERROR_TOO_MANY_OBJECTS: 202 return "Too many objects of the type have already been created"; 203 case VkResult.VK_ERROR_FORMAT_NOT_SUPPORTED: 204 return "A requested format is not supported on this device"; 205 case VkResult.VK_ERROR_SURFACE_LOST_KHR: 206 return "A surface is no longer available"; 207 case VkResult.VK_SUBOPTIMAL_KHR: 208 return "A swapchain no longer matches the surface properties exactly, but can still be used"; 209 case VkResult.VK_ERROR_OUT_OF_DATE_KHR: 210 return "A surface has changed in such a way that it is no longer compatible with the swapchain"; 211 case VkResult.VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: 212 return "The display used by a swapchain does not use the same presentable image layout"; 213 case VkResult.VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: 214 return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API"; 215 case VkResult.VK_ERROR_VALIDATION_FAILED_EXT: 216 return "A validation layer found an error"; 217 default: 218 return "ERROR: UNKNOWN VULKAN ERROR"; 219 } 220 } 221 222 223 ////////////////////////////////////////////////////////////////////////// 224 ////// GLFW public API ////// 225 ////////////////////////////////////////////////////////////////////////// 226 227 int glfwVulkanSupported() { 228 mixin(_GLFW_REQUIRE_INIT_OR_RETURN!"GLFW_FALSE"); 229 return _glfwInitVulkan(_GLFW_FIND_LOADER); 230 } 231 232 const(char)** glfwGetRequiredInstanceExtensions(uint* count) { 233 assert(count != null); 234 235 *count = 0; 236 237 mixin(_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 cast(const(char)**) _glfw.vk.extensions; 247 } 248 249 GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const(char)* procname) { 250 GLFWvkproc proc; 251 assert(procname != null); 252 253 mixin(_GLFW_REQUIRE_INIT_OR_RETURN!"null"); 254 255 if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) 256 return null; 257 258 proc = cast(GLFWvkproc) _glfw.vk.GetInstanceProcAddr(instance, procname); 259 version (_GLFW_VULKAN_STATIC) { 260 if (!proc) 261 { 262 if (strcmp(procname, "vkGetInstanceProcAddr") == 0) 263 return cast(GLFWvkproc) vkGetInstanceProcAddr; 264 } 265 } else { 266 if (!proc) 267 proc = cast(GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname); 268 } 269 270 return proc; 271 } 272 273 int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint queuefamily) { 274 assert(instance != null); 275 assert(device != null); 276 277 mixin(_GLFW_REQUIRE_INIT_OR_RETURN!"GLFW_FALSE"); 278 279 if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) 280 return GLFW_FALSE; 281 282 if (!_glfw.vk.extensions[0]) 283 { 284 _glfwInputError(GLFW_API_UNAVAILABLE, 285 "Vulkan: Window surface creation extensions not found"); 286 return GLFW_FALSE; 287 } 288 289 return _glfwPlatformGetPhysicalDevicePresentationSupport(instance, 290 device, 291 queuefamily); 292 } 293 294 VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* handle, const(VkAllocationCallbacks)* allocator, VkSurfaceKHR* surface) { 295 _GLFWwindow* window = cast(_GLFWwindow*) handle; 296 assert(instance != null); 297 assert(window != null); 298 assert(surface != null); 299 300 *surface = VK_NULL_HANDLE; 301 302 mixin(_GLFW_REQUIRE_INIT_OR_RETURN!"VkResult.VK_ERROR_INITIALIZATION_FAILED"); 303 304 if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER)) 305 return VkResult.VK_ERROR_INITIALIZATION_FAILED; 306 307 if (!_glfw.vk.extensions[0]) 308 { 309 _glfwInputError(GLFW_API_UNAVAILABLE, 310 "Vulkan: Window surface creation extensions not found"); 311 return VkResult.VK_ERROR_EXTENSION_NOT_PRESENT; 312 } 313 314 if (window.context.client != GLFW_NO_API) 315 { 316 _glfwInputError(GLFW_INVALID_VALUE, 317 "Vulkan: Window surface creation requires the window to have the client API set to GLFW_NO_API"); 318 return VkResult.VK_ERROR_NATIVE_WINDOW_IN_USE_KHR; 319 } 320 321 return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface); 322 }