github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/external/glfw/src/vulkan.c (about)

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