volviewer

Volumetric Data Toy Viewer
git clone anongit@rnpnr.xyz:volviewer.git
Log | Files | Refs | Feed | LICENSE

vulkan.c (11947B)


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