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