Skip to content

Commit

Permalink
Initial support for vulkan on macOS ( MoltenVK )
Browse files Browse the repository at this point in the history
  • Loading branch information
CarterLi committed Jan 19, 2020
1 parent dd1de41 commit 5acf3f0
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 17 deletions.
13 changes: 7 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down Expand Up @@ -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}")
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()

Expand All @@ -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()

Expand Down
19 changes: 17 additions & 2 deletions Common/Vulkan/VulkanContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -760,6 +765,16 @@ VkResult VulkanContext::ReinitSurface() {
return vkCreateAndroidSurfaceKHR(instance_, &android, nullptr, &surface_);
}
#endif
#if defined(__APPLE__)
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:
{
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions Common/Vulkan/VulkanContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions Common/Vulkan/VulkanLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions Common/Vulkan/VulkanLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#ifndef NOMINMAX
#define NOMINMAX
#endif
#elif defined(__APPLE__)
#define VK_USE_PLATFORM_METAL_EXT
#endif

#define VK_NO_PROTOTYPES
Expand Down Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions SDL/SDLCocoaMetalLayer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

extern "C" {
void *makeWindowMetalCompatible(void *window);
}
17 changes: 17 additions & 0 deletions SDL/SDLCocoaMetalLayer.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#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]];
[view setWantsLayer:YES];
}
return view.layer;
}
2 changes: 0 additions & 2 deletions SDL/SDLGLGraphicsContext.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
#if !defined(__APPLE__)
#include "SDL_syswm.h"
#endif
#include "SDL.h"

#include "thin3d/GLRenderManager.h"
Expand Down
8 changes: 5 additions & 3 deletions SDL/SDLMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down
10 changes: 8 additions & 2 deletions SDL/SDLVulkanGraphicsContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)) {
Expand All @@ -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();
Expand Down
2 changes: 0 additions & 2 deletions SDL/SDLVulkanGraphicsContext.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include "SDL.h"
#if !defined(__APPLE__)
#include "SDL_syswm.h"
#endif

#include "Common/GraphicsContext.h"
#include "Common/Vulkan/VulkanContext.h"
Expand Down

0 comments on commit 5acf3f0

Please sign in to comment.