Browse Source
Merge pull request #5230 from ReinUsesLisp/vulkan-common
Merge pull request #5230 from ReinUsesLisp/vulkan-common
vulkan_common: Move reusable Vulkan abstractions to a separate directorynce_cpp
committed by
GitHub
60 changed files with 574 additions and 486 deletions
-
12src/video_core/CMakeLists.txt
-
2src/video_core/renderer_vulkan/blit_image.cpp
-
2src/video_core/renderer_vulkan/blit_image.h
-
2src/video_core/renderer_vulkan/maxwell_to_vk.cpp
-
2src/video_core/renderer_vulkan/maxwell_to_vk.h
-
306src/video_core/renderer_vulkan/renderer_vulkan.cpp
-
11src/video_core/renderer_vulkan/renderer_vulkan.h
-
2src/video_core/renderer_vulkan/vk_blit_screen.cpp
-
2src/video_core/renderer_vulkan/vk_blit_screen.h
-
2src/video_core/renderer_vulkan/vk_buffer_cache.cpp
-
2src/video_core/renderer_vulkan/vk_buffer_cache.h
-
2src/video_core/renderer_vulkan/vk_command_pool.cpp
-
2src/video_core/renderer_vulkan/vk_command_pool.h
-
2src/video_core/renderer_vulkan/vk_compute_pass.cpp
-
2src/video_core/renderer_vulkan/vk_compute_pass.h
-
2src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
-
2src/video_core/renderer_vulkan/vk_compute_pipeline.h
-
2src/video_core/renderer_vulkan/vk_descriptor_pool.cpp
-
2src/video_core/renderer_vulkan/vk_descriptor_pool.h
-
146src/video_core/renderer_vulkan/vk_device.cpp
-
18src/video_core/renderer_vulkan/vk_device.h
-
2src/video_core/renderer_vulkan/vk_fence_manager.cpp
-
2src/video_core/renderer_vulkan/vk_fence_manager.h
-
2src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
-
2src/video_core/renderer_vulkan/vk_graphics_pipeline.h
-
2src/video_core/renderer_vulkan/vk_master_semaphore.cpp
-
2src/video_core/renderer_vulkan/vk_master_semaphore.h
-
2src/video_core/renderer_vulkan/vk_memory_manager.cpp
-
2src/video_core/renderer_vulkan/vk_memory_manager.h
-
2src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
-
2src/video_core/renderer_vulkan/vk_pipeline_cache.h
-
2src/video_core/renderer_vulkan/vk_query_cache.cpp
-
2src/video_core/renderer_vulkan/vk_query_cache.h
-
2src/video_core/renderer_vulkan/vk_rasterizer.cpp
-
2src/video_core/renderer_vulkan/vk_rasterizer.h
-
2src/video_core/renderer_vulkan/vk_scheduler.cpp
-
2src/video_core/renderer_vulkan/vk_scheduler.h
-
11src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
-
2src/video_core/renderer_vulkan/vk_shader_util.cpp
-
2src/video_core/renderer_vulkan/vk_shader_util.h
-
2src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp
-
2src/video_core/renderer_vulkan/vk_staging_buffer_pool.h
-
2src/video_core/renderer_vulkan/vk_stream_buffer.cpp
-
2src/video_core/renderer_vulkan/vk_stream_buffer.h
-
2src/video_core/renderer_vulkan/vk_swapchain.cpp
-
2src/video_core/renderer_vulkan/vk_swapchain.h
-
2src/video_core/renderer_vulkan/vk_texture_cache.cpp
-
2src/video_core/renderer_vulkan/vk_texture_cache.h
-
2src/video_core/renderer_vulkan/vk_update_descriptor.cpp
-
2src/video_core/renderer_vulkan/vk_update_descriptor.h
-
45src/video_core/vulkan_common/vulkan_debug_callback.cpp
-
11src/video_core/vulkan_common/vulkan_debug_callback.h
-
151src/video_core/vulkan_common/vulkan_instance.cpp
-
32src/video_core/vulkan_common/vulkan_instance.h
-
36src/video_core/vulkan_common/vulkan_library.cpp
-
13src/video_core/vulkan_common/vulkan_library.h
-
81src/video_core/vulkan_common/vulkan_surface.cpp
-
18src/video_core/vulkan_common/vulkan_surface.h
-
58src/video_core/vulkan_common/vulkan_wrapper.cpp
-
23src/video_core/vulkan_common/vulkan_wrapper.h
@ -0,0 +1,45 @@ |
|||||
|
// Copyright 2020 yuzu Emulator Project
|
||||
|
// Licensed under GPLv2 or any later version
|
||||
|
// Refer to the license.txt file included.
|
||||
|
|
||||
|
#include <string_view>
|
||||
|
#include "common/logging/log.h"
|
||||
|
#include "video_core/vulkan_common/vulkan_debug_callback.h"
|
||||
|
|
||||
|
namespace Vulkan { |
||||
|
namespace { |
||||
|
VkBool32 Callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity, |
||||
|
VkDebugUtilsMessageTypeFlagsEXT type, |
||||
|
const VkDebugUtilsMessengerCallbackDataEXT* data, |
||||
|
[[maybe_unused]] void* user_data) { |
||||
|
const std::string_view message{data->pMessage}; |
||||
|
if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) { |
||||
|
LOG_CRITICAL(Render_Vulkan, "{}", message); |
||||
|
} else if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { |
||||
|
LOG_WARNING(Render_Vulkan, "{}", message); |
||||
|
} else if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) { |
||||
|
LOG_INFO(Render_Vulkan, "{}", message); |
||||
|
} else if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) { |
||||
|
LOG_DEBUG(Render_Vulkan, "{}", message); |
||||
|
} |
||||
|
return VK_FALSE; |
||||
|
} |
||||
|
} // Anonymous namespace
|
||||
|
|
||||
|
vk::DebugUtilsMessenger CreateDebugCallback(const vk::Instance& instance) { |
||||
|
return instance.CreateDebugUtilsMessenger(VkDebugUtilsMessengerCreateInfoEXT{ |
||||
|
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, |
||||
|
.pNext = nullptr, |
||||
|
.flags = 0, |
||||
|
.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | |
||||
|
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | |
||||
|
VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT | |
||||
|
VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, |
||||
|
.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | |
||||
|
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | |
||||
|
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, |
||||
|
.pfnUserCallback = Callback, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
} // namespace Vulkan
|
||||
@ -0,0 +1,11 @@ |
|||||
|
// Copyright 2020 yuzu Emulator Project |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#include "video_core/vulkan_common/vulkan_wrapper.h" |
||||
|
|
||||
|
namespace Vulkan { |
||||
|
|
||||
|
vk::DebugUtilsMessenger CreateDebugCallback(const vk::Instance& instance); |
||||
|
|
||||
|
} // namespace Vulkan |
||||
@ -0,0 +1,151 @@ |
|||||
|
// Copyright 2020 yuzu Emulator Project
|
||||
|
// Licensed under GPLv2 or any later version
|
||||
|
// Refer to the license.txt file included.
|
||||
|
|
||||
|
#include <algorithm>
|
||||
|
#include <optional>
|
||||
|
#include <span>
|
||||
|
#include <utility>
|
||||
|
#include <vector>
|
||||
|
|
||||
|
#include "common/common_types.h"
|
||||
|
#include "common/dynamic_library.h"
|
||||
|
#include "common/logging/log.h"
|
||||
|
#include "core/frontend/emu_window.h"
|
||||
|
#include "video_core/vulkan_common/vulkan_instance.h"
|
||||
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||
|
|
||||
|
// Include these late to avoid polluting previous headers
|
||||
|
#ifdef _WIN32
|
||||
|
#include <windows.h>
|
||||
|
// ensure include order
|
||||
|
#include <vulkan/vulkan_win32.h>
|
||||
|
#endif
|
||||
|
|
||||
|
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
|
#include <X11/Xlib.h>
|
||||
|
#include <vulkan/vulkan_wayland.h>
|
||||
|
#include <vulkan/vulkan_xlib.h>
|
||||
|
#endif
|
||||
|
|
||||
|
namespace Vulkan { |
||||
|
namespace { |
||||
|
[[nodiscard]] std::vector<const char*> RequiredExtensions( |
||||
|
Core::Frontend::WindowSystemType window_type, bool enable_debug_utils) { |
||||
|
std::vector<const char*> extensions; |
||||
|
extensions.reserve(6); |
||||
|
switch (window_type) { |
||||
|
case Core::Frontend::WindowSystemType::Headless: |
||||
|
break; |
||||
|
#ifdef _WIN32
|
||||
|
case Core::Frontend::WindowSystemType::Windows: |
||||
|
extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); |
||||
|
break; |
||||
|
#endif
|
||||
|
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
|
case Core::Frontend::WindowSystemType::X11: |
||||
|
extensions.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); |
||||
|
break; |
||||
|
case Core::Frontend::WindowSystemType::Wayland: |
||||
|
extensions.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME); |
||||
|
break; |
||||
|
#endif
|
||||
|
default: |
||||
|
LOG_ERROR(Render_Vulkan, "Presentation not supported on this platform"); |
||||
|
break; |
||||
|
} |
||||
|
if (window_type != Core::Frontend::WindowSystemType::Headless) { |
||||
|
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); |
||||
|
} |
||||
|
if (enable_debug_utils) { |
||||
|
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); |
||||
|
} |
||||
|
extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
||||
|
return extensions; |
||||
|
} |
||||
|
|
||||
|
[[nodiscard]] bool AreExtensionsSupported(const vk::InstanceDispatch& dld, |
||||
|
std::span<const char* const> extensions) { |
||||
|
const std::optional properties = vk::EnumerateInstanceExtensionProperties(dld); |
||||
|
if (!properties) { |
||||
|
LOG_ERROR(Render_Vulkan, "Failed to query extension properties"); |
||||
|
return false; |
||||
|
} |
||||
|
for (const char* extension : extensions) { |
||||
|
const auto it = std::ranges::find_if(*properties, [extension](const auto& prop) { |
||||
|
return std::strcmp(extension, prop.extensionName) == 0; |
||||
|
}); |
||||
|
if (it == properties->end()) { |
||||
|
LOG_ERROR(Render_Vulkan, "Required instance extension {} is not available", extension); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
[[nodiscard]] std::vector<const char*> Layers(bool enable_layers) { |
||||
|
std::vector<const char*> layers; |
||||
|
if (enable_layers) { |
||||
|
layers.push_back("VK_LAYER_KHRONOS_validation"); |
||||
|
} |
||||
|
return layers; |
||||
|
} |
||||
|
|
||||
|
void RemoveUnavailableLayers(const vk::InstanceDispatch& dld, std::vector<const char*>& layers) { |
||||
|
const std::optional layer_properties = vk::EnumerateInstanceLayerProperties(dld); |
||||
|
if (!layer_properties) { |
||||
|
LOG_ERROR(Render_Vulkan, "Failed to query layer properties, disabling layers"); |
||||
|
layers.clear(); |
||||
|
} |
||||
|
std::erase_if(layers, [&layer_properties](const char* layer) { |
||||
|
const auto comp = [layer](const VkLayerProperties& layer_property) { |
||||
|
return std::strcmp(layer, layer_property.layerName) == 0; |
||||
|
}; |
||||
|
const auto it = std::ranges::find_if(*layer_properties, comp); |
||||
|
if (it == layer_properties->end()) { |
||||
|
LOG_ERROR(Render_Vulkan, "Layer {} not available, removing it", layer); |
||||
|
return true; |
||||
|
} |
||||
|
return false; |
||||
|
}); |
||||
|
} |
||||
|
} // Anonymous namespace
|
||||
|
|
||||
|
vk::Instance CreateInstance(const Common::DynamicLibrary& library, vk::InstanceDispatch& dld, |
||||
|
u32 required_version, Core::Frontend::WindowSystemType window_type, |
||||
|
bool enable_debug_utils, bool enable_layers) { |
||||
|
if (!library.IsOpen()) { |
||||
|
LOG_ERROR(Render_Vulkan, "Vulkan library not available"); |
||||
|
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
||||
|
} |
||||
|
if (!library.GetSymbol("vkGetInstanceProcAddr", &dld.vkGetInstanceProcAddr)) { |
||||
|
LOG_ERROR(Render_Vulkan, "vkGetInstanceProcAddr not present in Vulkan"); |
||||
|
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
||||
|
} |
||||
|
if (!vk::Load(dld)) { |
||||
|
LOG_ERROR(Render_Vulkan, "Failed to load Vulkan function pointers"); |
||||
|
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
||||
|
} |
||||
|
const std::vector<const char*> extensions = RequiredExtensions(window_type, enable_debug_utils); |
||||
|
if (!AreExtensionsSupported(dld, extensions)) { |
||||
|
throw vk::Exception(VK_ERROR_EXTENSION_NOT_PRESENT); |
||||
|
} |
||||
|
std::vector<const char*> layers = Layers(enable_layers); |
||||
|
RemoveUnavailableLayers(dld, layers); |
||||
|
|
||||
|
const u32 available_version = vk::AvailableVersion(dld); |
||||
|
if (available_version < required_version) { |
||||
|
LOG_ERROR(Render_Vulkan, "Vulkan {}.{} is not supported, {}.{} is required", |
||||
|
VK_VERSION_MAJOR(available_version), VK_VERSION_MINOR(available_version), |
||||
|
VK_VERSION_MAJOR(required_version), VK_VERSION_MINOR(required_version)); |
||||
|
throw vk::Exception(VK_ERROR_INCOMPATIBLE_DRIVER); |
||||
|
} |
||||
|
vk::Instance instance = vk::Instance::Create(required_version, layers, extensions, dld); |
||||
|
if (!vk::Load(*instance, dld)) { |
||||
|
LOG_ERROR(Render_Vulkan, "Failed to load Vulkan instance function pointers"); |
||||
|
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
||||
|
} |
||||
|
return instance; |
||||
|
} |
||||
|
|
||||
|
} // namespace Vulkan
|
||||
@ -0,0 +1,32 @@ |
|||||
|
// Copyright 2020 yuzu Emulator Project |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include "common/common_types.h" |
||||
|
#include "common/dynamic_library.h" |
||||
|
#include "core/frontend/emu_window.h" |
||||
|
#include "video_core/vulkan_common/vulkan_wrapper.h" |
||||
|
|
||||
|
namespace Vulkan { |
||||
|
|
||||
|
/** |
||||
|
* Create a Vulkan instance |
||||
|
* |
||||
|
* @param library Dynamic library to load the Vulkan instance from |
||||
|
* @param dld Dispatch table to load function pointers into |
||||
|
* @param required_version Required Vulkan version (for example, VK_API_VERSION_1_1) |
||||
|
* @param window_type Window system type's enabled extension |
||||
|
* @param enable_debug_utils Whether to enable VK_EXT_debug_utils_extension_name or not |
||||
|
* @param enable_layers Whether to enable Vulkan validation layers or not |
||||
|
* |
||||
|
* @return A new Vulkan instance |
||||
|
* @throw vk::Exception on failure |
||||
|
*/ |
||||
|
[[nodiscard]] vk::Instance CreateInstance( |
||||
|
const Common::DynamicLibrary& library, vk::InstanceDispatch& dld, u32 required_version, |
||||
|
Core::Frontend::WindowSystemType window_type = Core::Frontend::WindowSystemType::Headless, |
||||
|
bool enable_debug_utils = false, bool enable_layers = false); |
||||
|
|
||||
|
} // namespace Vulkan |
||||
@ -0,0 +1,36 @@ |
|||||
|
// Copyright 2020 yuzu Emulator Project
|
||||
|
// Licensed under GPLv2 or any later version
|
||||
|
// Refer to the license.txt file included.
|
||||
|
|
||||
|
#include <cstdlib>
|
||||
|
#include <string>
|
||||
|
|
||||
|
#include "common/dynamic_library.h"
|
||||
|
#include "common/file_util.h"
|
||||
|
#include "video_core/vulkan_common/vulkan_library.h"
|
||||
|
|
||||
|
namespace Vulkan { |
||||
|
|
||||
|
Common::DynamicLibrary OpenLibrary() { |
||||
|
Common::DynamicLibrary library; |
||||
|
#ifdef __APPLE__
|
||||
|
// Check if a path to a specific Vulkan library has been specified.
|
||||
|
char* const libvulkan_env = std::getenv("LIBVULKAN_PATH"); |
||||
|
if (!libvulkan_env || !library.Open(libvulkan_env)) { |
||||
|
// Use the libvulkan.dylib from the application bundle.
|
||||
|
const std::string filename = |
||||
|
Common::FS::GetBundleDirectory() + "/Contents/Frameworks/libvulkan.dylib"; |
||||
|
library.Open(filename.c_str()); |
||||
|
} |
||||
|
#else
|
||||
|
std::string filename = Common::DynamicLibrary::GetVersionedFilename("vulkan", 1); |
||||
|
if (!library.Open(filename.c_str())) { |
||||
|
// Android devices may not have libvulkan.so.1, only libvulkan.so.
|
||||
|
filename = Common::DynamicLibrary::GetVersionedFilename("vulkan"); |
||||
|
void(library.Open(filename.c_str())); |
||||
|
} |
||||
|
#endif
|
||||
|
return library; |
||||
|
} |
||||
|
|
||||
|
} // namespace Vulkan
|
||||
@ -0,0 +1,13 @@ |
|||||
|
// Copyright 2020 yuzu Emulator Project |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include "common/dynamic_library.h" |
||||
|
|
||||
|
namespace Vulkan { |
||||
|
|
||||
|
Common::DynamicLibrary OpenLibrary(); |
||||
|
|
||||
|
} // namespace Vulkan |
||||
@ -0,0 +1,81 @@ |
|||||
|
// Copyright 2020 yuzu Emulator Project
|
||||
|
// Licensed under GPLv2 or any later version
|
||||
|
// Refer to the license.txt file included.
|
||||
|
|
||||
|
#include "common/logging/log.h"
|
||||
|
#include "core/frontend/emu_window.h"
|
||||
|
#include "video_core/vulkan_common/vulkan_surface.h"
|
||||
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||
|
|
||||
|
// Include these late to avoid polluting previous headers
|
||||
|
#ifdef _WIN32
|
||||
|
#include <windows.h>
|
||||
|
// ensure include order
|
||||
|
#include <vulkan/vulkan_win32.h>
|
||||
|
#endif
|
||||
|
|
||||
|
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
|
#include <X11/Xlib.h>
|
||||
|
#include <vulkan/vulkan_wayland.h>
|
||||
|
#include <vulkan/vulkan_xlib.h>
|
||||
|
#endif
|
||||
|
|
||||
|
namespace Vulkan { |
||||
|
|
||||
|
vk::SurfaceKHR CreateSurface(const vk::Instance& instance, |
||||
|
const Core::Frontend::EmuWindow& emu_window) { |
||||
|
[[maybe_unused]] const vk::InstanceDispatch& dld = instance.Dispatch(); |
||||
|
[[maybe_unused]] const auto& window_info = emu_window.GetWindowInfo(); |
||||
|
VkSurfaceKHR unsafe_surface = nullptr; |
||||
|
|
||||
|
#ifdef _WIN32
|
||||
|
if (window_info.type == Core::Frontend::WindowSystemType::Windows) { |
||||
|
const HWND hWnd = static_cast<HWND>(window_info.render_surface); |
||||
|
const VkWin32SurfaceCreateInfoKHR win32_ci{VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, |
||||
|
nullptr, 0, nullptr, hWnd}; |
||||
|
const auto vkCreateWin32SurfaceKHR = reinterpret_cast<PFN_vkCreateWin32SurfaceKHR>( |
||||
|
dld.vkGetInstanceProcAddr(*instance, "vkCreateWin32SurfaceKHR")); |
||||
|
if (!vkCreateWin32SurfaceKHR || |
||||
|
vkCreateWin32SurfaceKHR(*instance, &win32_ci, nullptr, &unsafe_surface) != VK_SUCCESS) { |
||||
|
LOG_ERROR(Render_Vulkan, "Failed to initialize Win32 surface"); |
||||
|
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
||||
|
} |
||||
|
} |
||||
|
#endif
|
||||
|
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
|
if (window_info.type == Core::Frontend::WindowSystemType::X11) { |
||||
|
const VkXlibSurfaceCreateInfoKHR xlib_ci{ |
||||
|
VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, nullptr, 0, |
||||
|
static_cast<Display*>(window_info.display_connection), |
||||
|
reinterpret_cast<Window>(window_info.render_surface)}; |
||||
|
const auto vkCreateXlibSurfaceKHR = reinterpret_cast<PFN_vkCreateXlibSurfaceKHR>( |
||||
|
dld.vkGetInstanceProcAddr(*instance, "vkCreateXlibSurfaceKHR")); |
||||
|
if (!vkCreateXlibSurfaceKHR || |
||||
|
vkCreateXlibSurfaceKHR(*instance, &xlib_ci, nullptr, &unsafe_surface) != VK_SUCCESS) { |
||||
|
LOG_ERROR(Render_Vulkan, "Failed to initialize Xlib surface"); |
||||
|
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
||||
|
} |
||||
|
} |
||||
|
if (window_info.type == Core::Frontend::WindowSystemType::Wayland) { |
||||
|
const VkWaylandSurfaceCreateInfoKHR wayland_ci{ |
||||
|
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, nullptr, 0, |
||||
|
static_cast<wl_display*>(window_info.display_connection), |
||||
|
static_cast<wl_surface*>(window_info.render_surface)}; |
||||
|
const auto vkCreateWaylandSurfaceKHR = reinterpret_cast<PFN_vkCreateWaylandSurfaceKHR>( |
||||
|
dld.vkGetInstanceProcAddr(*instance, "vkCreateWaylandSurfaceKHR")); |
||||
|
if (!vkCreateWaylandSurfaceKHR || |
||||
|
vkCreateWaylandSurfaceKHR(*instance, &wayland_ci, nullptr, &unsafe_surface) != |
||||
|
VK_SUCCESS) { |
||||
|
LOG_ERROR(Render_Vulkan, "Failed to initialize Wayland surface"); |
||||
|
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
||||
|
} |
||||
|
} |
||||
|
#endif
|
||||
|
if (!unsafe_surface) { |
||||
|
LOG_ERROR(Render_Vulkan, "Presentation not supported on this platform"); |
||||
|
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
||||
|
} |
||||
|
return vk::SurfaceKHR(unsafe_surface, *instance, dld); |
||||
|
} |
||||
|
|
||||
|
} // namespace Vulkan
|
||||
@ -0,0 +1,18 @@ |
|||||
|
// Copyright 2020 yuzu Emulator Project |
||||
|
// Licensed under GPLv2 or any later version |
||||
|
// Refer to the license.txt file included. |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include "video_core/vulkan_common/vulkan_wrapper.h" |
||||
|
|
||||
|
namespace Core::Frontend { |
||||
|
class EmuWindow; |
||||
|
} |
||||
|
|
||||
|
namespace Vulkan { |
||||
|
|
||||
|
[[nodiscard]] vk::SurfaceKHR CreateSurface(const vk::Instance& instance, |
||||
|
const Core::Frontend::EmuWindow& emu_window); |
||||
|
|
||||
|
} // namespace Vulkan |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue