feat(macos): add gpu info

This commit is contained in:
utox39
2025-03-03 01:01:54 +01:00
parent dfad29f268
commit 24923b5b11

View File

@@ -1,6 +1,9 @@
const std = @import("std");
const utils = @import("./utils.zig");
const c_libproc = @cImport(@cInclude("libproc.h"));
const c_sysctl = @cImport(@cInclude("sys/sysctl.h"));
const c_iokit = @cImport(@cInclude("IOKit/IOKitLib.h"));
const c_core_foundation = @cImport(@cInclude("CoreFoundation/CoreFoundation.h"));
/// Structure representing system uptime in days, hours, and minutes.
pub const SystemUptime = struct {
@@ -14,6 +17,11 @@ pub const CpuInfo = struct {
cpu_cores: i32,
};
pub const GpuInfo = struct {
gpu_name: []u8,
gpu_cores: i32,
};
/// Returns the current logged-in uesr's username.
/// Uses the environment variable `USER`.
/// The caller is responsible for freeing the allocated memory.
@@ -118,3 +126,83 @@ pub fn getCpuInfo(allocator: std.mem.Allocator) !CpuInfo {
.cpu_cores = n_cpu,
};
}
/// Returns the gpu info.
pub fn getGpuInfo(allocator: std.mem.Allocator) !GpuInfo {
// TODO: add support for non-Apple Silicon Macs
var gpu_info = GpuInfo{
.gpu_name = try allocator.dupe(u8, "Unknown"),
.gpu_cores = 0,
};
// https://developer.apple.com/documentation/iokit/1514687-ioservicematching
const accel_matching_dict = c_iokit.IOServiceMatching("IOAccelerator");
if (accel_matching_dict == null) {
return error.MatchingDictionaryCreationFailed;
}
var iterator: c_iokit.io_iterator_t = undefined;
// https://developer.apple.com/documentation/iokit/1514494-ioservicegetmatchingservices
const result = c_iokit.IOServiceGetMatchingServices(c_iokit.kIOMasterPortDefault, accel_matching_dict, &iterator);
if (result != c_iokit.KERN_SUCCESS) {
return error.ServiceMatchingFailed;
}
defer _ = c_iokit.IOObjectRelease(iterator);
const service = c_iokit.IOIteratorNext(iterator);
if (service != 0) {
defer _ = c_iokit.IOObjectRelease(service);
var properties_ptr: c_iokit.CFMutableDictionaryRef = null;
const properties_ptr_ref: [*c]c_iokit.CFMutableDictionaryRef = &properties_ptr;
// https://developer.apple.com/documentation/iokit/1514310-ioregistryentrycreatecfpropertie
if (c_iokit.IORegistryEntryCreateCFProperties(service, properties_ptr_ref, c_iokit.kCFAllocatorDefault, 0) != c_iokit.KERN_SUCCESS) {
return gpu_info;
}
if (properties_ptr == null) {
return gpu_info;
}
defer c_iokit.CFRelease(properties_ptr);
var name_ref: c_iokit.CFTypeRef = undefined;
var cores_ref: c_iokit.CFTypeRef = undefined;
// CFSTR is a macro and can't be translated by Zig
// The CFString is created "manually"
const model_key = c_iokit.CFStringCreateWithCString(c_iokit.kCFAllocatorDefault, "model", c_iokit.kCFStringEncodingUTF8);
if (model_key == null) return gpu_info;
defer c_iokit.CFRelease(model_key);
if (c_iokit.CFDictionaryGetValueIfPresent(@as(c_iokit.CFDictionaryRef, @ptrCast(properties_ptr)), model_key, &name_ref) == c_iokit.TRUE) {
if (c_iokit.CFGetTypeID(name_ref) == c_iokit.CFStringGetTypeID()) {
const accel_name = utils.cfStringToZigString(allocator, @as(c_iokit.CFStringRef, @ptrCast(name_ref))) catch {
return gpu_info;
};
allocator.free(gpu_info.gpu_name);
gpu_info.gpu_name = accel_name;
}
}
// CFSTR is a macro and can't be translated by Zig
// The CFString is created "manually"
const gpu_core_count_key = c_iokit.CFStringCreateWithCString(c_iokit.kCFAllocatorDefault, "gpu-core-count", c_iokit.kCFStringEncodingUTF8);
if (gpu_core_count_key == null) return gpu_info;
defer c_iokit.CFRelease(gpu_core_count_key);
if (c_iokit.CFDictionaryGetValueIfPresent(@as(c_iokit.CFDictionaryRef, @ptrCast(properties_ptr)), gpu_core_count_key, &cores_ref) == c_iokit.TRUE) {
if (c_iokit.CFGetTypeID(cores_ref) == c_core_foundation.CFNumberGetTypeID()) {
var cores_num: i32 = 0;
if (c_core_foundation.CFNumberGetValue(@as(c_core_foundation.CFNumberRef, @ptrCast(cores_ref)), c_core_foundation.kCFNumberIntType, &cores_num) == c_core_foundation.TRUE) {
gpu_info.gpu_cores = cores_num;
}
}
}
}
return gpu_info;
}