vulkan_surface.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "common/logging/log.h"
  4. #include "core/frontend/emu_window.h"
  5. #include "video_core/vulkan_common/vulkan_surface.h"
  6. #include "video_core/vulkan_common/vulkan_wrapper.h"
  7. // Include these late to avoid polluting previous headers
  8. #ifdef _WIN32
  9. #include <windows.h>
  10. // ensure include order
  11. #include <vulkan/vulkan_win32.h>
  12. #elif defined(__ANDROID__)
  13. #include <vulkan/vulkan_android.h>
  14. #elif !defined(__APPLE__)
  15. #include <X11/Xlib.h>
  16. #include <vulkan/vulkan_wayland.h>
  17. #include <vulkan/vulkan_xlib.h>
  18. #endif
  19. namespace Vulkan {
  20. vk::SurfaceKHR CreateSurface(
  21. const vk::Instance& instance,
  22. [[maybe_unused]] const Core::Frontend::EmuWindow::WindowSystemInfo& window_info) {
  23. [[maybe_unused]] const vk::InstanceDispatch& dld = instance.Dispatch();
  24. VkSurfaceKHR unsafe_surface = nullptr;
  25. #ifdef _WIN32
  26. if (window_info.type == Core::Frontend::WindowSystemType::Windows) {
  27. const HWND hWnd = static_cast<HWND>(window_info.render_surface);
  28. const VkWin32SurfaceCreateInfoKHR win32_ci{VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
  29. nullptr, 0, nullptr, hWnd};
  30. const auto vkCreateWin32SurfaceKHR = reinterpret_cast<PFN_vkCreateWin32SurfaceKHR>(
  31. dld.vkGetInstanceProcAddr(*instance, "vkCreateWin32SurfaceKHR"));
  32. if (!vkCreateWin32SurfaceKHR ||
  33. vkCreateWin32SurfaceKHR(*instance, &win32_ci, nullptr, &unsafe_surface) != VK_SUCCESS) {
  34. LOG_ERROR(Render_Vulkan, "Failed to initialize Win32 surface");
  35. throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
  36. }
  37. }
  38. #elif defined(__APPLE__)
  39. if (window_info.type == Core::Frontend::WindowSystemType::Cocoa) {
  40. const VkMetalSurfaceCreateInfoEXT macos_ci = {
  41. .pLayer = static_cast<const CAMetalLayer*>(window_info.render_surface),
  42. };
  43. const auto vkCreateMetalSurfaceEXT = reinterpret_cast<PFN_vkCreateMetalSurfaceEXT>(
  44. dld.vkGetInstanceProcAddr(*instance, "vkCreateMetalSurfaceEXT"));
  45. if (!vkCreateMetalSurfaceEXT ||
  46. vkCreateMetalSurfaceEXT(*instance, &macos_ci, nullptr, &unsafe_surface) != VK_SUCCESS) {
  47. LOG_ERROR(Render_Vulkan, "Failed to initialize Metal surface");
  48. throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
  49. }
  50. }
  51. #elif defined(__ANDROID__)
  52. if (window_info.type == Core::Frontend::WindowSystemType::Android) {
  53. const VkAndroidSurfaceCreateInfoKHR android_ci{
  54. VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR, nullptr, 0,
  55. reinterpret_cast<ANativeWindow*>(window_info.render_surface)};
  56. const auto vkCreateAndroidSurfaceKHR = reinterpret_cast<PFN_vkCreateAndroidSurfaceKHR>(
  57. dld.vkGetInstanceProcAddr(*instance, "vkCreateAndroidSurfaceKHR"));
  58. if (!vkCreateAndroidSurfaceKHR ||
  59. vkCreateAndroidSurfaceKHR(*instance, &android_ci, nullptr, &unsafe_surface) !=
  60. VK_SUCCESS) {
  61. LOG_ERROR(Render_Vulkan, "Failed to initialize Android surface");
  62. throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
  63. }
  64. }
  65. #else
  66. if (window_info.type == Core::Frontend::WindowSystemType::X11) {
  67. const VkXlibSurfaceCreateInfoKHR xlib_ci{
  68. VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, nullptr, 0,
  69. static_cast<Display*>(window_info.display_connection),
  70. reinterpret_cast<Window>(window_info.render_surface)};
  71. const auto vkCreateXlibSurfaceKHR = reinterpret_cast<PFN_vkCreateXlibSurfaceKHR>(
  72. dld.vkGetInstanceProcAddr(*instance, "vkCreateXlibSurfaceKHR"));
  73. if (!vkCreateXlibSurfaceKHR ||
  74. vkCreateXlibSurfaceKHR(*instance, &xlib_ci, nullptr, &unsafe_surface) != VK_SUCCESS) {
  75. LOG_ERROR(Render_Vulkan, "Failed to initialize Xlib surface");
  76. throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
  77. }
  78. }
  79. if (window_info.type == Core::Frontend::WindowSystemType::Wayland) {
  80. const VkWaylandSurfaceCreateInfoKHR wayland_ci{
  81. VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, nullptr, 0,
  82. static_cast<wl_display*>(window_info.display_connection),
  83. static_cast<wl_surface*>(window_info.render_surface)};
  84. const auto vkCreateWaylandSurfaceKHR = reinterpret_cast<PFN_vkCreateWaylandSurfaceKHR>(
  85. dld.vkGetInstanceProcAddr(*instance, "vkCreateWaylandSurfaceKHR"));
  86. if (!vkCreateWaylandSurfaceKHR ||
  87. vkCreateWaylandSurfaceKHR(*instance, &wayland_ci, nullptr, &unsafe_surface) !=
  88. VK_SUCCESS) {
  89. LOG_ERROR(Render_Vulkan, "Failed to initialize Wayland surface");
  90. throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
  91. }
  92. }
  93. #endif
  94. if (!unsafe_surface) {
  95. LOG_ERROR(Render_Vulkan, "Presentation not supported on this platform");
  96. throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
  97. }
  98. return vk::SurfaceKHR(unsafe_surface, *instance, dld);
  99. }
  100. } // namespace Vulkan