Make linking to MoltenVK work

This commit is contained in:
Henrik Rydgård 2024-05-21 10:41:04 +02:00
parent 41f8670d2a
commit 47f12dfeec
6 changed files with 51 additions and 9 deletions

View File

@ -1313,7 +1313,7 @@ elseif(IOS AND NOT LIBRETRO)
Common/Battery/AppleBatteryClient.m
)
set(nativeExtraLibs ${nativeExtraLibs} "-framework Foundation -framework MediaPlayer -framework AudioToolbox -framework CoreGraphics -framework QuartzCore -framework UIKit -framework GLKit -framework OpenAL -framework AVFoundation -framework CoreLocation -framework CoreVideo -framework CoreMedia -framework CoreServices" )
set(nativeExtraLibs ${nativeExtraLibs} "-framework Foundation -framework MediaPlayer -framework AudioToolbox -framework CoreGraphics -framework QuartzCore -framework UIKit -framework GLKit -framework OpenAL -framework AVFoundation -framework CoreLocation -framework CoreVideo -framework CoreMedia -framework CoreServices -framework Metal -framework IOSurface" )
if(EXISTS "${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks/GameController.framework")
set(nativeExtraLibs ${nativeExtraLibs} "-weak_framework GameController")
endif()
@ -2879,13 +2879,18 @@ if(IOS AND NOT LIBRETRO)
# This updates the version in the plist.
COMMAND /bin/bash "${CMAKE_SOURCE_DIR}/ios/iosbundle.sh" \"${APP_DIR_NAME}\" "${CMAKE_CURRENT_BINARY_DIR}"
)
# Can't figure out properly using .xcframework from CMake, so just linking directly to the .a file.
target_link_libraries(${TargetBin}
"${CMAKE_CURRENT_SOURCE_DIR}/ios/MoltenVK/MoltenVK.xcframework/ios-arm64/libMoltenVK.a"
)
# https://stackoverflow.com/questions/40664125/cmake-and-code-signing-in-xcode-8-for-ios-projects
set_target_properties(${TargetBin} PROPERTIES
XCODE_GENERATE_SCHEME YES # Avoid the scheme bloat in XCode by only setting it to YES for this target.
RESOURCE "ios/Launch Screen.storyboard"
RESOURCE "ios/Settings.bundle"
RESOURCE "ios/assets.xcassets"
RESOURCE "ext/vulkan/iOS/Frameworks"
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER ${BUNDLE_IDENTIFIER}
XCODE_ATTRIBUTE_PRODUCT_NAME ${PRODUCT_NAME}
XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME ${ICON_NAME}

View File

@ -39,6 +39,7 @@
#endif
namespace PPSSPP_VK {
#if !PPSSPP_PLATFORM(IOS_APP_STORE)
PFN_vkCreateInstance vkCreateInstance;
PFN_vkDestroyInstance vkDestroyInstance;
PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices;
@ -240,12 +241,14 @@ PFN_vkCreateRenderPass2 vkCreateRenderPass2;
PFN_vkWaitForPresentKHR vkWaitForPresentKHR;
PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE;
PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE;
#endif
} // namespace PPSSPP_VK
using namespace PPSSPP_VK;
#if PPSSPP_PLATFORM(SWITCH)
#if PPSSPP_PLATFORM(IOS_APP_STORE)
// Statically linked MoltenVK
#elif PPSSPP_PLATFORM(SWITCH)
typedef void *VulkanLibraryHandle;
static VulkanLibraryHandle vulkanLibrary;
#define dlsym(x, y) nullptr
@ -280,7 +283,8 @@ static const char * const device_name_blacklist[] = {
#ifndef _WIN32
static const char * const so_names[] = {
#if PPSSPP_PLATFORM(IOS)
#if PPSSPP_PLATFORM(IOS_APP_STORE)
#elif PPSSPP_PLATFORM(IOS)
"@executable_path/Frameworks/libMoltenVK.dylib",
"MoltenVK",
#elif PPSSPP_PLATFORM(MAC)
@ -295,6 +299,7 @@ static const char * const so_names[] = {
};
#endif
#if !PPSSPP_PLATFORM(IOS_APP_STORE)
static VulkanLibraryHandle VulkanLoadLibrary(std::string *errorString) {
#if PPSSPP_PLATFORM(SWITCH)
// Always unavailable, for now.
@ -346,11 +351,13 @@ static VulkanLibraryHandle VulkanLoadLibrary(std::string *errorString) {
break;
}
}
}
}
return lib;
#endif
}
#endif
#if !PPSSPP_PLATFORM(IOS_APP_STORE)
static void VulkanFreeLibrary(VulkanLibraryHandle &h) {
if (h) {
#if PPSSPP_PLATFORM(SWITCH)
@ -363,6 +370,7 @@ static void VulkanFreeLibrary(VulkanLibraryHandle &h) {
h = nullptr;
}
}
#endif
void VulkanSetAvailable(bool available) {
INFO_LOG(G3D, "Setting Vulkan availability to true");
@ -371,6 +379,13 @@ void VulkanSetAvailable(bool available) {
}
bool VulkanMayBeAvailable() {
#if PPSSPP_PLATFORM(IOS_APP_STORE)
g_vulkanAvailabilityChecked = true;
g_vulkanMayBeAvailable = true;
INFO_LOG(G3D, "iOS: VulkanMayBeAvailable(): Reporting Vulkan as available");
return true;
#else
// Unsupported in VR at the moment
if (IsVREnabled()) {
return false;
@ -557,9 +572,15 @@ bail:
WARN_LOG(G3D, "Vulkan with working device not detected.");
}
return g_vulkanMayBeAvailable;
#endif
}
bool VulkanLoad(std::string *errorStr) {
#if PPSSPP_PLATFORM(IOS_APP_STORE)
INFO_LOG(G3D, "iOS: Vulkan doesn't need loading");
return true;
#else
if (!vulkanLibrary) {
vulkanLibrary = VulkanLoadLibrary(errorStr);
if (!vulkanLibrary) {
@ -585,9 +606,11 @@ bool VulkanLoad(std::string *errorStr) {
VulkanFreeLibrary(vulkanLibrary);
return false;
}
#endif
}
void VulkanLoadInstanceFunctions(VkInstance instance, const VulkanExtensions &enabledExtensions, uint32_t vulkanApiVersion) {
#if !PPSSPP_PLATFORM(IOS_APP_STORE)
// OK, let's use the above functions to get the rest.
LOAD_INSTANCE_FUNC(instance, vkDestroyInstance);
LOAD_INSTANCE_FUNC(instance, vkEnumeratePhysicalDevices);
@ -655,12 +678,14 @@ void VulkanLoadInstanceFunctions(VkInstance instance, const VulkanExtensions &en
}
INFO_LOG(G3D, "Vulkan instance functions loaded.");
#endif
}
// On some implementations, loading functions (that have Device as their first parameter) via vkGetDeviceProcAddr may
// increase performance - but then these function pointers will only work on that specific device. Thus, this loader is not very
// good for multi-device - not likely we'll ever try that anyway though.
void VulkanLoadDeviceFunctions(VkDevice device, const VulkanExtensions &enabledExtensions, uint32_t vulkanApiVersion) {
#if !PPSSPP_PLATFORM(IOS_APP_STORE)
INFO_LOG(G3D, "Vulkan device functions loaded.");
LOAD_DEVICE_FUNC(device, vkQueueSubmit);
@ -799,10 +824,13 @@ void VulkanLoadDeviceFunctions(VkDevice device, const VulkanExtensions &enabledE
if (enabledExtensions.KHR_create_renderpass2) {
LOAD_DEVICE_FUNC_CORE(device, vkCreateRenderPass2, vkCreateRenderPass2KHR, VK_API_VERSION_1_2);
}
#endif
}
void VulkanFree() {
#if !PPSSPP_PLATFORM(IOS_APP_STORE)
VulkanFreeLibrary(vulkanLibrary);
#endif
}
const char *VulkanResultToString(VkResult res) {

View File

@ -17,7 +17,9 @@
#pragma once
#ifdef __ANDROID__
#include "ppsspp_config.h"
#if PPSSPP_PLATFORM(ANDROID)
#define VK_USE_PLATFORM_ANDROID_KHR
#elif defined(_WIN32)
#define VK_USE_PLATFORM_WIN32_KHR
@ -29,7 +31,9 @@
#define VK_USE_PLATFORM_METAL_EXT
#endif
#if !PPSSPP_PLATFORM(IOS_APP_STORE)
#define VK_NO_PROTOTYPES
#endif
#include "ext/vulkan/vulkan.h"
#include <string>
@ -40,6 +44,7 @@
#endif
namespace PPSSPP_VK {
#if !PPSSPP_PLATFORM(IOS_APP_STORE)
// Putting our own Vulkan function pointers in a namespace ensures that ppsspp_libretro.so doesn't collide with libvulkan.so.
extern PFN_vkCreateInstance vkCreateInstance;
extern PFN_vkDestroyInstance vkDestroyInstance;
@ -240,6 +245,7 @@ extern PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesE
extern PFN_vkWaitForPresentKHR vkWaitForPresentKHR;
extern PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE;
extern PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE;
#endif // !PPSSPP_PLATFORM(IOS_APP_STORE)
} // namespace PPSSPP_VK
// For fast extension-enabled checks.

View File

@ -563,6 +563,7 @@ void VulkanRenderManager::RenderThreadFunc() {
void VulkanRenderManager::PresentWaitThreadFunc() {
SetCurrentThreadName("PresentWait");
#if !PPSSPP_PLATFORM(IOS_APP_STORE)
_dbg_assert_(vkWaitForPresentKHR != nullptr);
uint64_t waitedId = frameIdGen_;
@ -579,6 +580,7 @@ void VulkanRenderManager::PresentWaitThreadFunc() {
}
_dbg_assert_(waitedId <= frameIdGen_);
}
#endif
INFO_LOG(G3D, "Leaving PresentWaitThreadFunc()");
}

View File

@ -1289,7 +1289,7 @@ void MainScreen::CreateViews() {
}
rightColumnChoices->Add(new Spacer(25.0));
#if !PPSSPP_PLATFORM(IOS_APP_STORE)
#if !PPSSPP_PLATFORM(IOS_APP_STORE) || defined(_DEBUG)
// Officially, iOS apps should not have exit buttons. Remove it to maximize app store review chances.
rightColumnChoices->Add(new Choice(mm->T("Exit")))->OnClick.Handle(this, &MainScreen::OnExit);
#endif

View File

@ -216,7 +216,8 @@ extern float g_safeInsetBottom;
[self hideKeyboard];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// Was previously DISPATCH_QUEUE_PRIORITY_HIGH.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NativeInitGraphics(graphicsContext);
INFO_LOG(SYSTEM, "Emulation thread starting\n");