mirror of
https://github.com/cemu-project/Cemu.git
synced 2024-12-25 01:01:52 +01:00
Initial implementation of macOS Vulkan renderer over MoltenVK (#124)
This commit is contained in:
parent
15b71c57dd
commit
527ee3aea5
@ -89,7 +89,7 @@ if (NOT TARGET glslang::SPIRV AND TARGET SPIRV)
|
||||
add_library(glslang::SPIRV ALIAS SPIRV)
|
||||
endif()
|
||||
|
||||
if (UNIX)
|
||||
if (UNIX AND NOT APPLE)
|
||||
find_package(X11 REQUIRED)
|
||||
endif()
|
||||
|
||||
|
@ -20,7 +20,11 @@ if(MSVC)
|
||||
# _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
|
||||
# _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
|
||||
elseif(UNIX)
|
||||
if(NOT APPLE)
|
||||
if(APPLE)
|
||||
add_definitions(-D_XOPEN_SOURCE)
|
||||
add_definitions(-DVK_USE_PLATFORM_MACOS_MVK)
|
||||
add_definitions(-DVK_USE_PLATFORM_METAL_EXT)
|
||||
else()
|
||||
add_definitions(-DVK_USE_PLATFORM_XLIB_KHR) # legacy. Do we need to support XLIB surfaces?
|
||||
add_definitions(-DVK_USE_PLATFORM_XCB_KHR)
|
||||
endif()
|
||||
|
@ -6,7 +6,13 @@ endif()
|
||||
|
||||
file(GLOB_RECURSE CPP_FILES *.cpp)
|
||||
file(GLOB_RECURSE H_FILES *.h)
|
||||
add_library(CemuCafe ${CPP_FILES} ${H_FILES})
|
||||
|
||||
if(APPLE)
|
||||
file(GLOB_RECURSE MM_FILES *.mm)
|
||||
add_library(CemuCafe ${CPP_FILES} ${MM_FILES} ${H_FILES})
|
||||
else()
|
||||
add_library(CemuCafe ${CPP_FILES} ${H_FILES})
|
||||
endif()
|
||||
|
||||
set_property(TARGET CemuCafe PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
|
||||
|
@ -182,6 +182,8 @@ GraphicPack2::GraphicPack2(std::wstring filename, IniParser& rules)
|
||||
m_gfx_vendor = GfxVendor::Mesa;
|
||||
else if (boost::iequals(*option_vendorFilter, "nvidia"))
|
||||
m_gfx_vendor = GfxVendor::Nvidia;
|
||||
else if (boost::iequals(*option_vendorFilter, "apple"))
|
||||
m_gfx_vendor = GfxVendor::Apple;
|
||||
else
|
||||
cemuLog_force("Unknown value '{}' for vendorFilter", *option_vendorFilter);
|
||||
}
|
||||
|
@ -79,6 +79,7 @@
|
||||
#define GLVENDOR_INTEL_LEGACY (3)
|
||||
#define GLVENDOR_INTEL_NOLEGACY (4)
|
||||
#define GLVENDOR_INTEL (5)
|
||||
#define GLVENDOR_APPLE (6)
|
||||
|
||||
// decompiler
|
||||
|
||||
|
@ -161,6 +161,8 @@ int Latte_ThreadEntry()
|
||||
case GfxVendor::Nvidia:
|
||||
LatteGPUState.glVendor = GLVENDOR_NVIDIA;
|
||||
break;
|
||||
case GfxVendor::Apple:
|
||||
LatteGPUState.glVendor = GLVENDOR_APPLE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ enum class GfxVendor
|
||||
IntelNoLegacy,
|
||||
Intel,
|
||||
Nvidia,
|
||||
Apple,
|
||||
Mesa,
|
||||
|
||||
MAX
|
||||
|
9
src/Cafe/HW/Latte/Renderer/Vulkan/CocoaSurface.h
Normal file
9
src/Cafe/HW/Latte/Renderer/Vulkan/CocoaSurface.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#if BOOST_OS_MACOS
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
VkSurfaceKHR CreateCocoaSurface(VkInstance instance, void* handle);
|
||||
|
||||
#endif
|
45
src/Cafe/HW/Latte/Renderer/Vulkan/CocoaSurface.mm
Normal file
45
src/Cafe/HW/Latte/Renderer/Vulkan/CocoaSurface.mm
Normal file
@ -0,0 +1,45 @@
|
||||
#include "Cafe/HW/Latte/Renderer/Vulkan/CocoaSurface.h"
|
||||
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h"
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
|
||||
@interface MetalView : NSView
|
||||
@end
|
||||
|
||||
@implementation MetalView
|
||||
|
||||
-(BOOL) wantsUpdateLayer { return YES; }
|
||||
|
||||
+(Class) layerClass { return [CAMetalLayer class]; }
|
||||
|
||||
-(CALayer*) makeBackingLayer { return [self.class.layerClass layer]; }
|
||||
|
||||
@end
|
||||
|
||||
VkSurfaceKHR CreateCocoaSurface(VkInstance instance, void* handle)
|
||||
{
|
||||
NSView* view = (NSView*)handle;
|
||||
|
||||
MetalView* childView = [[MetalView alloc] initWithFrame:view.bounds];
|
||||
childView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
childView.wantsLayer = YES;
|
||||
|
||||
[view addSubview:childView];
|
||||
|
||||
VkMetalSurfaceCreateInfoEXT surface;
|
||||
surface.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
|
||||
surface.pNext = NULL;
|
||||
surface.flags = 0;
|
||||
surface.pLayer = (CAMetalLayer*)childView.layer;
|
||||
|
||||
VkSurfaceKHR result;
|
||||
VkResult err;
|
||||
if ((err = vkCreateMetalSurfaceEXT(instance, &surface, nullptr, &result)) != VK_SUCCESS)
|
||||
{
|
||||
forceLog_printf("Cannot create a Metal Vulkan surface: %d", (sint32)err);
|
||||
throw std::runtime_error(fmt::format("Cannot create a Metal Vulkan surface: {}", err));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -65,10 +65,14 @@ bool InitializeDeviceVulkan(VkDevice device)
|
||||
|
||||
void* dlopen_vulkan_loader()
|
||||
{
|
||||
void* vulkan_so = dlopen("libvulkan.so", RTLD_NOW);
|
||||
if(!vulkan_so)
|
||||
vulkan_so = dlopen("libvulkan.so.1", RTLD_NOW);
|
||||
return vulkan_so;
|
||||
#if BOOST_OS_LINUX
|
||||
void* vulkan_so = dlopen("libvulkan.so", RTLD_NOW);
|
||||
if(!vulkan_so)
|
||||
vulkan_so = dlopen("libvulkan.so.1", RTLD_NOW);
|
||||
#elif BOOST_OS_MACOS
|
||||
void* vulkan_so = dlopen("libMoltenVK.dylib", RTLD_NOW);
|
||||
#endif
|
||||
return vulkan_so;
|
||||
}
|
||||
|
||||
bool InitializeGlobalVulkan()
|
||||
|
@ -135,6 +135,10 @@ VKFUNC_INSTANCE(vkCreateXcbSurfaceKHR);
|
||||
VKFUNC_INSTANCE(vkCreateWin32SurfaceKHR);
|
||||
#endif
|
||||
|
||||
#if BOOST_OS_MACOS
|
||||
VKFUNC_INSTANCE(vkCreateMetalSurfaceEXT);
|
||||
#endif
|
||||
|
||||
VKFUNC_INSTANCE(vkDestroySurfaceKHR);
|
||||
VKFUNC_DEVICE(vkCreateSwapchainKHR);
|
||||
VKFUNC_DEVICE(vkDestroySwapchainKHR);
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "Cafe/HW/Latte/Renderer/Vulkan/LatteTextureVk.h"
|
||||
#include "Cafe/HW/Latte/Renderer/Vulkan/RendererShaderVk.h"
|
||||
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanTextureReadback.h"
|
||||
#include "Cafe/HW/Latte/Renderer/Vulkan/CocoaSurface.h"
|
||||
|
||||
#include "Cafe/HW/Latte/Core/LatteBufferCache.h"
|
||||
#include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h"
|
||||
@ -107,6 +108,8 @@ std::vector<VulkanRenderer::DeviceInfo> VulkanRenderer::GetDevices()
|
||||
requiredExtensions.emplace_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||||
#elif BOOST_OS_LINUX
|
||||
requiredExtensions.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||
#elif BOOST_OS_MACOS
|
||||
requiredExtensions.emplace_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME);
|
||||
#endif
|
||||
|
||||
VkApplicationInfo app_info{};
|
||||
@ -189,6 +192,9 @@ void VulkanRenderer::DetermineVendor()
|
||||
case 0x1002:
|
||||
m_vendor = GfxVendor::AMD;
|
||||
break;
|
||||
case 0x106B:
|
||||
m_vendor = GfxVendor::Apple;
|
||||
break;
|
||||
}
|
||||
|
||||
if (IsRunningInWine())
|
||||
@ -402,8 +408,10 @@ VulkanRenderer::VulkanRenderer()
|
||||
deviceFeatures.independentBlend = VK_TRUE;
|
||||
deviceFeatures.samplerAnisotropy = VK_TRUE;
|
||||
deviceFeatures.imageCubeArray = VK_TRUE;
|
||||
#if !BOOST_OS_MACOS
|
||||
deviceFeatures.geometryShader = VK_TRUE;
|
||||
deviceFeatures.logicOp = VK_TRUE;
|
||||
#endif
|
||||
deviceFeatures.occlusionQueryPrecise = VK_TRUE;
|
||||
deviceFeatures.depthClamp = VK_TRUE;
|
||||
deviceFeatures.depthBiasClamp = VK_TRUE;
|
||||
@ -1165,6 +1173,8 @@ std::vector<const char*> VulkanRenderer::CheckInstanceExtensionSupport(FeatureCo
|
||||
requiredInstanceExtensions.emplace_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||||
#elif BOOST_OS_LINUX
|
||||
requiredInstanceExtensions.emplace_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||
#elif BOOST_OS_MACOS
|
||||
requiredInstanceExtensions.emplace_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME);
|
||||
#endif
|
||||
if (cafeLog_isLoggingFlagEnabled(LOG_TYPE_VULKAN_VALIDATION))
|
||||
requiredInstanceExtensions.emplace_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
|
||||
@ -1342,8 +1352,7 @@ VkSurfaceKHR VulkanRenderer::CreateFramebufferSurface(VkInstance instance, struc
|
||||
#elif BOOST_OS_LINUX
|
||||
return CreateXlibSurface(instance, windowInfo.xlib_display, windowInfo.xlib_window);
|
||||
#elif BOOST_OS_MACOS
|
||||
cemu_assert_unimplemented();
|
||||
return nullptr;
|
||||
return CreateCocoaSurface(instance, windowInfo.handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ target_link_libraries(CemuCommon PRIVATE
|
||||
glm::glm
|
||||
)
|
||||
|
||||
if (UNIX)
|
||||
if (UNIX AND NOT APPLE)
|
||||
target_link_libraries(CemuCommon PRIVATE X11::X11 X11::Xrender X11::Xutil)
|
||||
endif()
|
||||
|
||||
|
@ -90,6 +90,8 @@ void gui_updateWindowTitles(bool isIdle, bool isLoading, double fps)
|
||||
graphicMode = "[Intel GPU]";
|
||||
else if (LatteGPUState.glVendor == GLVENDOR_NVIDIA)
|
||||
graphicMode = "[NVIDIA GPU]";
|
||||
else if (LatteGPUState.glVendor == GLVENDOR_APPLE)
|
||||
graphicMode = "[Apple GPU]";
|
||||
|
||||
const uint64 titleId = CafeSystem::GetForegroundTitleId();
|
||||
windowText.append(fmt::format(" - FPS: {:.2f} {} {} [TitleId: {:08x}-{:08x}]", (double)fps, renderer, graphicMode, (uint32)(titleId >> 32), (uint32)(titleId & 0xFFFFFFFF)));
|
||||
@ -197,6 +199,8 @@ void gui_initHandleContextFromWxWidgetsWindow(WindowHandleInfo& handleInfoOut, c
|
||||
{
|
||||
cemuLog_log(LogType::Force, "Unable to get xlib display");
|
||||
}
|
||||
#else
|
||||
handleInfoOut.handle = wxw->GetHandle();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,8 @@ struct WindowHandleInfo
|
||||
//xcb_window_t xcb_window{};
|
||||
// Wayland
|
||||
// todo
|
||||
#else
|
||||
void* handle;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "Fiber.h"
|
||||
#if BOOST_OS_LINUX || BOOST_OS_MACOS
|
||||
#define _XOPEN_SOURCE
|
||||
#include <ucontext.h>
|
||||
|
||||
thread_local Fiber* sCurrentFiber{};
|
||||
|
Loading…
Reference in New Issue
Block a user