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 llong = long long;
#if __APPLE__
using uptr = std::uint64_t;
#else
using uptr = std::uintptr_t;
#endif
using u8 = std::uint8_t;
using u16 = std::uint16_t;

View File

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

View File

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

View File

@ -516,7 +516,7 @@ VKGSRender::VKGSRender() : GSRender()
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 _) {});
#endif
@ -776,7 +776,7 @@ VKGSRender::~VKGSRender()
m_swapchain->destroy();
m_thread_context.close();
#if !defined(_WIN32) && defined(HAVE_VULKAN)
#if !defined(_WIN32) && !defined(__APPLE__) && defined(HAVE_VULKAN)
if (m_display_handle)
XCloseDisplay(m_display_handle);
#endif
@ -3265,4 +3265,4 @@ void VKGSRender::discard_occlusion_query(rsx::reports::occlusion_query_info* que
bool VKGSRender::on_decompiler_task()
{
return m_prog_buffer->async_update(8, *m_device, pipeline_layout).first;
}
}

View File

@ -375,7 +375,7 @@ private:
//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;
#endif

View File

@ -9,6 +9,10 @@
#include <memory>
#include <unordered_map>
#if !defined(_WIN32) && !defined(__APPLE__)
#include <X11/Xutil.h>
#endif
#include "Utilities/variant.hpp"
#include "Emu/RSX/GSRender.h"
#include "Emu/System.h"
@ -21,10 +25,6 @@
#include "3rdparty/GPUOpen/include/vk_mem_alloc.h"
#ifndef _WIN32
#include <X11/Xutil.h>
#endif
#ifdef __APPLE__
#define VK_DISABLE_COMPONENT_SWIZZLE 1
#else
@ -1502,6 +1502,52 @@ public:
src.first = false;
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
class swapchain_X11 : public native_swapchain_base
@ -1991,15 +2037,20 @@ public:
std::vector<const char *> extensions;
std::vector<const char *> layers;
#ifndef __APPLE__
if (!fast)
{
supported_extensions support;
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
if (support.is_supported(VK_EXT_DEBUG_REPORT_EXTENSION_NAME))
{
extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
}
#ifdef _WIN32
extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
#elif defined(__APPLE__)
extensions.push_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME);
#else
supported_extensions support;
bool found_surface_ext = false;
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");
return 0;
}
#endif //(WIN32)
#endif //(WIN32, __APPLE__)
if (g_cfg.video.debug_output)
layers.push_back("VK_LAYER_LUNARG_standard_validation");
}
#endif //(!APPLE)
VkInstanceCreateInfo instance_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)
{
VkSurfaceKHR surface;
#ifdef _WIN32
using swapchain_NATIVE = swapchain_WIN32;
HINSTANCE hInstance = NULL;
@ -2104,16 +2155,17 @@ public:
createInfo.hinstance = hInstance;
createInfo.hwnd = window_handle;
VkSurfaceKHR surface;
CHECK_RESULT(vkCreateWin32SurfaceKHR(m_instance, &createInfo, NULL, &surface));
#elif defined(__APPLE__)
using swapchain_NATIVE = swapchain_X11;
VkSurfaceKHR surface;
using swapchain_NATIVE = swapchain_MacOS;
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
using swapchain_NATIVE = swapchain_X11;
VkSurfaceKHR surface;
window_handle.match(
[&](std::pair<Display*, Window> p)
@ -2141,7 +2193,6 @@ public:
std::vector<VkBool32> supportsPresent(device_queues, VK_FALSE);
bool present_possible = false;
#ifndef __APPLE__
for (u32 index = 0; index < device_queues; 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)");
}
#endif
// Search for a graphics and a present queue in the array of queue
// families, try to find one that supports both
@ -2219,10 +2269,6 @@ public:
return swapchain;
}
#ifdef __APPLE__
fmt::throw_exception("Unreachable" HERE);
#endif
// Get the list of VkFormat's that are supported:
uint32_t formatCount;
CHECK_RESULT(vkGetPhysicalDeviceSurfaceFormatsKHR(dev, surface, &formatCount, nullptr));

View File

@ -2,7 +2,9 @@
#ifdef _WIN32
#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
#endif

View File

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