mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-12-30 10:37:07 +00:00
Initial implementation of macOS Vulkan renderer over MoltenVK (#124)
This commit is contained in:
parent
15b71c57dd
commit
527ee3aea5
16 changed files with 103 additions and 11 deletions
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue