mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2026-07-09 17:24:49 -06:00
macos: fix Vulkan/Metal renderer on macOS 26+ and bump MoltenVK (#2149)
* macos: fix Vulkan/Metal renderer on macOS 26+ and bump MoltenVK Four related changes that together let the Vulkan backend boot a game on Apple Silicon Macs running macOS 26.x. Each is needed independently; the combination was tested on a Mac16,6 (M4 Max) / macOS 26.4.1. CMakeModules/DownloadExternals.cmake: Bump bundled MoltenVK from v1.2.9 to v1.4.1. v1.2.9 does not recognize macOS 26 surface objects and traps with an Objective-C "unrecognized selector" inside vkGetPhysicalDeviceSurfaceCapabilitiesKHR. src/video_core/renderer_vulkan/vk_instance.cpp: Disable VK_EXT_tooling_info on MoltenVK. MoltenVK advertises the extension but does not expose vkGetPhysicalDeviceToolPropertiesEXT through its dispatcher, so the call inside CollectToolingInfo() trips a vulkan-hpp assertion in Debug and dereferences NULL in Release. src/citra_qt/bootmanager.cpp: Force-install a fresh CAMetalLayer on the NSView before handing it to createMetalSurfaceEXT. Qt 6.11's QWindow::MetalSurface does not always back the view with a CAMetalLayer on macOS 26, and MoltenVK 1.3+ aborts in MVKSurface::getNaturalExtent() if the layer is not the right class. Implemented via objc_msgSend so no .mm conversion is needed. src/citra_meta/CMakeLists.txt: Gate LaunchScreen.storyboard behind 'if (IOS)'. The storyboard is iOS-only and previously broke the Xcode generator on macOS with "iOS storyboards do not support target device type 'mac'." * Move Metal layer creation logic into MetalUtil::CreateMetalLayer ObjC++ function This change makes the code much more readable, as the logic is now in its native language --------- Co-authored-by: SergeyMild <> Co-authored-by: OpenSauce04 <opensauce04@gmail.com>
This commit is contained in:
parent
28960bf166
commit
04f3a93854
@ -174,7 +174,7 @@ function(download_moltenvk)
|
|||||||
set(MOLTENVK_TAR "${CMAKE_BINARY_DIR}/externals/MoltenVK.tar")
|
set(MOLTENVK_TAR "${CMAKE_BINARY_DIR}/externals/MoltenVK.tar")
|
||||||
if (NOT EXISTS "${CMAKE_BINARY_DIR}/externals/MoltenVK")
|
if (NOT EXISTS "${CMAKE_BINARY_DIR}/externals/MoltenVK")
|
||||||
if (NOT EXISTS ${MOLTENVK_TAR})
|
if (NOT EXISTS ${MOLTENVK_TAR})
|
||||||
file(DOWNLOAD https://github.com/KhronosGroup/MoltenVK/releases/download/v1.2.9/MoltenVK-all.tar
|
file(DOWNLOAD https://github.com/KhronosGroup/MoltenVK/releases/download/v1.4.1/MoltenVK-all.tar
|
||||||
${MOLTENVK_TAR} SHOW_PROGRESS)
|
${MOLTENVK_TAR} SHOW_PROGRESS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@ -15,9 +15,11 @@ if (APPLE)
|
|||||||
set(DIST_DIR "../../dist/apple")
|
set(DIST_DIR "../../dist/apple")
|
||||||
set(APPLE_RESOURCES
|
set(APPLE_RESOURCES
|
||||||
"${DIST_DIR}/azahar.icns"
|
"${DIST_DIR}/azahar.icns"
|
||||||
"${DIST_DIR}/LaunchScreen.storyboard"
|
|
||||||
"${DIST_DIR}/launch_logo.png"
|
"${DIST_DIR}/launch_logo.png"
|
||||||
)
|
)
|
||||||
|
if (IOS)
|
||||||
|
list(APPEND APPLE_RESOURCES "${DIST_DIR}/LaunchScreen.storyboard")
|
||||||
|
endif()
|
||||||
target_sources(citra_meta PRIVATE ${APPLE_RESOURCES})
|
target_sources(citra_meta PRIVATE ${APPLE_RESOURCES})
|
||||||
|
|
||||||
# Define app bundle metadata.
|
# Define app bundle metadata.
|
||||||
|
|||||||
@ -202,6 +202,8 @@ if (APPLE)
|
|||||||
target_sources(citra_qt PUBLIC
|
target_sources(citra_qt PUBLIC
|
||||||
qt_swizzle.h
|
qt_swizzle.h
|
||||||
qt_swizzle.mm
|
qt_swizzle.mm
|
||||||
|
util/metal_util.h
|
||||||
|
util/metal_util.mm
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@ -37,8 +37,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
#include <objc/message.h>
|
#include "util/metal_util.h"
|
||||||
#include <objc/objc.h>
|
|
||||||
#elif !defined(WIN32)
|
#elif !defined(WIN32)
|
||||||
#include <qpa/qplatformnativeinterface.h>
|
#include <qpa/qplatformnativeinterface.h>
|
||||||
#endif
|
#endif
|
||||||
@ -420,8 +419,7 @@ static Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window
|
|||||||
// Our Win32 Qt external doesn't have the private API.
|
// Our Win32 Qt external doesn't have the private API.
|
||||||
wsi.render_surface = reinterpret_cast<void*>(window->winId());
|
wsi.render_surface = reinterpret_cast<void*>(window->winId());
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
wsi.render_surface = reinterpret_cast<void* (*)(id, SEL)>(objc_msgSend)(
|
wsi.render_surface = MetalUtil::CreateMetalLayer(window->winId());
|
||||||
reinterpret_cast<id>(window->winId()), sel_registerName("layer"));
|
|
||||||
#else
|
#else
|
||||||
QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface();
|
QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface();
|
||||||
wsi.display_connection = pni->nativeResourceForWindow("display", window);
|
wsi.display_connection = pni->nativeResourceForWindow("display", window);
|
||||||
|
|||||||
11
src/citra_qt/util/metal_util.h
Normal file
11
src/citra_qt/util/metal_util.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#import "qwindowdefs.h"
|
||||||
|
|
||||||
|
namespace MetalUtil {
|
||||||
|
|
||||||
|
void* CreateMetalLayer(WId window);
|
||||||
|
|
||||||
|
}
|
||||||
23
src/citra_qt/util/metal_util.mm
Normal file
23
src/citra_qt/util/metal_util.mm
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
#import <QuartzCore/CAMetalLayer.h>
|
||||||
|
#import <qwindowdefs.h>
|
||||||
|
|
||||||
|
namespace MetalUtil {
|
||||||
|
|
||||||
|
void* CreateMetalLayer(WId winId) {
|
||||||
|
// Qt's MetalSurface QWindow on macOS does not always back the NSView
|
||||||
|
// with a CAMetalLayer immediately; MoltenVK 1.3+ aborts in
|
||||||
|
// MVKSurface::getNaturalExtent() if the layer is not CAMetalLayer.
|
||||||
|
// Force-install a fresh CAMetalLayer on the view.
|
||||||
|
CAMetalLayer* metalLayer = [CAMetalLayer layer];
|
||||||
|
NSView* view = (__bridge NSView*)winId;
|
||||||
|
view.wantsLayer = YES;
|
||||||
|
view.layer = metalLayer;
|
||||||
|
return (__bridge void*)metalLayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace MetalUtil
|
||||||
@ -451,7 +451,8 @@ bool Instance::CreateDevice() {
|
|||||||
image_format_list = add_extension(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME);
|
image_format_list = add_extension(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME);
|
||||||
shader_stencil_export = add_extension(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
|
shader_stencil_export = add_extension(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
|
||||||
external_memory_host = add_extension(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME);
|
external_memory_host = add_extension(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME);
|
||||||
tooling_info = add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME);
|
tooling_info = add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME, is_moltenvk,
|
||||||
|
"function pointer is not exposed by MoltenVK");
|
||||||
const bool has_timeline_semaphores =
|
const bool has_timeline_semaphores =
|
||||||
add_extension(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME, is_qualcomm || is_turnip,
|
add_extension(VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME, is_qualcomm || is_turnip,
|
||||||
"it is broken on Qualcomm drivers");
|
"it is broken on Qualcomm drivers");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user