From 0c3ebb1933d10bf274715302a7cdac971e80a0ba Mon Sep 17 00:00:00 2001 From: Emerson Pinter Date: Sat, 27 Apr 2024 08:47:50 -0300 Subject: [PATCH] Refactor ADL sensors update (#1317) * Refactor ADL sensors update - Check support for each sensor, on OD8 and new PMLog. - Exclude cards before Vega10 from using PMLog - Better validation for individual sensor support (for now asic-power/board-power) - Validate pmlog struct using the lastUpdate, there are situations the sensors values are corrupted, maybe because something blocking the pointer access to the struct, but this needs to be verified. * Update AmdGpu.cs --------- Co-authored-by: PhyxionNL <7643972+PhyxionNL@users.noreply.github.com> --- .../Hardware/Gpu/AmdGpu.cs | 334 +++++++++--------- LibreHardwareMonitorLib/Interop/AtiAdlxx.cs | 84 ++--- 2 files changed, 208 insertions(+), 210 deletions(-) diff --git a/LibreHardwareMonitorLib/Hardware/Gpu/AmdGpu.cs b/LibreHardwareMonitorLib/Hardware/Gpu/AmdGpu.cs index c63ed9f..40f92a3 100644 --- a/LibreHardwareMonitorLib/Hardware/Gpu/AmdGpu.cs +++ b/LibreHardwareMonitorLib/Hardware/Gpu/AmdGpu.cs @@ -5,7 +5,6 @@ // All Rights Reserved. using System; -using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Runtime.InteropServices; @@ -18,6 +17,8 @@ internal sealed class AmdGpu : GenericGpu { private readonly AtiAdlxx.ADLAdapterInfo _adapterInfo; private readonly AtiAdlxx.ADLPMLogStartOutput _adlPMLogStartOutput; + private readonly AtiAdlxx.ADLPMLogSupportInfo _adlPMLogSupportInfo; + private readonly AtiAdlxx.ADLGcnInfo _adlGcnInfo; private readonly IntPtr _context = IntPtr.Zero; private readonly Sensor _controlSensor; private readonly Sensor _coreClock; @@ -54,8 +55,8 @@ internal sealed class AmdGpu : GenericGpu private readonly Sensor _temperaturePlx; private readonly Sensor _temperatureSoC; private readonly Sensor _temperatureVddc; - private readonly ushort pmLogSampleRate = 1000; - private bool? _newQueryPmLogDataGetExists; + private readonly ushort _pmLogSampleRate = 1000; + private bool _overdrive8LogExists; public AmdGpu(AtiAdlxx.ADLAdapterInfo adapterInfo, ISettings settings) : base(adapterInfo.AdapterName.Trim(), new Identifier("gpu-amd", adapterInfo.AdapterIndex.ToString(CultureInfo.InvariantCulture)), settings) @@ -136,6 +137,7 @@ internal sealed class AmdGpu : GenericGpu int supported = 0; int enabled = 0; int version = 0; + _adlGcnInfo = new(); if (AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Main_Control_Create)) && AtiAdlxx.ADL2_Main_Control_Create(AtiAdlxx.Main_Memory_Alloc, _adapterInfo.AdapterIndex, ref _context) != AtiAdlxx.ADLStatus.ADL_OK) @@ -153,14 +155,21 @@ internal sealed class AmdGpu : GenericGpu ActivateSensor(_fullscreenFps); } - if (AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Adapter_PMLog_Support_Get)) && + if (AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_GcnAsicInfo_Get))) + { + AtiAdlxx.ADL2_GcnAsicInfo_Get(_context, _adapterInfo.AdapterIndex, ref _adlGcnInfo); + } + + if (_adlGcnInfo.ASICFamilyId >= (int)AtiAdlxx.GCNFamilies.FAMILY_AI && + AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Adapter_PMLog_Support_Get)) && AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Device_PMLog_Device_Create)) && AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_Adapter_PMLog_Start))) { - AtiAdlxx.ADLPMLogSupportInfo _adlPMLogSupportInfo = new(); AtiAdlxx.ADLPMLogStartInput _adlPMLogStartInput = new(); + _adlPMLogSupportInfo = new(); _adlPMLogStartOutput = new AtiAdlxx.ADLPMLogStartOutput(); _adlPMLogStartInput.usSensors = new ushort[AtiAdlxx.ADL_PMLOG_MAX_SENSORS]; + if (_device == 0 && AtiAdlxx.ADLStatus.ADL_OK == AtiAdlxx.ADL2_Device_PMLog_Device_Create(_context, _adapterInfo.AdapterIndex, ref _device) && AtiAdlxx.ADLStatus.ADL_OK == AtiAdlxx.ADL2_Adapter_PMLog_Support_Get(_context, _adapterInfo.AdapterIndex, ref _adlPMLogSupportInfo)) @@ -173,14 +182,13 @@ internal sealed class AmdGpu : GenericGpu } _adlPMLogStartInput.usSensors[i] = (ushort)AtiAdlxx.ADLPMLogSensors.ADL_SENSOR_MAXTYPES; - _adlPMLogStartInput.ulSampleRate = pmLogSampleRate; + _adlPMLogStartInput.ulSampleRate = _pmLogSampleRate; if (AtiAdlxx.ADL2_Adapter_PMLog_Start(_context, adapterInfo.AdapterIndex, ref _adlPMLogStartInput, ref _adlPMLogStartOutput, - _device) == - AtiAdlxx.ADLStatus.ADL_OK) + _device) == AtiAdlxx.ADLStatus.ADL_OK) { _pmLogStarted = true; } @@ -348,87 +356,145 @@ internal sealed class AmdGpu : GenericGpu if (_currentOverdriveApiLevel >= 8 || !_overdriveApiSupported) { + _overdrive8LogExists = false; AtiAdlxx.ADLPMLogDataOutput logDataOutput = new(); + if (AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_New_QueryPMLogData_Get)) && + AtiAdlxx.ADL2_New_QueryPMLogData_Get(_context, _adapterInfo.AdapterIndex, ref logDataOutput) == AtiAdlxx.ADLStatus.ADL_OK) + { + _overdrive8LogExists = true; + } - _newQueryPmLogDataGetExists ??= AtiAdlxx.ADL_Method_Exists(nameof(AtiAdlxx.ADL2_New_QueryPMLogData_Get)); - + AtiAdlxx.ADLPMLogData adlPMLogData = new(); if (_pmLogStarted) { - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_CLK_GFXCLK, _coreClock, reset: false); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_CLK_SOCCLK, _socClock); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_CLK_MEMCLK, _memoryClock, reset: false); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_BOARD_POWER, _powerTotal, reset: false); - - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_TEMPERATURE_EDGE, _temperatureCore, reset: false); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_TEMPERATURE_MEM, _temperatureMemory, reset: false); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_TEMPERATURE_VRVDDC, _temperatureVddc, reset: false); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_TEMPERATURE_VRMVDD, _temperatureMvdd, reset: false); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_TEMPERATURE_LIQUID, _temperatureLiquid, reset: false); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_TEMPERATURE_PLX, _temperaturePlx, reset: false); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_TEMPERATURE_HOTSPOT, _temperatureHotSpot, reset: false); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_TEMPERATURE_SOC, _temperatureSoC); - - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_CLK_GFXCLK, _coreClock, reset: false); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_CLK_SOCCLK, _socClock); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_CLK_MEMCLK, _memoryClock, reset: false); - - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_FAN_RPM, _fan, reset: false); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_FAN_PERCENTAGE, _controlSensor, reset: false); - - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_GFX_VOLTAGE, _coreVoltage, 0.001f, false); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_SOC_VOLTAGE, _socVoltage, 0.001f); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_MEM_VOLTAGE, _memoryVoltage, 0.001f); - - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_INFO_ACTIVITY_GFX, _coreLoad, reset: false); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_INFO_ACTIVITY_MEM, _memoryLoad); - - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_ASIC_POWER, _powerTotal, reset: false); - - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_GFX_POWER, _powerCore, reset: false); - GetPMLog(AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_SOC_POWER, _powerSoC, reset: false); + adlPMLogData = (AtiAdlxx.ADLPMLogData)Marshal.PtrToStructure(_adlPMLogStartOutput.pLoggingAddress, typeof(AtiAdlxx.ADLPMLogData)); } - else if (_newQueryPmLogDataGetExists == true && AtiAdlxx.ADL2_New_QueryPMLogData_Get(_context, _adapterInfo.AdapterIndex, ref logDataOutput) == AtiAdlxx.ADLStatus.ADL_OK) + + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_CLK_GFXCLK, _coreClock, reset: false); + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_CLK_SOCCLK, _socClock); + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_CLK_MEMCLK, _memoryClock, reset: false); + + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_TEMPERATURE_EDGE, _temperatureCore, reset: false); + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_TEMPERATURE_MEM, _temperatureMemory, reset: false); + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_TEMPERATURE_VRVDDC, _temperatureVddc, reset: false); + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_TEMPERATURE_VRMVDD, _temperatureMvdd, reset: false); + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_TEMPERATURE_LIQUID, _temperatureLiquid, reset: false); + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_TEMPERATURE_PLX, _temperaturePlx, reset: false); + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_TEMPERATURE_HOTSPOT, _temperatureHotSpot, reset: false); + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_TEMPERATURE_SOC, _temperatureSoC); + + + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_FAN_RPM, _fan, reset: false); + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_FAN_PERCENTAGE, _controlSensor, reset: false); + + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_GFX_VOLTAGE, _coreVoltage, 0.001f, false); + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_SOC_VOLTAGE, _socVoltage, 0.001f); + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_MEM_VOLTAGE, _memoryVoltage, 0.001f); + + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_INFO_ACTIVITY_GFX, _coreLoad, reset: false); + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_INFO_ACTIVITY_MEM, _memoryLoad); + + if (_adlGcnInfo.ASICFamilyId >= (int)AtiAdlxx.GCNFamilies.FAMILY_NV3 || !GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_ASIC_POWER, _powerTotal, reset: false)) { - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_EDGE, _temperatureCore, reset: false); - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_MEM, _temperatureMemory, reset: false); - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_VRVDDC, _temperatureVddc, reset: false); - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_VRMVDD, _temperatureMvdd, reset: false); - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_LIQUID, _temperatureLiquid, reset: false); - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_PLX, _temperaturePlx, reset: false); - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_HOTSPOT, _temperatureHotSpot, reset: false); - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_SOC, _temperatureSoC); + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_BOARD_POWER, _powerTotal, reset: false); + } - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_CLK_GFXCLK, _coreClock, reset: false); - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_CLK_SOCCLK, _socClock); - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_CLK_MEMCLK, _memoryClock, reset: false); + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_GFX_POWER, _powerCore, reset: false); + GetAdlSensor(adlPMLogData, logDataOutput, AtiAdlxx.ADLPMLogSensors.ADL_PMLOG_SOC_POWER, _powerSoC, reset: false); + } + } - const int fanRpmIndex = (int)AtiAdlxx.ADLSensorType.PMLOG_FAN_RPM; - const int fanPercentageIndex = (int)AtiAdlxx.ADLSensorType.PMLOG_FAN_PERCENTAGE; + private bool IsSensorSupportedByPMLog(AtiAdlxx.ADLPMLogSensors sensorType) + { + if (!_pmLogStarted || (int)sensorType == 0) + return false; - if (logDataOutput.sensors.Length is > fanRpmIndex and > fanPercentageIndex && - logDataOutput.sensors[fanRpmIndex].value != ushort.MaxValue && - logDataOutput.sensors[fanRpmIndex].supported != 0) - { - _fan.Value = logDataOutput.sensors[fanRpmIndex].value; - _controlSensor.Value = logDataOutput.sensors[fanPercentageIndex].value; - - ActivateSensor(_fan); - ActivateSensor(_controlSensor); - } - - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_GFX_VOLTAGE, _coreVoltage, 0.001f, false); - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_SOC_VOLTAGE, _socVoltage, 0.001f); - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_MEM_VOLTAGE, _memoryVoltage, 0.001f); - - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_INFO_ACTIVITY_GFX, _coreLoad, reset: false); - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_INFO_ACTIVITY_MEM, _memoryLoad); - - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_ASIC_POWER, _powerTotal, reset: false); - - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_GFX_POWER, _powerCore, reset: false); - GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_SOC_POWER, _powerSoC, reset: false); + for (int i = 0; i < AtiAdlxx.ADL_PMLOG_MAX_SENSORS; i++) + { + if (_adlPMLogSupportInfo.usSensors[i] == (int)sensorType) + { + return true; } } + + return false; + } + + /// + /// Gets a sensor value. + /// + /// + /// Current pmlog struct, used with pmlog-support/start. + /// Legacy pmlogdataoutput struct, used with ADL2_New_QueryPMLogData_Get. + /// Type of the sensor. + /// The sensor. + /// The factor. + /// If set to true, resets the sensor value to null. + /// true if sensor is supported, false otherwise + private bool GetAdlSensor(AtiAdlxx.ADLPMLogData adlPMLogData, AtiAdlxx.ADLPMLogDataOutput od8Log, + AtiAdlxx.ADLPMLogSensors sensorType, Sensor sensor, float factor = 1.0f, bool reset = true) + { + int i = (int)sensorType; + bool supportedByPMLog = IsSensorSupportedByPMLog(sensorType); + bool supportedByOD8 = _overdrive8LogExists && i < od8Log.sensors.Length && od8Log.sensors[i].supported != 0; + + if (!supportedByPMLog && !supportedByOD8) + { + if (reset) + sensor.Value = null; + + return false; + } + + if (_pmLogStarted) + { + //check if ulLastUpdated is a valid number, avoid timezone issues with unspecified kind and 48h offset + DateTime now = new(DateTime.Now.Ticks, DateTimeKind.Unspecified); + if (adlPMLogData.ulLastUpdated == 0 || + adlPMLogData.ulActiveSampleRate < 0 || + adlPMLogData.ulActiveSampleRate > 86400000 || + now.AddHours(48).ToFileTime() < (long)adlPMLogData.ulLastUpdated || + now.AddHours(-48).ToFileTime() > (long)adlPMLogData.ulLastUpdated) + { + supportedByPMLog = false; + } + } + + if (supportedByPMLog) + { + bool found = false; + + if (adlPMLogData.ulValues != null) + { + for (int k = 0; k < adlPMLogData.ulValues.Length - 1; k += 2) + { + if (adlPMLogData.ulValues[k] == i) + { + sensor.Value = adlPMLogData.ulValues[k + 1] * factor; + ActivateSensor(sensor); + found = true; + } + } + } + + if (!found && reset) + { + sensor.Value = null; + } + } + else if (_overdrive8LogExists) + { + if (supportedByOD8) + { + sensor.Value = od8Log.sensors[i].value * factor; + ActivateSensor(sensor); + } + else if (reset) + { + sensor.Value = null; + } + } + return true; } private void GetOD5CurrentActivity() @@ -536,60 +602,6 @@ internal sealed class AmdGpu : GenericGpu } } - /// - /// Gets a PMLog sensor value. - /// - /// The data. - /// Type of the sensor. - /// The sensor. - /// The factor. - /// If set to true, resets the sensor value to null. - private void GetPMLog(AtiAdlxx.ADLPMLogDataOutput data, AtiAdlxx.ADLSensorType sensorType, Sensor sensor, float factor = 1.0f, bool reset = true) - { - int i = (int)sensorType; - if (i < data.sensors.Length && data.sensors[i].supported != 0) - { - sensor.Value = data.sensors[i].value * factor; - ActivateSensor(sensor); - } - else if (reset) - { - sensor.Value = null; - } - } - - /// - /// Gets a PMLog sensor value. - /// - /// Type of the sensor. - /// The sensor. - /// The factor. - /// If set to true, resets the sensor value to null. - private void GetPMLog(AtiAdlxx.ADLPMLogSensors sensorType, Sensor sensor, float factor = 1.0f, bool reset = true) - { - int i = (int)sensorType; - bool found = false; - AtiAdlxx.ADLPMLogData _adlPMLogData = (AtiAdlxx.ADLPMLogData)Marshal.PtrToStructure(_adlPMLogStartOutput.pLoggingAddress, typeof(AtiAdlxx.ADLPMLogData)); - - if (_adlPMLogData.ulValues != null) - { - for (int k = 0; k < _adlPMLogData.ulValues.Length - 1; k += 2) - { - if (_adlPMLogData.ulValues[k] == i) - { - sensor.Value = _adlPMLogData.ulValues[k + 1] * factor; - ActivateSensor(sensor); - found = true; - } - } - } - - if (!found && reset) - { - sensor.Value = null; - } - } - /// /// Gets the Overdrive6 power. /// @@ -870,49 +882,41 @@ internal sealed class AmdGpu : GenericGpu r.AppendLine(); try { + var data = new AtiAdlxx.ADLPMLogDataOutput(); + AtiAdlxx.ADLStatus status = AtiAdlxx.ADL2_New_QueryPMLogData_Get(_context, _adapterInfo.AdapterIndex, ref data); + AtiAdlxx.ADLPMLogData adlPMLogData = new(); if (_pmLogStarted) { - AtiAdlxx.ADLPMLogData _adlPMLogData = (AtiAdlxx.ADLPMLogData)Marshal.PtrToStructure(_adlPMLogStartOutput.pLoggingAddress, typeof(AtiAdlxx.ADLPMLogData)); - Dictionary> allSensorsSupport = new(); + adlPMLogData = (AtiAdlxx.ADLPMLogData)Marshal.PtrToStructure(_adlPMLogStartOutput.pLoggingAddress, typeof(AtiAdlxx.ADLPMLogData)); + } - foreach (int i in Enum.GetValues(typeof(AtiAdlxx.ADLPMLogSensors))) + foreach (AtiAdlxx.ADLPMLogSensors sensorType in Enum.GetValues(typeof(AtiAdlxx.ADLPMLogSensors))) + { + int i = (int)sensorType; + if (i == 0) + continue; + + bool supported = false; + + string st = ((AtiAdlxx.ADLPMLogSensors)i).ToString(); + if (IsSensorSupportedByPMLog(sensorType)) { - allSensorsSupport.Add((uint)i, new Tuple(false, 0)); - } - - for (int k = 0; k < _adlPMLogData.ulValues.Length - 1; k += 2) - { - allSensorsSupport[_adlPMLogData.ulValues[k]] = new Tuple(true, _adlPMLogData.ulValues[k + 1]); - } - - if (_adlPMLogData.ulValues != null) - { - r.AppendLine(" Status: OK"); - - foreach (KeyValuePair> kv in allSensorsSupport) + for (int k = 0; k < adlPMLogData.ulValues.Length - 1; k += 2) { - string st = ((AtiAdlxx.ADLPMLogSensors)kv.Key).ToString(); - - r.AppendFormat(" Sensor[{0}].Supported: {1}{2}", st, kv.Value.Item1, Environment.NewLine); - r.AppendFormat(" Sensor[{0}].Value: {1}{2}", st, kv.Value.Item2, Environment.NewLine); + if (adlPMLogData.ulValues[k] == i) + { + r.AppendFormat(" Sensor[{0}].Value: {1}{2}", st, adlPMLogData.ulValues[k + 1], Environment.NewLine); + supported = true; + } } } - } - else - { - var data = new AtiAdlxx.ADLPMLogDataOutput(); - AtiAdlxx.ADLStatus status = AtiAdlxx.ADL2_New_QueryPMLogData_Get(_context, _adapterInfo.AdapterIndex, ref data); - - r.Append(" Status: "); - r.AppendLine(status.ToString()); - - for (int i = 0; i < data.sensors.Length; i++) + else if (_overdrive8LogExists && i < data.sensors.Length && data.sensors[i].supported != 0) { - string st = ((AtiAdlxx.ADLSensorType)i).ToString(); - - r.AppendFormat(" Sensor[{0}].Supported: {1}{2}", st, data.sensors[i].supported, Environment.NewLine); r.AppendFormat(" Sensor[{0}].Value: {1}{2}", st, data.sensors[i].value, Environment.NewLine); + supported = true; } + + r.AppendFormat(" Sensor[{0}].Supported: {1}{2}", st, supported, Environment.NewLine); } } catch (EntryPointNotFoundException) diff --git a/LibreHardwareMonitorLib/Interop/AtiAdlxx.cs b/LibreHardwareMonitorLib/Interop/AtiAdlxx.cs index 39225ef..0ebb43d 100644 --- a/LibreHardwareMonitorLib/Interop/AtiAdlxx.cs +++ b/LibreHardwareMonitorLib/Interop/AtiAdlxx.cs @@ -186,6 +186,10 @@ internal static class AtiAdlxx [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] public static extern ADLStatus ADL2_Device_PMLog_Device_Destroy(IntPtr context, uint device); + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] + public static extern ADLStatus ADL2_GcnAsicInfo_Get(IntPtr context, int adapterIndex, ref ADLGcnInfo gcnInfo); + public static bool ADL_Method_Exists(string ADL_Method) { IntPtr module = Kernel32.LoadLibrary(DllName); @@ -534,51 +538,6 @@ internal static class AtiAdlxx public ADLSingleSensorData[] sensors; } - internal enum ADLSensorType - { - SENSOR_MAXTYPES = 0, - PMLOG_CLK_GFXCLK = 1, - PMLOG_CLK_MEMCLK = 2, - PMLOG_CLK_SOCCLK = 3, - PMLOG_CLK_UVDCLK1 = 4, - PMLOG_CLK_UVDCLK2 = 5, - PMLOG_CLK_VCECLK = 6, - PMLOG_CLK_VCNCLK = 7, - PMLOG_TEMPERATURE_EDGE = 8, - PMLOG_TEMPERATURE_MEM = 9, - PMLOG_TEMPERATURE_VRVDDC = 10, - PMLOG_TEMPERATURE_VRMVDD = 11, - PMLOG_TEMPERATURE_LIQUID = 12, - PMLOG_TEMPERATURE_PLX = 13, - PMLOG_FAN_RPM = 14, - PMLOG_FAN_PERCENTAGE = 15, - PMLOG_SOC_VOLTAGE = 16, - PMLOG_SOC_POWER = 17, - PMLOG_SOC_CURRENT = 18, - PMLOG_INFO_ACTIVITY_GFX = 19, - PMLOG_INFO_ACTIVITY_MEM = 20, - PMLOG_GFX_VOLTAGE = 21, - PMLOG_MEM_VOLTAGE = 22, - PMLOG_ASIC_POWER = 23, - PMLOG_TEMPERATURE_VRSOC = 24, - PMLOG_TEMPERATURE_VRMVDD0 = 25, - PMLOG_TEMPERATURE_VRMVDD1 = 26, - PMLOG_TEMPERATURE_HOTSPOT = 27, - PMLOG_TEMPERATURE_GFX = 28, - PMLOG_TEMPERATURE_SOC = 29, - PMLOG_GFX_POWER = 30, - PMLOG_GFX_CURRENT = 31, - PMLOG_TEMPERATURE_CPU = 32, - PMLOG_CPU_POWER = 33, - PMLOG_CLK_CPUCLK = 34, - PMLOG_THROTTLER_STATUS = 35, - PMLOG_CLK_VCN1CLK1 = 36, - PMLOG_CLK_VCN1CLK2 = 37, - PMLOG_SMART_POWERSHIFT_CPU = 38, - PMLOG_SMART_POWERSHIFT_DGPU = 39, - PMLOG_MAX_SENSORS_REAL - } - internal enum ADLPMLogSensors { ADL_SENSOR_MAXTYPES = 0, @@ -658,6 +617,27 @@ internal static class AtiAdlxx ADL_PMLOG_MAX_SENSORS_REAL } + internal enum GCNFamilies + { + FAMILY_UNKNOWN = 0, + FAMILY_TN = 105, // Trinity APUs + FAMILY_SI = 110, // Southern Islands: Tahiti, Pitcairn, CapeVerde, Oland, Hainan + FAMILY_CI = 120, // Sea Islands: Bonaire, Hawaii + FAMILY_KV = 125, // Kaveri, Kabini, Mullins + FAMILY_VI = 130, // Volcanic Islands: Iceland, Tonga, Fiji + FAMILY_CZ = 135, // Carrizo APUs: Carrizo, Stoney + FAMILY_AI = 141, // Vega: 10, 20 + FAMILY_RV = 142, // Raven (Vega GCN 5.0) + FAMILY_NV = 143, // Navi10, Navi2x + FAMILY_VGH = 144, // Van Gogh (RDNA 2.0) + FAMILY_NV3 = 145, // Navi: 3x (GC 11.0.0, RDNA 3.0) + FAMILY_YC = 146, // Rembrandt (Yellow Carp, RDNA 2.0) + FAMILY_GC_11_0_1 = 148, // Phoenix (GC 11.0.1, RDNA 3.0) + FAMILY_GC_10_3_6 = 149, // Raphael (GC 10.3.6, RDNA 2.0) + FAMILY_GC_11_5_0 = 150, // GC 11.5.0 + FAMILY_GC_10_3_7 = 151, // Mendocino (GC 10.3.7, RDNA 2.0) + } + //Structure containing information related power management logging. [StructLayout(LayoutKind.Sequential)] internal struct ADLPMLogSupportInfo @@ -717,4 +697,18 @@ internal static class AtiAdlxx [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] public uint[] ulReserved; } + + [StructLayout(LayoutKind.Sequential)] + internal struct ADLGcnInfo + { + public int CuCount; //Number of compute units on the ASIC. + public int TexCount; //Number of texture mapping units. + public int RopCount; //Number of Render backend Units. + + // see GCNFamilies enum, references: + // https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/amd/addrlib/src/amdgpu_asic_addr.h + // https://github.com/torvalds/linux/blob/master/include/uapi/drm/amdgpu_drm.h + public int ASICFamilyId; + public int ASICRevisionId; + } }