diff options
| author | sumuel <samuel@yakubos.org> | 2026-08-17 20:44:55 +0000 |
|---|---|---|
| committer | sumuel <samuel@yakubos.org> | 2026-08-17 20:44:55 +0000 |
| commit | 76424950e373d3b04ac3dd13019151bfba3e8423 (patch) | |
| tree | 4c3cfdbda039e592b9186be3e28f8d7cfd439e8a /src/detection/gpu/gpu_amd.c | |
Add the files
Diffstat (limited to 'src/detection/gpu/gpu_amd.c')
| -rw-r--r-- | src/detection/gpu/gpu_amd.c | 460 |
1 files changed, 460 insertions, 0 deletions
diff --git a/src/detection/gpu/gpu_amd.c b/src/detection/gpu/gpu_amd.c new file mode 100644 index 0000000..f396def --- /dev/null +++ b/src/detection/gpu/gpu_amd.c @@ -0,0 +1,460 @@ +#include "gpu_driver_specific.h" + +#include "adl.h" +#include "common/library.h" +#include "common/mallocHelper.h" +#include "common/debug.h" + +// Helper function to convert ADL status code to string +FF_A_UNUSED static const char* ffAdlStatusToString(int status) { + switch (status) { +#define FF_ADL_STATUS_CASE(name) \ + case name: \ + return #name; + FF_ADL_STATUS_CASE(ADL_OK) + FF_ADL_STATUS_CASE(ADL_OK_WARNING) + FF_ADL_STATUS_CASE(ADL_OK_MODE_CHANGE) + FF_ADL_STATUS_CASE(ADL_OK_RESTART) + FF_ADL_STATUS_CASE(ADL_OK_WAIT) + FF_ADL_STATUS_CASE(ADL_ERR) + FF_ADL_STATUS_CASE(ADL_ERR_NOT_INIT) + FF_ADL_STATUS_CASE(ADL_ERR_INVALID_PARAM) + FF_ADL_STATUS_CASE(ADL_ERR_INVALID_PARAM_SIZE) + FF_ADL_STATUS_CASE(ADL_ERR_INVALID_ADL_IDX) + FF_ADL_STATUS_CASE(ADL_ERR_INVALID_CONTROLLER_IDX) + FF_ADL_STATUS_CASE(ADL_ERR_INVALID_DIPLAY_IDX) + FF_ADL_STATUS_CASE(ADL_ERR_NOT_SUPPORTED) + FF_ADL_STATUS_CASE(ADL_ERR_NULL_POINTER) + FF_ADL_STATUS_CASE(ADL_ERR_DISABLED_ADAPTER) + FF_ADL_STATUS_CASE(ADL_ERR_INVALID_CALLBACK) + FF_ADL_STATUS_CASE(ADL_ERR_RESOURCE_CONFLICT) + FF_ADL_STATUS_CASE(ADL_ERR_SET_INCOMPLETE) + FF_ADL_STATUS_CASE(ADL_ERR_NO_XDISPLAY) + FF_ADL_STATUS_CASE(ADL_ERR_CALL_TO_INCOMPATIABLE_DRIVER) + FF_ADL_STATUS_CASE(ADL_ERR_NO_ADMINISTRATOR_PRIVILEGES) + FF_ADL_STATUS_CASE(ADL_ERR_FEATURESYNC_NOT_STARTED) + FF_ADL_STATUS_CASE(ADL_ERR_INVALID_POWER_STATE) +#undef FF_ADL_STATUS_CASE + default: + return "Unknown ADL error"; + } +} + +// Memory allocation function +static void* __stdcall ffAdlMainMemoryAlloc(int iSize) { + return malloc((size_t) iSize); +} + +struct FFAdlData { + FF_LIBRARY_SYMBOL(ADL2_Main_Control_Destroy) + FF_LIBRARY_SYMBOL(ADL2_Adapter_AdapterInfoX3_Get) + FF_LIBRARY_SYMBOL(ADL2_Adapter_Graphic_Core_Info_Get) + FF_LIBRARY_SYMBOL(ADL2_Adapter_MemoryInfo2_Get) + FF_LIBRARY_SYMBOL(ADL2_Adapter_DedicatedVRAMUsage_Get) + FF_LIBRARY_SYMBOL(ADL2_Adapter_ASICFamilyType_Get) + FF_LIBRARY_SYMBOL(ADL2_Overdrive_Caps) + FF_LIBRARY_SYMBOL(ADL2_OverdriveN_CapabilitiesX2_Get) + FF_LIBRARY_SYMBOL(ADL2_OverdriveN_SystemClocksX2_Get) + FF_LIBRARY_SYMBOL(ADL2_OverdriveN_PerformanceStatus_Get) + FF_LIBRARY_SYMBOL(ADL2_OverdriveN_Temperature_Get) + FF_LIBRARY_SYMBOL(ADL2_Overdrive8_Current_Setting_Get) + FF_LIBRARY_SYMBOL(ADL2_New_QueryPMLogData_Get) + FF_LIBRARY_SYMBOL(ADL2_Overdrive6_CurrentStatus_Get) + FF_LIBRARY_SYMBOL(ADL2_Overdrive6_Temperature_Get) + FF_LIBRARY_SYMBOL(ADL2_Overdrive6_StateInfo_Get) + + bool inited; + ADL_CONTEXT_HANDLE apiHandle; +} adlData; + +static void shutdownAdl() { + if (adlData.apiHandle) { + FF_DEBUG("Destroying ADL context"); + adlData.ffADL2_Main_Control_Destroy(adlData.apiHandle); + adlData.apiHandle = NULL; + } +} + +const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName) { + FF_DEBUG("Attempting to detect AMD GPU info using '%s'", soName); + + if (!adlData.inited) { + adlData.inited = true; + FF_DEBUG("Initializing ADL library"); + FF_LIBRARY_LOAD(atiadl, "dlopen atiadlxx failed", soName, 1); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(atiadl, ADL2_Main_Control_Create) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Main_Control_Destroy) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_AdapterInfoX3_Get) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_Graphic_Core_Info_Get) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_MemoryInfo2_Get) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_DedicatedVRAMUsage_Get) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_ASICFamilyType_Get) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Overdrive_Caps) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_OverdriveN_CapabilitiesX2_Get) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_OverdriveN_SystemClocksX2_Get) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_OverdriveN_PerformanceStatus_Get) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Overdrive8_Current_Setting_Get) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_New_QueryPMLogData_Get) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_OverdriveN_Temperature_Get) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Overdrive6_CurrentStatus_Get) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Overdrive6_Temperature_Get) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Overdrive6_StateInfo_Get) + FF_DEBUG("ADL library loaded"); + + int result = ffADL2_Main_Control_Create(ffAdlMainMemoryAlloc, 1 /*iEnumConnectedAdapters*/, &adlData.apiHandle); + FF_DEBUG("ADL2_Main_Control_Create returned %s (%d)", ffAdlStatusToString(result), result); + if (result != ADL_OK) { + return "ffADL2_Main_Control_Create() failed"; + } + + atexit(shutdownAdl); + atiadl = NULL; // don't close atiadl + FF_DEBUG("ADL initialization complete"); + } + + if (!adlData.apiHandle) { + FF_DEBUG("ADL context not initialized"); + return "ffADL2_Main_Control_Create() failed"; + } + + FF_AUTO_FREE AdapterInfo* devices = NULL; + int numDevices = 0; + int adapterResult = adlData.ffADL2_Adapter_AdapterInfoX3_Get(adlData.apiHandle, -1, &numDevices, &devices); + FF_DEBUG("ADL2_Adapter_AdapterInfoX3_Get returned %s (%d)", ffAdlStatusToString(adapterResult), adapterResult); + + if (adapterResult == ADL_OK) { + FF_DEBUG("found %d adapters", numDevices); + } else { + FF_DEBUG("ffADL2_Adapter_AdapterInfoX3_Get() failed"); + return "ffADL2_Adapter_AdapterInfoX3_Get() failed"; + } + + const AdapterInfo* device = NULL; + for (int iDev = 0; iDev < numDevices; iDev++) { + if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID) { + FF_DEBUG("Checking device %d: bus=%d, device=%d, func=%d against requested bus=%u, device=%u, func=%u", + iDev, + devices[iDev].iBusNumber, + devices[iDev].iDeviceNumber, + devices[iDev].iFunctionNumber, + cond->pciBusId.bus, + cond->pciBusId.device, + cond->pciBusId.func); + + if ( + cond->pciBusId.bus == (uint32_t) devices[iDev].iBusNumber && + cond->pciBusId.device == (uint32_t) devices[iDev].iDeviceNumber && + cond->pciBusId.func == (uint32_t) devices[iDev].iFunctionNumber) { + device = &devices[iDev]; + FF_DEBUG("Found matching device: %s (index: %d)", device->strAdapterName, device->iAdapterIndex); + break; + } + } + } + + if (!device) { + FF_DEBUG("Device not found"); + return "Device not found"; + } + + if (result.coreCount) { + ADLGraphicCoreInfo coreInfo; + int status = adlData.ffADL2_Adapter_Graphic_Core_Info_Get(adlData.apiHandle, device->iAdapterIndex, &coreInfo); + FF_DEBUG("ADL2_Adapter_Graphic_Core_Info_Get returned %s (%d)", ffAdlStatusToString(status), status); + + if (status == ADL_OK) { + FF_DEBUG("Core info - NumCUs: %d, NumPEsPerCU: %d", coreInfo.iNumCUs, coreInfo.iNumPEsPerCU); + *result.coreCount = (uint32_t) coreInfo.iNumCUs * (uint32_t) coreInfo.iNumPEsPerCU; + FF_DEBUG("Got core count: %u", *result.coreCount); + } else { + FF_DEBUG("Failed to get core count"); + } + } + + if (result.memory) { + int vramUsage = 0; + int status = adlData.ffADL2_Adapter_DedicatedVRAMUsage_Get(adlData.apiHandle, device->iAdapterIndex, &vramUsage); + FF_DEBUG("ADL2_Adapter_DedicatedVRAMUsage_Get returned %s (%d), usage: %d MB", + ffAdlStatusToString(status), + status, + vramUsage); + + if (status == ADL_OK && vramUsage >= 0) { + result.memory->used = (uint64_t) vramUsage * 1024 * 1024; + FF_DEBUG("Dedicated VRAM usage: %llu bytes (%d MB)", result.memory->used, vramUsage); + } else { + FF_DEBUG("Failed to get dedicated VRAM usage"); + } + } + + if (result.memoryType) { + ADLMemoryInfo2 memoryInfo; + int status = adlData.ffADL2_Adapter_MemoryInfo2_Get(adlData.apiHandle, device->iAdapterIndex, &memoryInfo); + FF_DEBUG("ADL2_Adapter_MemoryInfo2_Get returned %s (%d)", ffAdlStatusToString(status), status); + + if (status == ADL_OK) { + FF_DEBUG("Memory info - Type: %s, Size: %lld MB", memoryInfo.strMemoryType, memoryInfo.iMemorySize / 1024 / 1024); + ffStrbufSetS(result.memoryType, memoryInfo.strMemoryType); + FF_DEBUG("Got memory type: %s", memoryInfo.strMemoryType); + } else { + FF_DEBUG("Failed to get memory type"); + } + } + + if (result.type) { + int asicTypes = 0; + int valids = 0; + int status = adlData.ffADL2_Adapter_ASICFamilyType_Get(adlData.apiHandle, device->iAdapterIndex, &asicTypes, &valids); + FF_DEBUG("ADL2_Adapter_ASICFamilyType_Get returned %s (%d), asicTypes: 0x%x, valids: 0x%x", + ffAdlStatusToString(status), + status, + asicTypes, + valids); + + if (status == ADL_OK) { + asicTypes &= valids; // This design is strange + *result.type = asicTypes & ADL_ASIC_INTEGRATED ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + FF_DEBUG("GPU type: %s (asicTypes: 0x%x, valids: 0x%x)", + *result.type == FF_GPU_TYPE_INTEGRATED ? "Integrated" : "Discrete", + asicTypes, + valids); + } else { + FF_DEBUG("Failed to get GPU type"); + } + } + + if (result.index) { + *result.index = (uint32_t) device->iAdapterIndex; + FF_DEBUG("Setting adapter index: %u", *result.index); + } + + if (result.name) { + ffStrbufSetS(result.name, device->strAdapterName); + FF_DEBUG("Setting adapter name: %s; UDID: %s, Present: %d, Exist: %d", device->strAdapterName, device->strUDID, device->iPresent, device->iExist); + } + + int odVersion = 0; + + { + int odSupported = 0; + int odEnabled = 0; + int status = adlData.ffADL2_Overdrive_Caps(adlData.apiHandle, device->iAdapterIndex, &odSupported, &odEnabled, &odVersion); + FF_DEBUG("ADL2_Overdrive_Caps returned %s (%d); supported %d, enabled %d; version %d", + ffAdlStatusToString(status), + status, + odSupported, + odEnabled, + odVersion); + if (status != ADL_OK) { + FF_DEBUG("Overdrive not supported, results may be inaccurate"); + // Note even if Overdrive is not supported, we can still get the OD version + } + } + + if (odVersion == 8) { + FF_DEBUG("Using Overdrive8 API (odVersion=%d)", odVersion); + + if (result.frequency) { + ADLOD8CurrentSetting currentSetting = { .count = OD8_COUNT }; + int status = adlData.ffADL2_Overdrive8_Current_Setting_Get(adlData.apiHandle, device->iAdapterIndex, ¤tSetting); + FF_DEBUG("ADL2_Overdrive8_Current_Setting_Get returned %s (%d)", ffAdlStatusToString(status), status); + if (status == ADL_OK) { + FF_DEBUG("OD8 Settings count: %d", currentSetting.count); + + *result.frequency = (uint32_t) currentSetting.Od8SettingTable[OD8_GFXCLK_FMAX]; + FF_DEBUG("Got max engine clock (OD8_GFXCLK_FMAX): %u MHz", *result.frequency); + } else { + FF_DEBUG("Failed to get max frequency information"); + } + } + + if (result.temp || result.coreUsage) { + ADLPMLogDataOutput pmLogDataOutput = {}; + int status = adlData.ffADL2_New_QueryPMLogData_Get(adlData.apiHandle, device->iAdapterIndex, &pmLogDataOutput); + FF_DEBUG("ADL2_New_QueryPMLogData_Get returned %s (%d)", ffAdlStatusToString(status), status); + if (status == ADL_OK) { + if (result.temp) { + ADLSingleSensorData* sensor = &pmLogDataOutput.sensors[ADL_PMLOG_TEMPERATURE_HOTSPOT]; + FF_DEBUG("Sensor %d: %s, supported: %d, value: %d", ADL_PMLOG_TEMPERATURE_HOTSPOT, "ADL_PMLOG_TEMPERATURE_HOTSPOT", sensor->supported, sensor->value); + if (sensor->supported) { + *result.temp = sensor->value; + FF_DEBUG("Temperature: %.1f°C (HOTSPOT)", *result.temp); + } else { + sensor = &pmLogDataOutput.sensors[ADL_PMLOG_TEMPERATURE_GFX]; + FF_DEBUG("Sensor %d: %s, supported: %d, value: %d", ADL_PMLOG_TEMPERATURE_GFX, "ADL_PMLOG_TEMPERATURE_GFX", sensor->supported, sensor->value); + if (sensor->supported) { + *result.temp = sensor->value; + FF_DEBUG("Temperature: %.1f°C (GFX)", *result.temp); + } else { + sensor = &pmLogDataOutput.sensors[ADL_PMLOG_TEMPERATURE_SOC]; + FF_DEBUG("Sensor %d: %s, supported: %d, value: %d", ADL_PMLOG_TEMPERATURE_SOC, "ADL_PMLOG_TEMPERATURE_SOC", sensor->supported, sensor->value); + if (sensor->supported) { + *result.temp = sensor->value; + FF_DEBUG("Temperature: %.1f°C (SOC)", *result.temp); + } else { + FF_DEBUG("No supported temp sensor found, temp detection failed"); + } + } + } + } + if (result.coreUsage) { + ADLSingleSensorData* activity = &pmLogDataOutput.sensors[ADL_PMLOG_INFO_ACTIVITY_GFX]; + FF_DEBUG("Sensor %d: %s, supported: %d, value: %d", ADL_PMLOG_INFO_ACTIVITY_GFX, "ADL_PMLOG_INFO_ACTIVITY_GFX", activity->supported, activity->value); + if (activity->supported) { + *result.coreUsage = activity->value; + FF_DEBUG("Core usage: %.1f%%", *result.coreUsage); + } else { + FF_DEBUG("Sensor %d not supported, GPU usage detection failed", ADL_PMLOG_INFO_ACTIVITY_GFX); + } + } + } else { + FF_DEBUG("Failed to get temperature / GPU activity"); + } + } + } else if (odVersion == 7) { + FF_DEBUG("Using OverdriveN API (odVersion=%d)", odVersion); + + if (result.frequency) { + // https://github.com/MaynardMiner/odvii/blob/master/OverdriveN.cpp#L176 + ADLODNCapabilitiesX2 odCapabilities = {}; + int status = adlData.ffADL2_OverdriveN_CapabilitiesX2_Get(adlData.apiHandle, device->iAdapterIndex, &odCapabilities); + FF_DEBUG("ADL2_OverdriveN_CapabilitiesX2_Get returned %s (%d)", ffAdlStatusToString(status), status); + + if (status == ADL_OK) { + if (odCapabilities.iMaximumNumberOfPerformanceLevels == 0) { + FF_DEBUG("ADL2_OverdriveN_CapabilitiesX2_Get: no performance levels available"); + } else { + FF_DEBUG("ODN Capabilities - MaxPerformanceLevels: %d, GPU Clock Range: [%d - %d]", + odCapabilities.iMaximumNumberOfPerformanceLevels, + odCapabilities.sEngineClockRange.iMin, + odCapabilities.sEngineClockRange.iMax); + + size_t size = sizeof(ADLODNPerformanceLevelsX2) + sizeof(ADLODNPerformanceLevelX2) * ((unsigned) odCapabilities.iMaximumNumberOfPerformanceLevels - 1); + FF_AUTO_FREE ADLODNPerformanceLevelsX2* odPerfLevels = calloc(size, 1); + odPerfLevels->iSize = (int) size; + odPerfLevels->iNumberOfPerformanceLevels = odCapabilities.iMaximumNumberOfPerformanceLevels; + odPerfLevels->iMode = ODNControlType_Current; + + int status = adlData.ffADL2_OverdriveN_SystemClocksX2_Get(adlData.apiHandle, device->iAdapterIndex, odPerfLevels); + FF_DEBUG("ADL2_OverdriveN_SystemClocksX2_Get returned %s (%d), levels: %d", + ffAdlStatusToString(status), + status, + odPerfLevels->iNumberOfPerformanceLevels); + + if (status != ADL_OK) { + FF_DEBUG("Failed to get frequency information"); + } else { + // lowest to highest + for (int i = odPerfLevels->iNumberOfPerformanceLevels - 1; i >= 0; i--) { + ADLODNPerformanceLevelX2* level = &odPerfLevels->aLevels[i]; + FF_DEBUG("Performance level %d: enabled: %d, engine clock = %d", i, level->iEnabled, level->iClock); + if (level->iEnabled) { + *result.frequency = (uint32_t) level->iClock / 100; // in 10 kHz + FF_DEBUG("Got max engine clock: %u MHz", *result.frequency); + break; + } + } + } + } + } else { + FF_DEBUG("Failed to get frequency information"); + } + } + + if (result.coreUsage) { + ADLODNPerformanceStatus performanceStatus = {}; + int status = adlData.ffADL2_OverdriveN_PerformanceStatus_Get(adlData.apiHandle, device->iAdapterIndex, &performanceStatus); + FF_DEBUG("ADL2_OverdriveN_PerformanceStatus_Get returned %s (%d)", ffAdlStatusToString(status), status); + + if (status == ADL_OK) { + FF_DEBUG("Performance Status - Activity: %d%%, CoreClock: %dMHz, MemoryClock: %dMHz", + performanceStatus.iGPUActivityPercent, + performanceStatus.iCoreClock, + performanceStatus.iMemoryClock); + + *result.coreUsage = performanceStatus.iGPUActivityPercent; + FF_DEBUG("Got GPU activity: %d%%", performanceStatus.iGPUActivityPercent); + } else { + FF_DEBUG("Failed to get GPU activity"); + } + } + + if (result.temp) { + int milliDegrees = 0; + int status = adlData.ffADL2_OverdriveN_Temperature_Get(adlData.apiHandle, device->iAdapterIndex, 1, &milliDegrees); + FF_DEBUG("ADL2_OverdriveN_Temperature_Get returned %s (%d)", ffAdlStatusToString(status), status); + + if (status == ADL_OK) { + *result.temp = milliDegrees / 1000.0; + FF_DEBUG("Temperature: %.1f°C (raw: %d milliC)", *result.temp, milliDegrees); + } else { + FF_DEBUG("Failed to get temperature"); + } + } + } else if (odVersion == 6) { + FF_DEBUG("Using Overdrive6 API (odVersion=%d)", odVersion); + + if (result.frequency) { + FF_AUTO_FREE ADLOD6StateInfo* stateInfo = calloc(sizeof(ADLOD6StateInfo) + sizeof(ADLOD6PerformanceLevel), 1); + stateInfo->iNumberOfPerformanceLevels = 2; + + int status = adlData.ffADL2_Overdrive6_StateInfo_Get(adlData.apiHandle, device->iAdapterIndex, ADL_OD6_GETSTATEINFO_CUSTOM_PERFORMANCE, stateInfo); + FF_DEBUG("ADL2_Overdrive6_StateInfo_Get returned %s (%d), performance levels: %d", + ffAdlStatusToString(status), + status, + stateInfo->iNumberOfPerformanceLevels); + + if (status == ADL_OK) { + // OD6 uses clock ranges instead of discrete performance levels. + // iNumberOfPerformanceLevels is always 2. + // The 1st level indicates the minimum clocks in the range. + // The 2nd level indicates the maximum clocks in the range. + if (stateInfo->iNumberOfPerformanceLevels != 2) { + FF_DEBUG("ADL2_Overdrive6_StateInfo_Get: unexpected number of performance levels: %d", stateInfo->iNumberOfPerformanceLevels); + } else { + FF_DEBUG("OD6 Settings - MinPerformanceLevels: %d, MaxPerformanceLevels: %d", + stateInfo->aLevels[0].iEngineClock, + stateInfo->aLevels[1].iEngineClock); + *result.frequency = (uint32_t) stateInfo->aLevels[1].iEngineClock / 100; // in 10 kHz + FF_DEBUG("Got max engine clock: %u MHz", *result.frequency); + } + } else { + FF_DEBUG("Failed to get frequency information"); + } + } + + if (result.coreUsage) { + ADLOD6CurrentStatus status = {}; + int apiStatus = adlData.ffADL2_Overdrive6_CurrentStatus_Get(adlData.apiHandle, device->iAdapterIndex, &status); + FF_DEBUG("ADL2_Overdrive6_CurrentStatus_Get returned %s (%d)", ffAdlStatusToString(apiStatus), apiStatus); + + if (apiStatus == ADL_OK) { + *result.coreUsage = status.iActivityPercent; + FF_DEBUG("Got GPU activity: %d%%", status.iActivityPercent); + } else { + FF_DEBUG("Failed to get GPU activity"); + } + } + + if (result.temp) { + int milliDegrees = 0; + int status = adlData.ffADL2_Overdrive6_Temperature_Get(adlData.apiHandle, device->iAdapterIndex, &milliDegrees); + FF_DEBUG("ADL2_Overdrive6_Temperature_Get returned %s (%d), temperature: %d milliC", + ffAdlStatusToString(status), + status, + milliDegrees); + + if (status == ADL_OK) { + *result.temp = milliDegrees / 1000.0; + FF_DEBUG("Temperature: %.1f°C", *result.temp); + } else { + FF_DEBUG("Failed to get temperature"); + } + } + } else { + FF_DEBUG("Unknown Overdrive version: %d", odVersion); + return "Unknown Overdrive version"; + } + FF_DEBUG("AMD GPU detection complete - returning success"); + return NULL; +} |