mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07:00
iOS: fix two warnings that were real bugs
MTLCopyAllDevices is iOS 18 only and we deploy to 17, so on 17 it's a null weak symbol and GSDeviceMTL::Create crashes on it before ever reaching the MTLCreateSystemDefaultDevice fallback. Guard both call sites with @available; below 18 there's one GPU and nothing to enumerate. CocoaTools::GetBundlePath was defined twice on iOS -- once in MacOSStubs.cpp returning nullopt, once in HostImpls.mm returning std::string where the header says std::optional<std::string>. Return types aren't mangled, so both are the same symbol, the linker picked one, and DynamicLibrary.cpp read an uninitialised has_value byte off the stack. HostImpls.mm has the real implementation, so drop the stub and give it the declared signature. CreateMetalLayer and DestroyMetalLayer were duplicated the same way. CreateMetalLayer also returned void* against a bool declaration, which reads back the low byte of a pointer -- fine until a layer lands on a 256-byte boundary. Nothing calls it on iOS today (Vulkan is off) but it's the only definition left, so make it match.
This commit is contained in:
@@ -28,17 +28,31 @@ GSDevice* MakeGSDeviceMTL()
|
||||
return new GSDeviceMTL();
|
||||
}
|
||||
|
||||
static GSAdapterInfo GetMetalAdapterInfo(id<MTLDevice> dev)
|
||||
{
|
||||
GSAdapterInfo ai;
|
||||
ai.name = [[dev name] UTF8String];
|
||||
ai.max_texture_size = GSMTLDevice::GetMaxTextureSize(dev);
|
||||
ai.max_upscale_multiplier = GSGetMaxUpscaleMultiplier(ai.max_texture_size);
|
||||
return ai;
|
||||
}
|
||||
|
||||
std::vector<GSAdapterInfo> GetMetalAdapterList()
|
||||
{ @autoreleasepool {
|
||||
std::vector<GSAdapterInfo> list;
|
||||
auto devs = MRCTransfer(MTLCopyAllDevices());
|
||||
for (id<MTLDevice> dev in devs.Get())
|
||||
// MTLCopyAllDevices only exists on iOS 18. We ship down to 17, where there's a
|
||||
// single GPU and nothing to enumerate anyway.
|
||||
if (@available(macOS 10.11, iOS 18.0, *))
|
||||
{
|
||||
GSAdapterInfo ai;
|
||||
ai.name = [[dev name] UTF8String];
|
||||
ai.max_texture_size = GSMTLDevice::GetMaxTextureSize(dev);
|
||||
ai.max_upscale_multiplier = GSGetMaxUpscaleMultiplier(ai.max_texture_size);
|
||||
list.push_back(std::move(ai));
|
||||
auto devs = MRCTransfer(MTLCopyAllDevices());
|
||||
for (id<MTLDevice> dev in devs.Get())
|
||||
list.push_back(GetMetalAdapterInfo(dev));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto dev = MRCTransfer(MTLCreateSystemDefaultDevice());
|
||||
if (dev.Get())
|
||||
list.push_back(GetMetalAdapterInfo(dev.Get()));
|
||||
}
|
||||
return list;
|
||||
}}
|
||||
@@ -1091,11 +1105,15 @@ bool GSDeviceMTL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
return false;
|
||||
|
||||
NSString* ns_adapter_name = [NSString stringWithUTF8String:GSConfig.Adapter.c_str()];
|
||||
auto devs = MRCTransfer(MTLCopyAllDevices());
|
||||
for (id<MTLDevice> dev in devs.Get())
|
||||
// No device enumeration below iOS 18 — fall through to the default device.
|
||||
if (@available(macOS 10.11, iOS 18.0, *))
|
||||
{
|
||||
if ([[dev name] isEqualToString:ns_adapter_name])
|
||||
m_dev = GSMTLDevice(MRCRetain(dev));
|
||||
auto devs = MRCTransfer(MTLCopyAllDevices());
|
||||
for (id<MTLDevice> dev in devs.Get())
|
||||
{
|
||||
if ([[dev name] isEqualToString:ns_adapter_name])
|
||||
m_dev = GSMTLDevice(MRCRetain(dev));
|
||||
}
|
||||
}
|
||||
if (!m_dev.dev)
|
||||
{
|
||||
|
||||
@@ -132,6 +132,10 @@ void PCAPAdapter::reloadSettings() {}
|
||||
// On iOS, CocoaTools.mm is excluded from the build. Provide stubs for the
|
||||
// functions referenced by iOS-compiled core code (DynamicLibrary, WindowInfo,
|
||||
// Pcsx2Config, etc.). iOS uses UIKit/Foundation, not Cocoa/AppKit.
|
||||
//
|
||||
// CreateMetalLayer, DestroyMetalLayer and GetBundlePath are deliberately absent:
|
||||
// the app's HostImpls.mm implements them for real. Defining them here too gave the
|
||||
// linker two of each and it picked one on its own.
|
||||
#include "common/CocoaTools.h"
|
||||
#include "common/WindowInfo.h"
|
||||
#include <optional>
|
||||
@@ -139,11 +143,8 @@ void PCAPAdapter::reloadSettings() {}
|
||||
|
||||
namespace CocoaTools
|
||||
{
|
||||
bool CreateMetalLayer(WindowInfo* wi) { return false; }
|
||||
void DestroyMetalLayer(WindowInfo* wi) {}
|
||||
std::optional<float> GetViewRefreshRate(const WindowInfo& wi) { return std::nullopt; }
|
||||
void MarkHelpMenu(void* menu) {}
|
||||
std::optional<std::string> GetBundlePath() { return std::nullopt; }
|
||||
std::optional<std::string> GetNonTranslocatedBundlePath() { return std::nullopt; }
|
||||
std::optional<std::string> MoveToTrash(std::string_view file) { return std::nullopt; }
|
||||
bool DelayedLaunch(std::string_view file) { return false; }
|
||||
|
||||
@@ -764,27 +764,27 @@ namespace FileSystem {
|
||||
namespace CocoaTools {
|
||||
void InhibitAppNap(const std::string&) {}
|
||||
void UninhibitAppNap() {}
|
||||
std::string GetBundlePath() { return [[NSBundle mainBundle].bundlePath UTF8String]; }
|
||||
// Signature must match common/CocoaTools.h (not included here, it's mostly
|
||||
// macOS-only). Return types aren't mangled, so a mismatch still links and
|
||||
// callers read garbage off the stack.
|
||||
std::optional<std::string> GetBundlePath() { return std::string([[NSBundle mainBundle].bundlePath UTF8String]); }
|
||||
|
||||
void* CreateMetalLayer(WindowInfo* wi) {
|
||||
if (!Host::g_sdl_window) return nullptr;
|
||||
|
||||
// Return existing layer if we already have it
|
||||
if (wi->surface_handle) {
|
||||
return SDL_Metal_GetLayer((SDL_MetalView)wi->surface_handle);
|
||||
}
|
||||
|
||||
bool CreateMetalLayer(WindowInfo* wi) {
|
||||
if (!Host::g_sdl_window) return false;
|
||||
|
||||
// Already have one
|
||||
if (wi->surface_handle) return true;
|
||||
|
||||
// Create the Metal view
|
||||
SDL_MetalView view = SDL_Metal_CreateView(Host::g_sdl_window);
|
||||
if (!view) {
|
||||
Console.Error("SDL_Metal_CreateView failed: %s", SDL_GetError());
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
void* layer = SDL_Metal_GetLayer(view);
|
||||
|
||||
wi->surface_handle = view; // Store view handle to destroy later
|
||||
Console.WriteLn("Created Metal Layer: %p from View: %p", layer, view);
|
||||
return layer;
|
||||
Console.WriteLn("Created Metal Layer: %p from View: %p", SDL_Metal_GetLayer(view), view);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DestroyMetalLayer(WindowInfo* wi) {
|
||||
|
||||
Reference in New Issue
Block a user