ohmu
·
2026-10-15
1#include "gpu.h"
2
3#import <Metal/MTLDevice.h>
4#import <IOKit/kext/KextManager.h>
5
6#ifndef MAC_OS_VERSION_26_0
7 #define MTLGPUFamilyMetal4 ((MTLGPUFamily) 5002)
8#endif
9#ifndef MAC_OS_VERSION_13_0
10 #define MTLGPUFamilyMetal3 ((MTLGPUFamily) 5001)
11#endif
12#ifndef MAC_OS_X_VERSION_10_15
13 #define MTLFeatureSet_macOS_GPUFamily1_v4 ((MTLFeatureSet) 10004)
14 #define MTLFeatureSet_macOS_GPUFamily2_v1 ((MTLFeatureSet) 10005)
15#endif
16
17const char* ffGpuDetectDriverVersion(FFlist* gpus) {
18 NSMutableArray* arr = NSMutableArray.new;
19 FF_LIST_FOR_EACH (FFGPUResult, x, *gpus) {
20 [arr addObject:@(x->driver.chars)];
21 }
22
23 NSDictionary* dict = CFBridgingRelease(KextManagerCopyLoadedKextInfo((__bridge CFArrayRef) arr, (__bridge CFArrayRef) @[ @"CFBundleVersion" ]));
24 FF_LIST_FOR_EACH (FFGPUResult, x, *gpus) {
25 NSString* version = dict[@(x->driver.chars)][@"CFBundleVersion"];
26 if (version) {
27 ffStrbufAppendC(&x->driver, ' ');
28 ffStrbufAppendS(&x->driver, version.UTF8String);
29 }
30 }
31 return nullptr;
32}
33
34const char* ffGpuDetectMetal(FFlist* gpus) {
35 // Metal.framework is statically linked into the application,
36 // so `MTLCopyAllDevices` is always available, or the application will not start.
37 for (id<MTLDevice> device in MTLCopyAllDevices()) {
38 FFGPUResult* gpu = nullptr;
39 FF_LIST_FOR_EACH (FFGPUResult, x, *gpus) {
40 if (x->deviceId == device.registryID) {
41 gpu = x;
42 break;
43 }
44 }
45 if (!gpu) {
46 continue;
47 }
48
49#pragma clang diagnostic ignored "-Wdeprecated-declarations"
50#ifndef MAC_OS_X_VERSION_10_15
51 if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1]) {
52 ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 2");
53 } else if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1]) {
54 ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 1");
55 }
56#else // MAC_OS_X_VERSION_10_15
57 if ([device supportsFamily:MTLGPUFamilyMetal4]) {
58 ffStrbufSetStatic(&gpu->platformApi, "Metal 4");
59 } else if ([device supportsFamily:MTLGPUFamilyMetal3]) {
60 ffStrbufSetStatic(&gpu->platformApi, "Metal 3");
61 }
62 else if ([device supportsFamily:MTLGPUFamilyCommon3]) {
63 ffStrbufSetStatic(&gpu->platformApi, "Metal Common 3");
64 } else if ([device supportsFamily:MTLGPUFamilyCommon2]) {
65 ffStrbufSetStatic(&gpu->platformApi, "Metal Common 2");
66 } else if ([device supportsFamily:MTLGPUFamilyCommon1]) {
67 ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1");
68 }
69
70 gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
71 gpu->index = (uint32_t) device.locationNumber;
72
73 if (device.hasUnifiedMemory && device.recommendedMaxWorkingSetSize > 0) {
74 gpu->shared.total = device.recommendedMaxWorkingSetSize;
75 }
76#endif
77 }
78 return nullptr;
79}