Basic support for Vulkan Portability on OSX

This commit is contained in:
Dzmitry Malyshau 2018-08-17 21:13:25 -04:00 committed by kd-11
parent eaf20295ac
commit c452b43ebc
8 changed files with 90 additions and 29 deletions

View file

@ -73,7 +73,11 @@ using ulong = unsigned long;
using ullong = unsigned long long; using ullong = unsigned long long;
using llong = long long; using llong = long long;
#if __APPLE__
using uptr = std::uint64_t;
#else
using uptr = std::uintptr_t; using uptr = std::uintptr_t;
#endif
using u8 = std::uint8_t; using u8 = std::uint8_t;
using u16 = std::uint16_t; using u16 = std::uint16_t;

View file

@ -256,10 +256,11 @@ if(USE_LIBEVDEV)
endif() endif()
endif() endif()
option(USE_VULKAN "Vulkan render backend" ON) option(USE_VULKAN "Vulkan render backend" ON)
if(NOT APPLE AND USE_VULKAN) if(USE_VULKAN)
find_package(Vulkan) find_package(Vulkan)
if(VULKAN_FOUND) if(VULKAN_FOUND)
add_definitions(-DHAVE_VULKAN) add_definitions(-DHAVE_VULKAN)
include_directories("${Vulkan_INCLUDE_DIRS}")
else() else()
message("WARNING! USE_VULKAN was enabled, but libvulkan was not found. RPCS3 will be compiled without Vulkan support.") message("WARNING! USE_VULKAN was enabled, but libvulkan was not found. RPCS3 will be compiled without Vulkan support.")
endif() endif()
@ -388,7 +389,7 @@ if(NOT MSVC)
target_link_libraries(rpcs3 Threads::Threads) target_link_libraries(rpcs3 Threads::Threads)
endif() endif()
if(UNIX) if(NOT APPLE AND UNIX)
find_package(X11 REQUIRED) find_package(X11 REQUIRED)
target_include_directories(rpcs3 PUBLIC ${X11_INCLUDE_DIR}) target_include_directories(rpcs3 PUBLIC ${X11_INCLUDE_DIR})
target_link_libraries(rpcs3 ${X11_LIBRARIES}) target_link_libraries(rpcs3 ${X11_LIBRARIES})
@ -438,7 +439,7 @@ else()
if(CMAKE_SYSTEM MATCHES "Linux") if(CMAKE_SYSTEM MATCHES "Linux")
target_link_libraries(rpcs3 "${RPCS3_SRC_DIR}/../3rdparty/discord-rpc/lib/libdiscord-rpc-linux.a") target_link_libraries(rpcs3 "${RPCS3_SRC_DIR}/../3rdparty/discord-rpc/lib/libdiscord-rpc-linux.a")
elseif(APPLE) elseif(APPLE)
target_link_libraries(rpcs3 "${RPCS3_SRC_DIR}/../3rdparty/discord-rpc/lib/libdiscord-rpc-mac.a") target_link_libraries(rpcs3 "${RPCS3_SRC_DIR}/../3rdparty/discord-rpc/lib/libdiscord-rpc-mac.a" objc "-framework Foundation" "-framework CoreServices")
endif() endif()
endif() endif()

View file

@ -5,6 +5,8 @@
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
#elif defined(__APPLE__)
// nothing
#else #else
// Cannot include Xlib.h before Qt5 // Cannot include Xlib.h before Qt5
// and we don't need all of Xlib anyway // and we don't need all of Xlib anyway
@ -49,6 +51,8 @@ using draw_context_t = void*;
#ifdef _WIN32 #ifdef _WIN32
using display_handle_t = HWND; using display_handle_t = HWND;
#elif defined(__APPLE__)
using display_handle_t = void*; // NSView
#else #else
using display_handle_t = std::variant< using display_handle_t = std::variant<
std::pair<Display*, Window> std::pair<Display*, Window>

View file

@ -516,7 +516,7 @@ VKGSRender::VKGSRender() : GSRender()
display_handle_t display = m_frame->handle(); display_handle_t display = m_frame->handle();
#ifndef _WIN32 #if !defined(_WIN32) && !defined(__APPLE__)
display.match([this](std::pair<Display*, Window> p) { m_display_handle = p.first; XFlush(m_display_handle); }, [](auto _) {}); display.match([this](std::pair<Display*, Window> p) { m_display_handle = p.first; XFlush(m_display_handle); }, [](auto _) {});
#endif #endif
@ -776,7 +776,7 @@ VKGSRender::~VKGSRender()
m_swapchain->destroy(); m_swapchain->destroy();
m_thread_context.close(); m_thread_context.close();
#if !defined(_WIN32) && defined(HAVE_VULKAN) #if !defined(_WIN32) && !defined(__APPLE__) && defined(HAVE_VULKAN)
if (m_display_handle) if (m_display_handle)
XCloseDisplay(m_display_handle); XCloseDisplay(m_display_handle);
#endif #endif

View file

@ -375,7 +375,7 @@ private:
//Vertex layout //Vertex layout
rsx::vertex_input_layout m_vertex_layout; rsx::vertex_input_layout m_vertex_layout;
#if !defined(_WIN32) && defined(HAVE_VULKAN) #if !defined(_WIN32) && !defined(__APPLE__) && defined(HAVE_VULKAN)
Display *m_display_handle = nullptr; Display *m_display_handle = nullptr;
#endif #endif

View file

@ -9,6 +9,10 @@
#include <memory> #include <memory>
#include <unordered_map> #include <unordered_map>
#if !defined(_WIN32) && !defined(__APPLE__)
#include <X11/Xutil.h>
#endif
#include "Utilities/variant.hpp" #include "Utilities/variant.hpp"
#include "Emu/RSX/GSRender.h" #include "Emu/RSX/GSRender.h"
#include "Emu/System.h" #include "Emu/System.h"
@ -21,10 +25,6 @@
#include "3rdparty/GPUOpen/include/vk_mem_alloc.h" #include "3rdparty/GPUOpen/include/vk_mem_alloc.h"
#ifndef _WIN32
#include <X11/Xutil.h>
#endif
#ifdef __APPLE__ #ifdef __APPLE__
#define VK_DISABLE_COMPONENT_SWIZZLE 1 #define VK_DISABLE_COMPONENT_SWIZZLE 1
#else #else
@ -1502,6 +1502,52 @@ public:
src.first = false; src.first = false;
return VK_SUCCESS; return VK_SUCCESS;
} }
#elif defined(__APPLE__)
class swapchain_MacOS : public native_swapchain_base
{
void* nsView = NULL;
public:
swapchain_MacOS(physical_device &gpu, uint32_t _present_queue, uint32_t _graphics_queue, VkFormat format = VK_FORMAT_B8G8R8A8_UNORM)
: native_swapchain_base(gpu, _present_queue, _graphics_queue, format)
{}
~swapchain_MacOS(){}
bool init() override
{
//TODO: get from `nsView`
m_width = 0;
m_height = 0;
if (m_width == 0 || m_height == 0)
{
LOG_ERROR(RSX, "Invalid window dimensions %d x %d", m_width, m_height);
return false;
}
init_swapchain_images(dev, 3);
return true;
}
void create(display_handle_t& window_handle) override
{
nsView = window_handle;
}
void destroy(bool full=true) override
{
swapchain_images.clear();
if (full)
dev.destroy();
}
VkResult present(u32 index) override
{
fmt::throw_exception("Native macOS swapchain is not implemented yet!");
}
#else #else
class swapchain_X11 : public native_swapchain_base class swapchain_X11 : public native_swapchain_base
@ -1991,15 +2037,20 @@ public:
std::vector<const char *> extensions; std::vector<const char *> extensions;
std::vector<const char *> layers; std::vector<const char *> layers;
#ifndef __APPLE__
if (!fast) if (!fast)
{ {
supported_extensions support;
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME); extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
if (support.is_supported(VK_EXT_DEBUG_REPORT_EXTENSION_NAME))
{
extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
}
#ifdef _WIN32 #ifdef _WIN32
extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
#elif defined(__APPLE__)
extensions.push_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME);
#else #else
supported_extensions support;
bool found_surface_ext = false; bool found_surface_ext = false;
if (support.is_supported(VK_KHR_XLIB_SURFACE_EXTENSION_NAME)) if (support.is_supported(VK_KHR_XLIB_SURFACE_EXTENSION_NAME))
{ {
@ -2018,11 +2069,10 @@ public:
LOG_ERROR(RSX, "Could not find a supported Vulkan surface extension"); LOG_ERROR(RSX, "Could not find a supported Vulkan surface extension");
return 0; return 0;
} }
#endif //(WIN32) #endif //(WIN32, __APPLE__)
if (g_cfg.video.debug_output) if (g_cfg.video.debug_output)
layers.push_back("VK_LAYER_LUNARG_standard_validation"); layers.push_back("VK_LAYER_LUNARG_standard_validation");
} }
#endif //(!APPLE)
VkInstanceCreateInfo instance_info = {}; VkInstanceCreateInfo instance_info = {};
instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
@ -2095,6 +2145,7 @@ public:
swapchain_base* createSwapChain(display_handle_t window_handle, vk::physical_device &dev) swapchain_base* createSwapChain(display_handle_t window_handle, vk::physical_device &dev)
{ {
VkSurfaceKHR surface;
#ifdef _WIN32 #ifdef _WIN32
using swapchain_NATIVE = swapchain_WIN32; using swapchain_NATIVE = swapchain_WIN32;
HINSTANCE hInstance = NULL; HINSTANCE hInstance = NULL;
@ -2104,16 +2155,17 @@ public:
createInfo.hinstance = hInstance; createInfo.hinstance = hInstance;
createInfo.hwnd = window_handle; createInfo.hwnd = window_handle;
VkSurfaceKHR surface;
CHECK_RESULT(vkCreateWin32SurfaceKHR(m_instance, &createInfo, NULL, &surface)); CHECK_RESULT(vkCreateWin32SurfaceKHR(m_instance, &createInfo, NULL, &surface));
#elif defined(__APPLE__) #elif defined(__APPLE__)
using swapchain_NATIVE = swapchain_X11; using swapchain_NATIVE = swapchain_MacOS;
VkSurfaceKHR surface; VkMacOSSurfaceCreateInfoMVK createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
createInfo.pView = window_handle;
CHECK_RESULT(vkCreateMacOSSurfaceMVK(m_instance, &createInfo, NULL, &surface));
#else #else
using swapchain_NATIVE = swapchain_X11; using swapchain_NATIVE = swapchain_X11;
VkSurfaceKHR surface;
window_handle.match( window_handle.match(
[&](std::pair<Display*, Window> p) [&](std::pair<Display*, Window> p)
@ -2141,7 +2193,6 @@ public:
std::vector<VkBool32> supportsPresent(device_queues, VK_FALSE); std::vector<VkBool32> supportsPresent(device_queues, VK_FALSE);
bool present_possible = false; bool present_possible = false;
#ifndef __APPLE__
for (u32 index = 0; index < device_queues; index++) for (u32 index = 0; index < device_queues; index++)
{ {
vkGetPhysicalDeviceSurfaceSupportKHR(dev, index, surface, &supportsPresent[index]); vkGetPhysicalDeviceSurfaceSupportKHR(dev, index, surface, &supportsPresent[index]);
@ -2160,7 +2211,6 @@ public:
{ {
LOG_ERROR(RSX, "It is not possible for the currently selected GPU to present to the window (Likely caused by NVIDIA driver running the current display)"); LOG_ERROR(RSX, "It is not possible for the currently selected GPU to present to the window (Likely caused by NVIDIA driver running the current display)");
} }
#endif
// Search for a graphics and a present queue in the array of queue // Search for a graphics and a present queue in the array of queue
// families, try to find one that supports both // families, try to find one that supports both
@ -2219,10 +2269,6 @@ public:
return swapchain; return swapchain;
} }
#ifdef __APPLE__
fmt::throw_exception("Unreachable" HERE);
#endif
// Get the list of VkFormat's that are supported: // Get the list of VkFormat's that are supported:
uint32_t formatCount; uint32_t formatCount;
CHECK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(dev, surface, &formatCount, nullptr)); CHECK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(dev, surface, &formatCount, nullptr));

View file

@ -2,7 +2,9 @@
#ifdef _WIN32 #ifdef _WIN32
#define VK_USE_PLATFORM_WIN32_KHR #define VK_USE_PLATFORM_WIN32_KHR
#elif !defined __APPLE__ #elif defined(__APPLE__)
#define VK_USE_PLATFORM_MACOS_MVK
#else
#define VK_USE_PLATFORM_XLIB_KHR #define VK_USE_PLATFORM_XLIB_KHR
#endif #endif

View file

@ -13,6 +13,8 @@
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
#elif defined(__APPLE__)
//nothing
#else #else
#ifdef VK_USE_PLATFORM_WAYLAND_KHR #ifdef VK_USE_PLATFORM_WAYLAND_KHR
#include <QGuiApplication> #include <QGuiApplication>
@ -200,6 +202,8 @@ display_handle_t gs_frame::handle() const
{ {
#ifdef _WIN32 #ifdef _WIN32
return (HWND) this->winId(); return (HWND) this->winId();
#elif defined(__APPLE__)
return (void*) this->winId(); //NSView
#else #else
#ifdef VK_USE_PLATFORM_WAYLAND_KHR #ifdef VK_USE_PLATFORM_WAYLAND_KHR
QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface(); QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface();
@ -238,7 +242,7 @@ void gs_frame::delete_context(draw_context_t ctx)
int gs_frame::client_width() int gs_frame::client_width()
{ {
#ifdef _WIN32 #if defined(_WIN32) || defined(__APPLE__)
return size().width(); return size().width();
#else #else
return size().width() * devicePixelRatio(); return size().width() * devicePixelRatio();
@ -247,7 +251,7 @@ int gs_frame::client_width()
int gs_frame::client_height() int gs_frame::client_height()
{ {
#ifdef _WIN32 #if defined(_WIN32) || defined(__APPLE__)
return size().height(); return size().height();
#else #else
return size().height() * devicePixelRatio(); return size().height() * devicePixelRatio();