iOS 在运行时识别金属支撑的代码?

iOS code to identify metal support in runtime?

通常,我使用下面的代码来识别设备的 iOS 版本。

if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0)

以类似的方式,我正在尝试为设备寻找 Metal 支持。配备 A7(或更好)GPU 和 iOS 8.0.

的 Apple 设备支持 Metal

这是我希望我的代码工作的方式:

if (MetalSupported == true) {
  // metal programming
} else {
  // opengles2 programming
}

如何获取布尔变量 MetalSupported 的值?

我认为最好的方法是尝试获得其中一种金属类。

Class metalDeviceClass = NSClassFromString(@"MTLDevice");
BOOL isMetalAvailable = metalDeviceClass != nil;
if (isMetalAvailable) {
    NSLog(@"Metal available");
} else {
    NSLog(@"Metal not available");
}

您正在寻找特定于 Metal 的东西是件好事 — 通常,iOS 版本检查和硬件名称检查很脆弱,因为它们依赖于您的应用了解所有 OS 版本以及可以 运行 它的设备。如果 Apple 返回并发布 iOS 7.x 版本添加了 Metal 支持(好吧,似乎不太可能),或者支持 Metal 但不是您正在寻找的硬件名称之一的设备在(似乎更有可能),您将不得不跟踪所有这些事情并更新您的应用程序以管理它们。

无论如何,最好的方法是检查您正在使用的设备 运行Metal 是否足以支持您出色的图形代码?尝试获取一个 MTLDevice 对象:

id<MTLDevice> device = MTLCreateSystemDefaultDevice();
if (device) {
    // ready to rock 
} else {
    // back to OpenGL
}

请注意,仅测试 Metal 框架 class 的存在并没有帮助 — 这些 classes 在任何设备上都存在 运行ning iOS 8 (一直回到 iPhone 4s & iPad 2),无论该设备是否具有支持 Metal 的 GPU。

在 Simulator 中,从 iOS 13 / tvOS 13 当 运行ning on macOS 10.15 开始支持 Metal。使用相同的策略:调用 MTLCreateSystemDefaultDevice()。如果它 returns 一个对象,那么您的模拟器代码在模拟器是硬件加速的环境中 运行ning。如果它 returns nil 那么你 运行 正在使用较旧的模拟器或在 Metal 不可用的环境中。

Ricster解释清楚了所有在运行时识别支持metal的设备的方法。如果您不能通过包含金属库在 class 中使用 MTLCreateSystemDefaultDevice(),请使用设备信息(iOS 版本,gpu/cpu 体系结构),但您需要考虑 Ricster 解释的所有情况使用设备信息。

void deviceConfigurations(){
        size_t size;
        cpu_type_t type;
        cpu_subtype_t subtype;
        size = sizeof(type);
        sysctlbyname("hw.cputype", &type, &size, NULL, 0);

        size = sizeof(subtype);
        sysctlbyname("hw.cpusubtype", &subtype, &size, NULL, 0);
}

使用子类型和类型变量来识别设备和其他信息。

在 iOS,您应该只检查 MTLCreateSystemDefaultDevice()。如果它 returns 是一个有效的设备,你就可以开始了。在 macOS 上,你需要小心;使用 [MTLCopyAllDevices() count] 确定您是否有可用的受支持金属设备。

您应该避免在 macOS 上使用 MTLCreateSystemDefaultDevice(),因为这会强制将多路复用器切换到独立的 GPU(例如:如果您使用的笔记本电脑可以在独立显卡和集成显卡之间自动切换显卡)。