diff --git a/.gitmodules b/.gitmodules index 4be8c3f5bd..72ce484b1a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -44,9 +44,6 @@ [submodule "ext/OpenXR-SDK"] path = ext/OpenXR-SDK url = https://github.com/KhronosGroup/OpenXR-SDK.git -[submodule "ios/MoltenVK"] - path = ios/MoltenVK - url = https://github.com/hrydgard/ppsspp-moltenvk.git [submodule "ext/lua"] path = ext/lua url = https://github.com/hrydgard/ppsspp-lua.git diff --git a/CMakeLists.txt b/CMakeLists.txt index b1b56f7a15..0f777b54e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -323,7 +323,7 @@ elseif(NOT OPENGL_LIBRARIES AND USING_GLES2) set(OPENGL_LIBRARIES GLESv2 EGL) endif() -# The iOS app is Vulkan (MoltenVK) only. Must match PPSSPP_API_ANY_GL in ppsspp_config.h. +# The iOS app is Metal only. Must match PPSSPP_API_ANY_GL in ppsspp_config.h. if(IOS AND NOT LIBRETRO) set(NO_OPENGL ON) endif() @@ -1566,11 +1566,6 @@ if(IOS AND NOT LIBRETRO) if(IOS_DEBUG) file(INSTALL pspautotests DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/assets) endif() - if(TVOS) - set(MOLTENVK_SLICE tvos-arm64) - else() - set(MOLTENVK_SLICE ios-arm64) - endif() set(RSRC_XIB_FILES "Launch Screen.storyboard" ${CMAKE_CURRENT_SOURCE_DIR}/ios/assets.xcassets) set_source_files_properties(${RSRC_XIB_FILES} @@ -1584,15 +1579,6 @@ if(IOS AND NOT LIBRETRO) set(APP_DIR_NAME "$") #endif() - # Can't figure out properly using .xcframework from CMake, so just linking directly to the .a file. - # The simulator renders with Metal only, and loads no Vulkan (see PPSSPP_VK_STATIC). - if(IOS_PLATFORM STREQUAL "SIMULATOR") - set(MOLTENVK_LIB "") - else() - set(MOLTENVK_LIB "${CMAKE_CURRENT_SOURCE_DIR}/ios/MoltenVK/MoltenVK.xcframework/${MOLTENVK_SLICE}/libMoltenVK.a") - endif() - target_link_libraries(${TargetBin} ${MOLTENVK_LIB}) - set(MACOSX_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET}) set(PRODUCT_NAME "PPSSPP") if(TVOS) @@ -1697,7 +1683,6 @@ if(IOS AND NOT LIBRETRO) # PPSSPPHeadless as an app of its own (org.ppsspp.headless), for running frame dumps on a # device. Signed for development, so devicectl can copy files in and out of its container. target_link_libraries(PPSSPPHeadless - ${MOLTENVK_LIB} "-framework Foundation -framework UIKit -framework CoreGraphics -framework CoreText -framework QuartzCore -framework Metal -framework IOSurface -framework AudioToolbox -framework AVFoundation -framework CoreMedia -framework CoreVideo -framework UniformTypeIdentifiers" ) if(NOT ICONV_LIBRARY) diff --git a/Common/GPU/Vulkan/VulkanContext.cpp b/Common/GPU/Vulkan/VulkanContext.cpp index 43c93db5c7..0bd4baa9ac 100644 --- a/Common/GPU/Vulkan/VulkanContext.cpp +++ b/Common/GPU/Vulkan/VulkanContext.cpp @@ -251,9 +251,7 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) { inst_info.enabledExtensionCount = (uint32_t)instance_extensions_enabled_.size(); inst_info.ppEnabledExtensionNames = instance_extensions_enabled_.size() ? instance_extensions_enabled_.data() : nullptr; -#if PPSSPP_VK_STATIC - inst_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; -#elif PPSSPP_PLATFORM(MAC) +#if PPSSPP_PLATFORM(MAC) // Through the Khronos loader (like the SDK's, for the validation layers), MoltenVK is only // listed if we ask for portability drivers. if (IsInstanceExtensionAvailable(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)) { diff --git a/Common/GPU/Vulkan/VulkanLoader.cpp b/Common/GPU/Vulkan/VulkanLoader.cpp index 39a45a12bd..2fa107b057 100644 --- a/Common/GPU/Vulkan/VulkanLoader.cpp +++ b/Common/GPU/Vulkan/VulkanLoader.cpp @@ -43,7 +43,6 @@ #endif namespace PPSSPP_VK { -#if !PPSSPP_VK_STATIC PFN_vkCreateInstance vkCreateInstance; PFN_vkDestroyInstance vkDestroyInstance; PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; @@ -245,14 +244,11 @@ PFN_vkCreateRenderPass2 vkCreateRenderPass2; PFN_vkWaitForPresentKHR vkWaitForPresentKHR; PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; -#endif } // namespace PPSSPP_VK using namespace PPSSPP_VK; -#if PPSSPP_VK_STATIC -// Statically linked MoltenVK -#elif PPSSPP_PLATFORM(SWITCH) +#if PPSSPP_PLATFORM(SWITCH) typedef void *VulkanLibraryHandle; static VulkanLibraryHandle vulkanLibrary; #define dlsym(x, y) nullptr @@ -337,10 +333,10 @@ static constexpr DriverBlackListEntry g_gpuNameBlacklist[] = { }; #endif -#if !defined(_WIN32) && !PPSSPP_VK_STATIC +#if !defined(_WIN32) static const char * const so_names[] = { #if PPSSPP_PLATFORM(IOS) - // Only reached by the libretro core and the simulator (which has none). The app links MoltenVK statically. + // Only reached by the libretro core. The app has no MoltenVK. "@executable_path/Frameworks/libMoltenVK.dylib", "MoltenVK", #elif PPSSPP_PLATFORM(MAC) @@ -360,7 +356,6 @@ static const char * const so_names[] = { }; #endif -#if !PPSSPP_VK_STATIC static VulkanLibraryHandle VulkanLoadLibrary(std::string *errorString) { #if PPSSPP_PLATFORM(SWITCH) // Always unavailable, for now. @@ -418,9 +413,7 @@ static VulkanLibraryHandle VulkanLoadLibrary(std::string *errorString) { return lib; #endif } -#endif -#if !PPSSPP_VK_STATIC static void VulkanFreeLibrary(VulkanLibraryHandle &h) { if (h) { #if PPSSPP_PLATFORM(SWITCH) @@ -433,7 +426,6 @@ static void VulkanFreeLibrary(VulkanLibraryHandle &h) { h = nullptr; } } -#endif void VulkanSetAvailable(bool available) { INFO_LOG(Log::G3D, "Setting Vulkan availability to true"); @@ -446,7 +438,10 @@ void VulkanSetNativeLibDir(std::string_view nativeLibDir) { } bool VulkanMayBeAvailable() { -#if PPSSPP_PLATFORM(IOS) && !PPSSPP_PLATFORM(IOS_SIMULATOR) +#if PPSSPP_PLATFORM(IOS) && !defined(__LIBRETRO__) + // The app renders with Metal, and has no MoltenVK. + return false; +#elif PPSSPP_PLATFORM(IOS) && !PPSSPP_PLATFORM(IOS_SIMULATOR) // The deployment target (15.0) is above anything MoltenVK doesn't support. g_vulkanAvailabilityChecked = true; g_vulkanMayBeAvailable = true; @@ -681,11 +676,6 @@ bail: } bool VulkanLoad(std::string *errorStr) { -#if PPSSPP_VK_STATIC - INFO_LOG(Log::G3D, "iOS: Vulkan doesn't need loading"); - return true; -#else - if (!vulkanLibrary) { vulkanLibrary = VulkanLoadLibrary(errorStr); if (!vulkanLibrary) { @@ -711,15 +701,9 @@ bool VulkanLoad(std::string *errorStr) { VulkanFreeLibrary(vulkanLibrary); return false; } -#endif } bool VulkanLoadFromGetInstanceProcAddr(VkInstance instance, PFN_vkGetInstanceProcAddr getInstanceProcAddr) { -#if PPSSPP_VK_STATIC - // MoltenVK is linked statically, the functions are already there - there are no function pointers to fill in. - INFO_LOG(Log::G3D, "iOS: Vulkan doesn't need loading"); - return true; -#else vkGetInstanceProcAddr = getInstanceProcAddr; vkCreateInstance = (PFN_vkCreateInstance)getInstanceProcAddr(nullptr, "vkCreateInstance"); // Per the Vulkan spec, vkGetDeviceProcAddr is not one of the handful of commands queryable with a @@ -737,11 +721,9 @@ bool VulkanLoadFromGetInstanceProcAddr(VkInstance instance, PFN_vkGetInstancePro ERROR_LOG(Log::G3D, "VulkanLoadFromGetInstanceProcAddr: Failed to load Vulkan base functions"); return false; } -#endif } void VulkanLoadInstanceFunctions(VkInstance instance, const VulkanExtensions &enabledExtensions, uint32_t vulkanInstanceApiVersion) { -#if !PPSSPP_VK_STATIC INFO_LOG(Log::G3D, "Loading Vulkan instance functions. Instance API version: %08x (%d.%d.%d)", vulkanInstanceApiVersion, VK_API_VERSION_MAJOR(vulkanInstanceApiVersion), VK_API_VERSION_MINOR(vulkanInstanceApiVersion), VK_API_VERSION_PATCH(vulkanInstanceApiVersion)); // OK, let's use the above functions to get the rest. LOAD_INSTANCE_FUNC(instance, vkDestroyInstance); @@ -810,14 +792,12 @@ void VulkanLoadInstanceFunctions(VkInstance instance, const VulkanExtensions &en } INFO_LOG(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 vulkanDeviceApiVersion) { -#if !PPSSPP_VK_STATIC INFO_LOG(Log::G3D, "Loading Vulkan device functions. Device API version: %08x (%d.%d.%d)", vulkanDeviceApiVersion, VK_API_VERSION_MAJOR(vulkanDeviceApiVersion), VK_API_VERSION_MINOR(vulkanDeviceApiVersion), VK_API_VERSION_PATCH(vulkanDeviceApiVersion)); LOAD_DEVICE_FUNC(device, vkQueueSubmit); @@ -958,13 +938,10 @@ void VulkanLoadDeviceFunctions(VkDevice device, const VulkanExtensions &enabledE LOAD_DEVICE_FUNC_CORE(device, vkGetDeviceBufferMemoryRequirements, vkGetDeviceBufferMemoryRequirementsKHR, VK_API_VERSION_1_3); LOAD_DEVICE_FUNC_CORE(device, vkGetDeviceImageMemoryRequirements, vkGetDeviceImageMemoryRequirementsKHR, VK_API_VERSION_1_3); } -#endif } void VulkanFree() { -#if !PPSSPP_VK_STATIC VulkanFreeLibrary(vulkanLibrary); -#endif } const char *VulkanResultToString(VkResult res) { diff --git a/Common/GPU/Vulkan/VulkanLoader.h b/Common/GPU/Vulkan/VulkanLoader.h index fed9b7ba1f..97785cee27 100644 --- a/Common/GPU/Vulkan/VulkanLoader.h +++ b/Common/GPU/Vulkan/VulkanLoader.h @@ -32,14 +32,9 @@ #define VK_USE_PLATFORM_METAL_EXT #endif -// The iOS app links MoltenVK statically and calls Vulkan directly. Everywhere else (including the -// iOS libretro core), we load the functions at runtime into the pointers below. The simulator build -// has no MoltenVK at all (it uses Metal), so it takes the runtime path, which finds no library. -#if PPSSPP_PLATFORM(IOS) && !PPSSPP_PLATFORM(IOS_SIMULATOR) && !defined(__LIBRETRO__) -#define PPSSPP_VK_STATIC 1 -#else +// We load the functions at runtime into the pointers below. The iOS app has no MoltenVK (it uses +// Metal), so there this finds no library. #define VK_NO_PROTOTYPES -#endif #define VK_ENABLE_BETA_EXTENSIONS 1 // VK_KHR_portability_subset #include "ext/vulkan/vulkan.h" @@ -51,7 +46,6 @@ #endif namespace PPSSPP_VK { -#if !PPSSPP_VK_STATIC // 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; @@ -252,7 +246,6 @@ extern PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesE extern PFN_vkWaitForPresentKHR vkWaitForPresentKHR; extern PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE; extern PFN_vkGetRefreshCycleDurationGOOGLE vkGetRefreshCycleDurationGOOGLE; -#endif // !PPSSPP_VK_STATIC } // namespace PPSSPP_VK // For fast extension-enabled checks. diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index e3f67e77b7..c2dcdc09dc 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -900,7 +900,6 @@ void VulkanRenderManager::RenderThreadFunc() { void VulkanRenderManager::PresentWaitThreadFunc() { SetCurrentThreadName("PresentWait"); -#if !PPSSPP_VK_STATIC _dbg_assert_(vkWaitForPresentKHR != nullptr); uint64_t waitedId = frameIdGen_; @@ -917,7 +916,6 @@ void VulkanRenderManager::PresentWaitThreadFunc() { } _dbg_assert_(waitedId <= frameIdGen_); } -#endif INFO_LOG(Log::G3D, "Leaving PresentWaitThreadFunc()"); } diff --git a/Core/Config.cpp b/Core/Config.cpp index a56536f6cb..349db597cd 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -661,9 +661,6 @@ static int DefaultGPUBackend() { return (int)GPUBackend::OPENGL; #endif -#elif PPSSPP_PLATFORM(TVOS) && !defined(__LIBRETRO__) - // Metal hasn't been tried on tvOS yet. - return (int)GPUBackend::VULKAN; #elif PPSSPP_PLATFORM(IOS) && !defined(__LIBRETRO__) return (int)GPUBackend::METAL; #endif diff --git a/UI/Settings/GraphicsPage.cpp b/UI/Settings/GraphicsPage.cpp index a1b131e01f..efbf9f5c94 100644 --- a/UI/Settings/GraphicsPage.cpp +++ b/UI/Settings/GraphicsPage.cpp @@ -139,6 +139,17 @@ static void BuildCardboardVRPage(SettingsPage *page) { page->Setting(&config.iCardboardYShift).Enabled(&config.bEnableCardboardVR); } +// Asking about Vulkan can load its driver, so that's done last, and only when it decides the answer. +static bool HasBackendChoice() { + int count = 0; + for (GPUBackend backend : { GPUBackend::OPENGL, GPUBackend::DIRECT3D11, GPUBackend::METAL }) { + if (g_Config.IsBackendEnabled(backend)) { + count++; + } + } + return count >= 2 || (count == 1 && g_Config.IsBackendEnabled(GPUBackend::VULKAN)); +} + void BuildGraphicsSettings(SettingsPage *page) { using namespace UI; SettingsPageHost *host = page->Host(); @@ -149,7 +160,7 @@ void BuildGraphicsSettings(SettingsPage *page) { page->Header("Rendering"); #if !PPSSPP_PLATFORM(UWP) - page->Setting(&g_Config.iGPUBackend).Setup([host](View *view) { + page->Setting(&g_Config.iGPUBackend).Visible(HasBackendChoice()).Setup([host](View *view) { PopupMultiChoice *renderingBackendChoice = static_cast(view); renderingBackendChoice->SetPreOpenCallback([host](UI::PopupMultiChoice *choice) { // Don't filter until the last possible moment, since it involves trying to initialize Vulkan, if we were diff --git a/UI/SettingsPage.cpp b/UI/SettingsPage.cpp index db8bb7eb77..82f8736b1f 100644 --- a/UI/SettingsPage.cpp +++ b/UI/SettingsPage.cpp @@ -430,12 +430,18 @@ static UI::View *CreateSettingView(const SettingItem &item, I18NCat pageCat, UI: clickable->SetHintText(item.hint.Translate(pageCat)); } else { // Custom views that can't show a hint get it below them. - parent->Add(new SettingHint(item.hint.Translate(pageCat), view)); + UI::View *hint = parent->Add(new SettingHint(item.hint.Translate(pageCat), view)); + if (!item.visible) { + hint->SetVisibility(UI::V_GONE); + } } } if (item.setup) { item.setup(view); } + if (!item.visible) { + view->SetVisibility(UI::V_GONE); + } return view; } diff --git a/UI/SettingsPage.h b/UI/SettingsPage.h index a59704881a..c322c67eb0 100644 --- a/UI/SettingsPage.h +++ b/UI/SettingsPage.h @@ -154,6 +154,8 @@ struct SettingItem { bool *disabledPtr = nullptr; std::function enabledFunc; SettingText disabledReason; + // A hidden item still gets its view (it's gone from the layout), so views stay in step with items. + bool visible = true; // Called on click (Bool, Choice), choice (choices) or change (sliders). std::function onChange; // From the config, for settings described there. Called before onChange. @@ -168,6 +170,7 @@ struct SettingItem { SettingItem &Enabled(bool *ptr) { enabledPtr = ptr; return *this; } SettingItem &Disabled(bool *ptr) { disabledPtr = ptr; return *this; } SettingItem &EnabledFunc(std::function func) { enabledFunc = std::move(func); return *this; } + SettingItem &Visible(bool value) { visible = value; return *this; } // Shown when the user tries to use the item while it's disabled (see ShowWhyViewDisabled). SettingItem &DisabledReason(SettingText text) { disabledReason = text; return *this; } diff --git a/UI/SettingsPagesDialogScreen.cpp b/UI/SettingsPagesDialogScreen.cpp index ad4bf4488b..5a7e19d0f5 100644 --- a/UI/SettingsPagesDialogScreen.cpp +++ b/UI/SettingsPagesDialogScreen.cpp @@ -426,7 +426,7 @@ bool SettingsPagesDialogScreen::SearchPage(UI::ViewGroup *parent, int settingsTa if (!item.hint.empty() && SettingTextMatches(item.hint, cat, searchText_)) { matches = true; } - show[i] = matches || sectionMatches; + show[i] = item.visible && (matches || sectionMatches); break; } } diff --git a/docs/metal-backend.md b/docs/metal-backend.md index efda857ecf..b4456456a6 100644 --- a/docs/metal-backend.md +++ b/docs/metal-backend.md @@ -1,12 +1,12 @@ # The Metal backend A native Metal backend for Mac and iOS (tvOS too), alongside OpenGL, D3D11 and Vulkan. It's selected as -`GPUBackend::METAL` (`--graphics=metal`). It's the default on iOS since 2026-10-22; Vulkan through MoltenVK -stays the default on Mac and tvOS. Written 2026-10-19; file references will drift. +`GPUBackend::METAL` (`--graphics=metal`). It's the only backend in the iOS and tvOS apps, which no longer ship +MoltenVK; Vulkan through MoltenVK stays the default on Mac. Written 2026-10-19; file references will drift. **Why:** programmable blending. Apple GPUs let a fragment shader read the color it's about to blend with (`[[color(0)]]`), so PSP blend modes that need shader blending no longer copy the framebuffer for every -draw. MoltenVK can't expose that. Removing the MoltenVK dependency is a smaller benefit, and comes later. +draw. MoltenVK can't expose that. ## Where things are diff --git a/ios/ExternalDisplaySceneDelegate.mm b/ios/ExternalDisplaySceneDelegate.mm index 39711f4550..f955e07fda 100644 --- a/ios/ExternalDisplaySceneDelegate.mm +++ b/ios/ExternalDisplaySceneDelegate.mm @@ -117,11 +117,6 @@ static bool g_launched = false; return; } // Without a window, iOS mirrors the phone. - // The running backend: the setting is already the new one while the restart prompt for a change is up. - if (GetGPUBackend() != GPUBackend::METAL && GetGPUBackend() != GPUBackend::VULKAN) { - INFO_LOG(Log::G3D, "External display: mirroring, as the backend can't present to it"); - return; - } if (g_Config.iExternalDisplay != (int)ExternalDisplayMode::SHOW_GAME) { INFO_LOG(Log::G3D, "External display: mirroring, as set"); return; diff --git a/ios/MoltenVK b/ios/MoltenVK deleted file mode 160000 index b77380b5c8..0000000000 --- a/ios/MoltenVK +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b77380b5c84653b96a058bcacb04d305628b1391 diff --git a/ios/README.md b/ios/README.md index 9a322c05e1..cea813a04d 100644 --- a/ios/README.md +++ b/ios/README.md @@ -1,10 +1,3 @@ -Updating with a self-built MoltenVK -=================================== - -Probably won't be needed again. - -cp -r ../dev/build-molten/MoltenVK/Package/Release/MoltenVK/static/MoltenVK.xcframework ios/MoltenVK - The Old iOS Build Instructions ============================== diff --git a/ios/ViewController.h b/ios/ViewController.h index 5350de0358..73b4b78d0d 100644 --- a/ios/ViewController.h +++ b/ios/ViewController.h @@ -8,7 +8,7 @@ #if PPSSPP_PLATFORM(TVOS) -// The one view controller. Renders with Vulkan (MoltenVK) to a CAMetalLayer. +// The one view controller. Renders with Metal to a CAMetalLayer. // A GCEventViewController, so controller input (the Siri Remote included) reaches us only through // GCController, instead of also driving UIKit's focus engine. @interface PPSSPPViewController : GCEventViewController @@ -20,7 +20,7 @@ #import "CameraHelper.h" #import "LocationHelper.h" -// The one view controller. Renders with Vulkan (MoltenVK) to a CAMetalLayer. +// The one view controller. Renders with Metal to a CAMetalLayer. @interface PPSSPPViewController : UIViewController< PHPickerViewControllerDelegate, CameraFrameDelegate, LocationHandlerDelegate, diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 5c7e3d5bae..042e793078 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -13,7 +13,6 @@ #include #include #include "Common/GPU/GraphicsContext.h" -#include "Common/GPU/Vulkan/VulkanGraphicsContext.h" #include "Common/GPU/Metal/MetalGraphicsContext.h" #include "Common/System/Request.h" #include "Common/System/System.h" @@ -108,7 +107,7 @@ static void ApplyPendingResolution() { } } -static void VulkanRenderLoop(GraphicsContext *graphicsContext, CAMetalLayer *metalLayer) { +static void RenderLoop(GraphicsContext *graphicsContext, CAMetalLayer *metalLayer) { // Only a provisional name, RunGraphicsLoop renames the thread once it knows its role. SetCurrentThreadName("RenderLoop"); _assert_(graphicsContext); @@ -239,10 +238,10 @@ static int GetPickerRequestId(id picker) { _dbg_assert_(sharedViewController != nil); sharedViewController = nil; - g_Config.Save("shutdown vk"); + g_Config.Save("shutdown"); // Normally already done by willResignActive, but not when the app is terminated. - [self requestExitVulkanRenderLoop]; + [self requestExitRenderLoop]; if (graphicsContext) { graphicsContext->ShutdownAPI(); @@ -252,24 +251,24 @@ static int GetPickerRequestId(id picker) { } - (void)dealloc { - INFO_LOG(Log::System, "dealloc VK"); + INFO_LOG(Log::System, "dealloc"); } -- (bool)runVulkanRenderLoop { - INFO_LOG(Log::G3D, "runVulkanRenderLoop"); +- (bool)runRenderLoop { + INFO_LOG(Log::G3D, "runRenderLoop"); if (!graphicsContext) { - ERROR_LOG(Log::G3D, "runVulkanRenderLoop: Tried to enter without a created graphics context."); + ERROR_LOG(Log::G3D, "runRenderLoop: Tried to enter without a created graphics context."); return false; } if (g_renderLoopThread.joinable()) { if (renderLoopRunning) { - ERROR_LOG(Log::G3D, "runVulkanRenderLoop: Already running"); + ERROR_LOG(Log::G3D, "runRenderLoop: Already running"); return false; } // The previous thread gave up by itself (failed surface init). Reap it so we can try again. - WARN_LOG(Log::G3D, "runVulkanRenderLoop: Joining a render thread that had already exited"); + WARN_LOG(Log::G3D, "runRenderLoop: Joining a render thread that had already exited"); g_renderLoopThread.join(); g_renderLoopThread = std::thread(); } @@ -279,12 +278,12 @@ static int GetPickerRequestId(id picker) { CAMetalLayer *metalLayer = (CAMetalLayer *)self.view.layer; // Set before the thread exists, so an exit request can't slip in ahead of it. renderLoopRunning = true; - g_renderLoopThread = std::thread(VulkanRenderLoop, graphicsContext, metalLayer); + g_renderLoopThread = std::thread(RenderLoop, graphicsContext, metalLayer); return true; } -- (void)requestExitVulkanRenderLoop { - INFO_LOG(Log::G3D, "requestExitVulkanRenderLoop"); +- (void)requestExitRenderLoop { + INFO_LOG(Log::G3D, "requestExitRenderLoop"); // Don't go by renderLoopRunning - the thread might have bailed by itself, and still needs joining. if (!g_renderLoopThread.joinable()) { @@ -343,11 +342,11 @@ static int GetPickerRequestId(id picker) { // Spin up the render thread, which in turn starts the emu thread. [self updateResolutionWithView:self.view]; - [self runVulkanRenderLoop]; + [self runRenderLoop]; } - (void)willResignActive { - [self requestExitVulkanRenderLoop]; + [self requestExitRenderLoop]; #if !PPSSPP_PLATFORM(TVOS) g_touchTracker.CancelAll(); @@ -631,11 +630,7 @@ static int GetPickerRequestId(id picker) { keyboardInputView_ = [[KeyboardInputView alloc] initWithFrame:CGRectZero]; [self.view addSubview:keyboardInputView_]; - if (g_Config.iGPUBackend == (int)GPUBackend::METAL) { - graphicsContext = new MetalGraphicsContext(); - } else { - graphicsContext = new VulkanGraphicsContext(); - } + graphicsContext = new MetalGraphicsContext(); std::string errorMessage; if (!graphicsContext->InitAPI(nullptr, &g_Config.sVulkanDevice, &errorMessage)) { delete graphicsContext; @@ -650,11 +645,9 @@ static int GetPickerRequestId(id picker) { // From iOS 27, an external display scene only goes to apps that register for one like this. Earlier // versions go by the Info.plist role instead. Without the scene, iOS mirrors the phone. if (@available(iOS 27.0, *)) { - if (g_Config.iGPUBackend == (int)GPUBackend::METAL || g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { - UISceneConfiguration *sceneConfiguration = [UISceneConfiguration new]; - sceneConfiguration.delegateClass = [ExternalDisplaySceneDelegate class]; - self.externalDisplayRegistration = [self registerSceneAccessory:[UISceneAccessory externalNonInteractiveSceneAccessoryWithConfiguration:sceneConfiguration]]; - } + UISceneConfiguration *sceneConfiguration = [UISceneConfiguration new]; + sceneConfiguration.delegateClass = [ExternalDisplaySceneDelegate class]; + self.externalDisplayRegistration = [self registerSceneAccessory:[UISceneAccessory externalNonInteractiveSceneAccessoryWithConfiguration:sceneConfiguration]]; } #endif diff --git a/ios/main.mm b/ios/main.mm index 2ed28c15da..2d3b334c84 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -5,7 +5,7 @@ // main.mm: JIT enablement, the System_ functions, starting the next step // AppDelegate.mm: Audio session interruptions, deep link and library export helpers // SceneDelegate.mm: Runs NativeInit, creates the window and the view controller -// ViewController.mm: The view controller. Rendering (Vulkan to a CAMetalLayer), input, keyboard, pickers and sizing +// ViewController.mm: The view controller. Rendering (Metal to a CAMetalLayer), input, keyboard, pickers and sizing #import #import