medfall

A super great game engine
Log | Files | Refs

vulkan.cc (11169B)


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