2022-09-05 17:42:42 +02:00
|
|
|
#include "gpu.h"
|
2022-09-05 13:41:05 -07:00
|
|
|
#include "common/library.h"
|
2022-09-09 05:40:27 -07:00
|
|
|
#include "detection/cpu/cpu.h"
|
2022-09-25 15:23:00 +08:00
|
|
|
#include "detection/temps/temps_apple.h"
|
2022-09-20 16:50:15 +08:00
|
|
|
#include "util/apple/cf_helpers.h"
|
2022-09-05 13:41:05 -07:00
|
|
|
|
|
|
|
|
#include <IOKit/graphics/IOGraphicsLib.h>
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2023-12-29 15:12:41 +08:00
|
|
|
const char* ffGpuDetectMetal(FFlist* gpus);
|
|
|
|
|
|
2022-09-25 15:23:00 +08:00
|
|
|
static double detectGpuTemp(const FFstrbuf* gpuName)
|
|
|
|
|
{
|
2023-08-07 10:15:08 +08:00
|
|
|
double result = 0;
|
2023-12-08 15:59:58 +08:00
|
|
|
const char* error = NULL;
|
2022-09-25 15:23:00 +08:00
|
|
|
|
2023-12-08 15:59:58 +08:00
|
|
|
if (ffStrbufStartsWithS(gpuName, "Apple M"))
|
|
|
|
|
{
|
|
|
|
|
switch (strtol(gpuName->chars + strlen("Apple M"), NULL, 10))
|
|
|
|
|
{
|
2023-12-27 08:46:49 +08:00
|
|
|
case 1: error = ffDetectSmcTemps(FF_TEMP_GPU_M1X, &result); break;
|
|
|
|
|
case 2: error = ffDetectSmcTemps(FF_TEMP_GPU_M2X, &result); break;
|
|
|
|
|
case 3: error = ffDetectSmcTemps(FF_TEMP_GPU_M3X, &result); break;
|
2023-12-08 15:59:58 +08:00
|
|
|
default: error = "Unsupported Apple Silicon GPU";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (ffStrbufStartsWithS(gpuName, "Intel"))
|
2023-12-27 08:46:49 +08:00
|
|
|
error = ffDetectSmcTemps(FF_TEMP_GPU_INTEL, &result);
|
2023-12-08 15:59:58 +08:00
|
|
|
else if (ffStrbufStartsWithS(gpuName, "Radeon") || ffStrbufStartsWithS(gpuName, "AMD"))
|
2023-12-27 08:46:49 +08:00
|
|
|
error = ffDetectSmcTemps(FF_TEMP_GPU_AMD, &result);
|
2022-09-25 15:23:00 +08:00
|
|
|
else
|
2023-12-27 08:46:49 +08:00
|
|
|
error = ffDetectSmcTemps(FF_TEMP_GPU_UNKNOWN, &result);
|
2022-09-25 15:23:00 +08:00
|
|
|
|
2023-12-08 15:59:58 +08:00
|
|
|
if (error)
|
2022-09-25 15:23:00 +08:00
|
|
|
return FF_GPU_TEMP_UNSET;
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-17 15:51:15 +08:00
|
|
|
#ifdef __aarch64__
|
|
|
|
|
#include "util/apple/cf_helpers.h"
|
|
|
|
|
|
|
|
|
|
#include <IOKit/IOKitLib.h>
|
|
|
|
|
|
|
|
|
|
static const char* detectFrequency(FFGPUResult* gpu)
|
|
|
|
|
{
|
|
|
|
|
// https://github.com/giampaolo/psutil/pull/2222/files
|
|
|
|
|
|
|
|
|
|
FF_IOOBJECT_AUTO_RELEASE io_registry_entry_t entryDevice = IOServiceGetMatchingService(MACH_PORT_NULL, IOServiceNameMatching("pmgr"));
|
|
|
|
|
if (!entryDevice)
|
|
|
|
|
return "IOServiceGetMatchingServices() failed";
|
|
|
|
|
|
|
|
|
|
if (!IOObjectConformsTo(entryDevice, "AppleARMIODevice"))
|
|
|
|
|
return "\"pmgr\" should conform to \"AppleARMIODevice\"";
|
|
|
|
|
|
|
|
|
|
FF_CFTYPE_AUTO_RELEASE CFDataRef freqProperty = (CFDataRef) IORegistryEntryCreateCFProperty(entryDevice, CFSTR("voltage-states9-sram"), kCFAllocatorDefault, kNilOptions);
|
|
|
|
|
if (CFGetTypeID(freqProperty) != CFDataGetTypeID())
|
|
|
|
|
return "\"voltage-states9-sram\" in \"pmgr\" is not found";
|
|
|
|
|
|
|
|
|
|
// voltage-states5-sram stores supported <frequency / voltage> pairs of gpu from the lowest to the highest
|
|
|
|
|
CFIndex propLength = CFDataGetLength(freqProperty);
|
|
|
|
|
if (propLength == 0 || propLength % (CFIndex) sizeof(uint32_t) * 2 != 0)
|
|
|
|
|
return "Invalid \"voltage-states9-sram\" length";
|
|
|
|
|
|
|
|
|
|
uint32_t* pStart = (uint32_t*) CFDataGetBytePtr(freqProperty);
|
|
|
|
|
uint32_t pMax = *pStart;
|
|
|
|
|
for (CFIndex i = 2; i < propLength / (CFIndex) sizeof(uint32_t) && pStart[i] > 0; i += 2 /* skip voltage */)
|
|
|
|
|
pMax = pMax > pStart[i] ? pMax : pStart[i];
|
|
|
|
|
|
|
|
|
|
if (pMax > 0)
|
|
|
|
|
gpu->frequency = pMax / 1000 / 1000;
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
2022-09-05 17:42:42 +02:00
|
|
|
{
|
2024-01-05 14:47:30 +08:00
|
|
|
FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = IO_OBJECT_NULL;
|
|
|
|
|
if (IOServiceGetMatchingServices(MACH_PORT_NULL, IOServiceMatching(kIOAcceleratorClassName), &iterator) != kIOReturnSuccess)
|
2022-09-16 18:11:39 +08:00
|
|
|
return "IOServiceGetMatchingServices() failed";
|
2022-09-05 13:41:05 -07:00
|
|
|
|
|
|
|
|
io_registry_entry_t registryEntry;
|
2024-01-05 14:47:30 +08:00
|
|
|
while ((registryEntry = IOIteratorNext(iterator)) != IO_OBJECT_NULL)
|
2022-09-05 13:41:05 -07:00
|
|
|
{
|
2022-09-06 02:28:32 -07:00
|
|
|
CFMutableDictionaryRef properties;
|
2022-09-14 14:55:28 +02:00
|
|
|
if(IORegistryEntryCreateCFProperties(registryEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
2022-09-06 02:28:32 -07:00
|
|
|
{
|
2022-09-14 14:55:28 +02:00
|
|
|
IOObjectRelease(registryEntry);
|
2022-09-06 02:28:32 -07:00
|
|
|
continue;
|
|
|
|
|
}
|
2022-09-05 13:41:05 -07:00
|
|
|
|
|
|
|
|
FFGPUResult* gpu = ffListAdd(gpus);
|
|
|
|
|
|
2023-02-11 12:34:57 +08:00
|
|
|
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
2023-01-12 11:41:07 +01:00
|
|
|
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
2023-12-20 14:45:27 +08:00
|
|
|
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
2023-12-29 15:12:41 +08:00
|
|
|
IORegistryEntryGetRegistryEntryID(registryEntry, &gpu->deviceId);
|
|
|
|
|
ffStrbufInitStatic(&gpu->platformApi, "Metal");
|
2023-01-12 11:41:07 +01:00
|
|
|
|
2023-06-25 23:35:51 +08:00
|
|
|
ffStrbufInit(&gpu->driver); // Ok for both Apple and Intel
|
2022-09-17 02:17:27 +08:00
|
|
|
ffCfDictGetString(properties, CFSTR("CFBundleIdentifier"), &gpu->driver);
|
2022-09-16 18:11:39 +08:00
|
|
|
|
2023-06-25 23:35:51 +08:00
|
|
|
if(ffCfDictGetInt(properties, CFSTR("gpu-core-count"), &gpu->coreCount)) // For Apple
|
|
|
|
|
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
|
|
|
|
|
2022-09-17 00:35:07 +08:00
|
|
|
ffStrbufInit(&gpu->name);
|
2023-06-25 23:35:51 +08:00
|
|
|
//IOAccelerator returns model / vendor-id properties for Apple Silicon, but not for Intel Iris GPUs.
|
2022-09-17 00:35:07 +08:00
|
|
|
//Still needs testing for AMD's
|
2022-09-20 16:50:15 +08:00
|
|
|
if(ffCfDictGetString(properties, CFSTR("model"), &gpu->name))
|
2022-09-17 02:59:07 +08:00
|
|
|
{
|
|
|
|
|
CFRelease(properties);
|
|
|
|
|
|
|
|
|
|
io_registry_entry_t parentEntry;
|
|
|
|
|
IORegistryEntryGetParentEntry(registryEntry, kIOServicePlane, &parentEntry);
|
|
|
|
|
if(IORegistryEntryCreateCFProperties(parentEntry, &properties, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess)
|
|
|
|
|
{
|
|
|
|
|
IOObjectRelease(parentEntry);
|
|
|
|
|
IOObjectRelease(registryEntry);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
ffCfDictGetString(properties, CFSTR("model"), &gpu->name);
|
|
|
|
|
}
|
2022-09-17 00:35:07 +08:00
|
|
|
|
2023-06-25 23:35:51 +08:00
|
|
|
ffStrbufInit(&gpu->vendor);
|
|
|
|
|
int vendorId;
|
|
|
|
|
if(!ffCfDictGetInt(properties, CFSTR("vendor-id"), &vendorId))
|
|
|
|
|
{
|
|
|
|
|
const char* vendorStr = ffGetGPUVendorString((unsigned) vendorId);
|
|
|
|
|
ffStrbufAppendS(&gpu->vendor, vendorStr);
|
|
|
|
|
if (vendorStr == FF_GPU_VENDOR_NAME_APPLE || vendorStr == FF_GPU_VENDOR_NAME_INTEL)
|
|
|
|
|
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
|
|
|
|
else if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA || vendorStr == FF_GPU_VENDOR_NAME_AMD)
|
|
|
|
|
gpu->type = FF_GPU_TYPE_DISCRETE;
|
2024-07-17 15:51:15 +08:00
|
|
|
|
|
|
|
|
#ifdef __aarch64__
|
|
|
|
|
if (vendorStr == FF_GPU_VENDOR_NAME_APPLE)
|
|
|
|
|
detectFrequency(gpu);
|
|
|
|
|
#endif
|
2023-06-25 23:35:51 +08:00
|
|
|
}
|
2022-09-17 00:35:07 +08:00
|
|
|
|
2023-08-07 10:15:08 +08:00
|
|
|
gpu->temperature = options->temp ? detectGpuTemp(&gpu->name) : FF_GPU_TEMP_UNSET;
|
2022-09-06 02:28:32 -07:00
|
|
|
|
2022-09-14 14:55:28 +02:00
|
|
|
CFRelease(properties);
|
|
|
|
|
IOObjectRelease(registryEntry);
|
2022-09-05 13:41:05 -07:00
|
|
|
}
|
|
|
|
|
|
2023-12-29 15:12:41 +08:00
|
|
|
ffGpuDetectMetal(gpus);
|
2022-09-16 18:11:39 +08:00
|
|
|
return NULL;
|
2022-09-05 17:42:42 +02:00
|
|
|
}
|