master ohmu/fastfetch-openbsd / src / detection / gpu / gpu_mthreads.c
ohmu  ·  2026-10-15
  1#include "gpu_driver_specific.h"
  2
  3#include "common/library.h"
  4#include "mtml.h"
  5
  6struct FFMtmlData {
  7    FF_LIBRARY_SYMBOL(mtmlDeviceCountGpuCores)
  8    FF_LIBRARY_SYMBOL(mtmlDeviceGetBrand)
  9    FF_LIBRARY_SYMBOL(mtmlDeviceGetIndex)
 10    FF_LIBRARY_SYMBOL(mtmlDeviceGetName)
 11    FF_LIBRARY_SYMBOL(mtmlDeviceGetPciInfo)
 12    FF_LIBRARY_SYMBOL(mtmlDeviceGetUUID)
 13    FF_LIBRARY_SYMBOL(mtmlDeviceInitGpu)
 14    FF_LIBRARY_SYMBOL(mtmlDeviceInitMemory)
 15    FF_LIBRARY_SYMBOL(mtmlGpuGetMaxClock)
 16    FF_LIBRARY_SYMBOL(mtmlGpuGetTemperature)
 17    FF_LIBRARY_SYMBOL(mtmlGpuGetUtilization)
 18    FF_LIBRARY_SYMBOL(mtmlLibraryCountDevice)
 19    FF_LIBRARY_SYMBOL(mtmlLibraryInitDeviceByIndex)
 20    FF_LIBRARY_SYMBOL(mtmlLibraryInitDeviceByPciSbdf)
 21    FF_LIBRARY_SYMBOL(mtmlLibraryInitSystem)
 22    FF_LIBRARY_SYMBOL(mtmlMemoryGetTotal)
 23    FF_LIBRARY_SYMBOL(mtmlMemoryGetUsed)
 24    FF_LIBRARY_SYMBOL(mtmlMemoryGetUtilization)
 25    FF_LIBRARY_SYMBOL(mtmlLibraryShutDown)
 26
 27    bool inited;
 28    MtmlLibrary* lib;
 29    MtmlSystem* sys;
 30} mtmlData;
 31
 32[[maybe_unused]] static void shutdownMtml(void) {
 33    mtmlData.ffmtmlLibraryShutDown(mtmlData.lib);
 34}
 35
 36const char* ffDetectMthreadsGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName) {
 37#ifndef FF_DISABLE_DLOPEN
 38
 39    if (!mtmlData.inited) {
 40        mtmlData.inited = true;
 41        FF_LIBRARY_LOAD(libmtml, "dlopen mtml failed", soName, 1);
 42        FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libmtml, mtmlLibraryInit)
 43        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceCountGpuCores)
 44        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetBrand)
 45        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetIndex)
 46        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetName)
 47        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetPciInfo)
 48        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceGetUUID)
 49        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceInitGpu)
 50        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlDeviceInitMemory)
 51        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlGpuGetMaxClock)
 52        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlGpuGetTemperature)
 53        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlGpuGetUtilization)
 54        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryCountDevice)
 55        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryInitDeviceByIndex)
 56        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryInitDeviceByPciSbdf)
 57        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryInitSystem)
 58        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlMemoryGetTotal)
 59        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlMemoryGetUsed)
 60        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlMemoryGetUtilization)
 61        FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libmtml, mtmlData, mtmlLibraryShutDown)
 62
 63        if (ffmtmlLibraryInit(&mtmlData.lib) != MTML_SUCCESS) {
 64            mtmlData.ffmtmlLibraryInitSystem = nullptr;
 65            return "mtmlLibraryInit failed";
 66        }
 67        if (mtmlData.ffmtmlLibraryInitSystem(mtmlData.lib, &mtmlData.sys) != MTML_SUCCESS) {
 68            mtmlData.ffmtmlLibraryShutDown(mtmlData.lib);
 69            mtmlData.ffmtmlLibraryInitSystem = nullptr;
 70            return "mtmlLibraryInitSystem failed";
 71        }
 72        atexit(shutdownMtml);
 73        libmtml = nullptr; // don't close mtml
 74    }
 75
 76    if (mtmlData.ffmtmlLibraryInitSystem == nullptr) {
 77        return "loading mtml library failed";
 78    }
 79
 80    MtmlDevice* device = nullptr;
 81    if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID) {
 82        char pciBusIdStr[32];
 83        snprintf(pciBusIdStr, ARRAY_SIZE(pciBusIdStr) - 1, "%04x:%02x:%02x.%d", cond->pciBusId.domain, cond->pciBusId.bus, cond->pciBusId.device, cond->pciBusId.func);
 84
 85        MtmlReturn ret = mtmlData.ffmtmlLibraryInitDeviceByPciSbdf(mtmlData.lib, pciBusIdStr, &device);
 86        if (ret != MTML_SUCCESS) {
 87            return "mtmlLibraryInitDeviceByPciSbdf() failed";
 88        }
 89    } else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID) {
 90        uint32_t count;
 91        if (mtmlData.ffmtmlLibraryCountDevice(mtmlData.lib, &count) != MTML_SUCCESS) {
 92            return "mtmlLibraryCountDevice() failed";
 93        }
 94
 95        for (uint32_t i = 0; i < count; i++, device = nullptr) {
 96            if (mtmlData.ffmtmlLibraryInitDeviceByIndex(mtmlData.lib, i, &device) != MTML_SUCCESS) {
 97                continue;
 98            }
 99
100            MtmlPciInfo pciInfo;
101            if (mtmlData.ffmtmlDeviceGetPciInfo(device, &pciInfo) != MTML_SUCCESS) {
102                continue;
103            }
104
105            if (pciInfo.pciDeviceId != ((cond->pciDeviceId.deviceId << 16u) | cond->pciDeviceId.vendorId) ||
106                pciInfo.pciSubsystemId != cond->pciDeviceId.subSystemId) {
107                continue;
108            }
109
110            break;
111        }
112        if (!device) {
113            return "Device not found";
114        }
115    } else {
116        return "Unknown condition type";
117    }
118
119    MtmlBrandType brand;
120    if (mtmlData.ffmtmlDeviceGetBrand(device, &brand) == MTML_SUCCESS) {
121        switch (brand) {
122            case MTML_BRAND_MTT:
123                *result.type = FF_GPU_TYPE_DISCRETE;
124                break;
125            default:
126                break;
127        }
128    }
129
130    if (result.index) {
131        unsigned int value;
132        if (mtmlData.ffmtmlDeviceGetIndex(device, &value) == MTML_SUCCESS) {
133            *result.index = value;
134        }
135    }
136
137    if (result.temp) {
138        MtmlGpu* gpu = nullptr;
139        if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS) {
140            uint32_t value;
141            if (mtmlData.ffmtmlGpuGetTemperature(gpu, &value) == MTML_SUCCESS) {
142                *result.temp = value;
143            }
144        }
145    }
146
147    if (result.memory) {
148        MtmlMemory* mem = nullptr;
149        if (mtmlData.ffmtmlDeviceInitMemory(device, &mem) == MTML_SUCCESS) {
150            unsigned long long total;
151            if (mtmlData.ffmtmlMemoryGetTotal(mem, &total) == MTML_SUCCESS) {
152                result.memory->total = total;
153            }
154
155            unsigned long long used;
156            if (mtmlData.ffmtmlMemoryGetUsed(mem, &used) == MTML_SUCCESS) {
157                result.memory->used = used;
158            }
159        }
160    }
161
162    if (result.coreCount) {
163        mtmlData.ffmtmlDeviceCountGpuCores(device, result.coreCount);
164    }
165
166    if (result.frequency) {
167        MtmlGpu* gpu = nullptr;
168        if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS) {
169            uint32_t clockMHz;
170            if (mtmlData.ffmtmlGpuGetMaxClock(gpu, &clockMHz) == MTML_SUCCESS) {
171                *result.frequency = clockMHz;
172            }
173        }
174    }
175
176    if (result.coreUsage) {
177        MtmlGpu* gpu = nullptr;
178        if (mtmlData.ffmtmlDeviceInitGpu(device, &gpu) == MTML_SUCCESS) {
179            unsigned int utilization;
180            if (mtmlData.ffmtmlGpuGetUtilization(gpu, &utilization) == MTML_SUCCESS) {
181                *result.coreUsage = utilization;
182            }
183        }
184    }
185
186    if (result.name) {
187        char name[MTML_DEVICE_NAME_BUFFER_SIZE];
188        if (mtmlData.ffmtmlDeviceGetName(device, name, ARRAY_SIZE(name)) == MTML_SUCCESS) {
189            ffStrbufSetS(result.name, name);
190        }
191    }
192
193    if (result.psCurr || result.psMax) {
194        MtmlPciInfo pciInfo;
195        if (mtmlData.ffmtmlDeviceGetPciInfo(device, &pciInfo) == MTML_SUCCESS) {
196            if (result.psCurr) {
197                result.psCurr->lanes = (uint16_t) pciInfo.pciCurWidth;
198                result.psCurr->gen = (uint16_t) pciInfo.pciCurGen;
199            }
200            if (result.psMax) {
201                result.psMax->lanes = (uint16_t) pciInfo.pciMaxWidth;
202                result.psMax->gen = (uint16_t) pciInfo.pciMaxGen;
203            }
204        }
205    }
206
207    return nullptr;
208
209#else
210
211    FF_UNUSED(cond, result, soName);
212    return "dlopen is disabled";
213
214#endif
215}