Initial support for vulkan on macOS ( MoltenVK )

This commit is contained in:
李通洲 2020-01-19 17:34:21 +08:00
parent dd1de41db7
commit 7cd60549dd
No known key found for this signature in database
GPG Key ID: 185E60A519A7E290
11 changed files with 76 additions and 17 deletions

View File

@ -84,8 +84,8 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Android")
set(ANDROID ON)
endif()
# We only support Vulkan on Unix, Android and Windows.
if(ANDROID OR WIN32 OR (UNIX AND NOT APPLE AND NOT ARM_NO_VULKAN))
# We only support Vulkan on Unix, macOS (by MoltenVK), Android and Windows.
if(ANDROID OR WIN32 OR (UNIX AND NOT ARM_NO_VULKAN))
set(VULKAN ON)
endif()
@ -188,6 +188,7 @@ include(FindThreads)
if(APPLE)
find_library(COCOA_LIBRARY Cocoa)
find_library(QUARTZ_CORE_LIBRARY QuartzCore)
endif()
include_directories("${CMAKE_SOURCE_DIR}")
@ -828,8 +829,8 @@ elseif(TARGET SDL2::SDL2)
)
set(nativeExtraLibs ${nativeExtraLibs} SDL2::SDL2)
if(APPLE)
set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm)
set(nativeExtraLibs ${nativeExtraLibs} ${COCOA_LIBRARY})
set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm SDL/SDLCocoaMetalLayer.h SDL/SDLCocoaMetalLayer.mm)
set(nativeExtraLibs ${nativeExtraLibs} ${COCOA_LIBRARY} ${QUARTZ_CORE_LIBRARY})
elseif(USING_EGL)
set(nativeExtraLibs ${nativeExtraLibs} pthread)
endif()
@ -1955,7 +1956,7 @@ if(HEADLESS)
headless/SDLHeadlessHost.cpp
headless/SDLHeadlessHost.h
)
target_link_libraries(PPSSPPHeadless ${COCOA_LIBRARY} ${LinkCommon})
target_link_libraries(PPSSPPHeadless ${COCOA_LIBRARY} ${QUARTZ_CORE_LIBRARY} ${LinkCommon})
setup_target_project(PPSSPPHeadless headless)
endif()
@ -1970,7 +1971,7 @@ if(UNITTEST)
Core/MIPS/ARM/ArmRegCache.cpp
Core/MIPS/ARM/ArmRegCacheFPU.cpp
)
target_link_libraries(unitTest ${COCOA_LIBRARY} ${LinkCommon} Common)
target_link_libraries(unitTest ${COCOA_LIBRARY} ${QUARTZ_CORE_LIBRARY} ${LinkCommon} Common)
setup_target_project(unitTest unittest)
endif()

View File

@ -125,6 +125,11 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
instance_extensions_enabled_.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
}
#endif
#if defined(VK_USE_PLATFORM_METAL_EXT)
if (IsInstanceExtensionAvailable(VK_EXT_METAL_SURFACE_EXTENSION_NAME)) {
instance_extensions_enabled_.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME);
}
#endif
#endif
if (flags_ & VULKAN_FLAG_VALIDATE) {
@ -760,6 +765,16 @@ VkResult VulkanContext::ReinitSurface() {
return vkCreateAndroidSurfaceKHR(instance_, &android, nullptr, &surface_);
}
#endif
#if defined(VK_USE_PLATFORM_METAL_EXT)
case WINDOWSYSTEM_METAL_EXT:
{
VkMetalSurfaceCreateInfoEXT metal{ VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT };
metal.flags = 0;
metal.pLayer = winsysData1_;
metal.pNext = winsysData2_;
return vkCreateMetalSurfaceEXT(instance_, &metal, nullptr, &surface_);
}
#endif
#if defined(VK_USE_PLATFORM_XLIB_KHR)
case WINDOWSYSTEM_XLIB:
{
@ -968,10 +983,10 @@ bool VulkanContext::InitSwapchain() {
// Application must settle for fewer images than desired:
desiredNumberOfSwapChainImages = surfCapabilities_.maxImageCount;
}
// We mostly follow the practices from
// https://arm-software.github.io/vulkan_best_practice_for_mobile_developers/samples/surface_rotation/surface_rotation_tutorial.html
//
//
VkSurfaceTransformFlagBitsKHR preTransform;
std::string supportedTransforms = surface_transforms_to_string(surfCapabilities_.supportedTransforms);
std::string currentTransform = surface_transforms_to_string(surfCapabilities_.currentTransform);

View File

@ -34,6 +34,9 @@ enum WindowSystem {
#ifdef __ANDROID__
WINDOWSYSTEM_ANDROID,
#endif
#ifdef VK_USE_PLATFORM_METAL_EXT
WINDOWSYSTEM_METAL_EXT,
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR
WINDOWSYSTEM_XLIB,
#endif

View File

@ -176,6 +176,9 @@ PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR;
#elif defined(_WIN32)
PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR;
#endif
#if defined(VK_USE_PLATFORM_METAL_EXT)
PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT;
#endif
#if defined(VK_USE_PLATFORM_XLIB_KHR)
PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR;
#endif
@ -236,10 +239,14 @@ static const char *device_name_blacklist[] = {
};
static const char *so_names[] = {
#if defined(__APPLE__)
"libMoltenVK.dylib",
#else
"libvulkan.so",
#if !defined(__ANDROID__)
"libvulkan.so.1",
#endif
#endif
};
void VulkanSetAvailable(bool available) {
@ -310,6 +317,8 @@ bool VulkanMayBeAvailable() {
const char * const platformSurfaceExtension = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
#elif defined(__ANDROID__)
const char *platformSurfaceExtension = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
#elif defined(VK_USE_PLATFORM_METAL_EXT)
const char * const platformSurfaceExtension = VK_EXT_METAL_SURFACE_EXTENSION_NAME;
#else
const char *platformSurfaceExtension = 0;
#endif
@ -515,6 +524,8 @@ void VulkanLoadInstanceFunctions(VkInstance instance, const VulkanDeviceExtensio
LOAD_INSTANCE_FUNC(instance, vkCreateWin32SurfaceKHR);
#elif defined(__ANDROID__)
LOAD_INSTANCE_FUNC(instance, vkCreateAndroidSurfaceKHR);
#elif defined(VK_USE_PLATFORM_METAL_EXT)
LOAD_INSTANCE_FUNC(instance, vkCreateMetalSurfaceEXT);
#endif
#if defined(VK_USE_PLATFORM_XLIB_KHR)
LOAD_INSTANCE_FUNC(instance, vkCreateXlibSurfaceKHR);

View File

@ -25,6 +25,8 @@
#ifndef NOMINMAX
#define NOMINMAX
#endif
#elif defined(__APPLE__)
#define VK_USE_PLATFORM_METAL_EXT
#endif
#define VK_NO_PROTOTYPES
@ -173,6 +175,8 @@ extern PFN_vkCmdExecuteCommands vkCmdExecuteCommands;
extern PFN_vkCreateAndroidSurfaceKHR vkCreateAndroidSurfaceKHR;
#elif defined(_WIN32)
extern PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR;
#elif defined(VK_USE_PLATFORM_METAL_EXT)
extern PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT;
#endif
#if defined(VK_USE_PLATFORM_XLIB_KHR)
extern PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR;

5
SDL/SDLCocoaMetalLayer.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
extern "C" {
void *makeWindowMetalCompatible(void *window);
}

16
SDL/SDLCocoaMetalLayer.mm Normal file
View File

@ -0,0 +1,16 @@
#import <Cocoa/Cocoa.h>
#import <QuartzCore/CAMetalLayer.h>
#include "base/logging.h"
#include "SDLCocoaMetalLayer.h"
void *makeWindowMetalCompatible(void *window) {
NSView *view = ((NSWindow *)window).contentView;
assert([view isKindOfClass:[NSView class]]);
if (![view.layer isKindOfClass:[CAMetalLayer class]])
{
[view setLayer:[CAMetalLayer layer]];
}
return view.layer;
}

View File

@ -1,6 +1,4 @@
#if !defined(__APPLE__)
#include "SDL_syswm.h"
#endif
#include "SDL.h"
#include "thin3d/GLRenderManager.h"

View File

@ -35,9 +35,7 @@ SDLJoystick *joystick = NULL;
#include "thread/threadutil.h"
#include "math.h"
#if !defined(__APPLE__)
#include "SDL_syswm.h"
#endif
#if defined(VK_USE_PLATFORM_XLIB_KHR)
#include <X11/Xlib.h>
@ -66,6 +64,7 @@ static int g_QuitRequested = 0;
static int g_DesktopWidth = 0;
static int g_DesktopHeight = 0;
static int g_RefreshRate = 60000;
int getDisplayNumber(void) {
int displayNumber = 0;
@ -308,13 +307,15 @@ int System_GetPropertyInt(SystemProperty prop) {
case SYSPROP_AUDIO_SAMPLE_RATE:
return 44100;
case SYSPROP_DISPLAY_REFRESH_RATE:
return 60000;
return g_RefreshRate;
case SYSPROP_DEVICE_TYPE:
#if defined(MOBILE_DEVICE)
return DEVICE_TYPE_MOBILE;
#else
return DEVICE_TYPE_DESKTOP;
#endif
case SYSPROP_DISPLAY_COUNT:
return SDL_GetNumVideoDisplays();
default:
return -1;
}
@ -509,6 +510,7 @@ int main(int argc, char *argv[]) {
}
g_DesktopWidth = displayMode.w;
g_DesktopHeight = displayMode.h;
g_RefreshRate = (int)(displayMode.refresh_rate * 1000);
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);

View File

@ -8,6 +8,9 @@
#include "Core/System.h"
#include "SDLVulkanGraphicsContext.h"
#if defined(VK_USE_PLATFORM_METAL_EXT)
#include "SDLCocoaMetalLayer.h"
#endif
bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message) {
window = SDL_CreateWindow("Initializing Vulkan...", x, y, pixel_xres, pixel_yres, mode);
@ -50,7 +53,6 @@ bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode,
return false;
}
#if !defined(__APPLE__)
SDL_SysWMinfo sys_info{};
SDL_VERSION(&sys_info.version); //Set SDL version
if (!SDL_GetWindowWMInfo(window, &sys_info)) {
@ -71,13 +73,17 @@ bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode,
case SDL_SYSWM_WAYLAND:
vulkan_->InitSurface(WINDOWSYSTEM_WAYLAND, (void*)sys_info.info.wl.display, (void *)sys_info.info.wl.surface);
break;
#endif
#if defined(VK_USE_PLATFORM_METAL_EXT)
case SDL_SYSWM_COCOA:
vulkan_->InitSurface(WINDOWSYSTEM_METAL_EXT, makeWindowMetalCompatible(sys_info.info.cocoa.window), nullptr);
break;
#endif
default:
fprintf(stderr, "Vulkan subsystem %d not supported\n", sys_info.subsystem);
exit(1);
break;
}
#endif
if (!vulkan_->InitObjects()) {
*error_message = vulkan_->InitError();

View File

@ -1,7 +1,5 @@
#include "SDL.h"
#if !defined(__APPLE__)
#include "SDL_syswm.h"
#endif
#include "Common/GraphicsContext.h"
#include "Common/Vulkan/VulkanContext.h"