diff --git a/LibreHardwareMonitorLib/Hardware/Gpu/AmdGpu.cs b/LibreHardwareMonitorLib/Hardware/Gpu/AmdGpu.cs index 84044bd..63afdca 100644 --- a/LibreHardwareMonitorLib/Hardware/Gpu/AmdGpu.cs +++ b/LibreHardwareMonitorLib/Hardware/Gpu/AmdGpu.cs @@ -6,6 +6,7 @@ using System; using System.Globalization; +using System.Text; using LibreHardwareMonitor.Interop; namespace LibreHardwareMonitor.Hardware.Gpu @@ -13,32 +14,34 @@ namespace LibreHardwareMonitor.Hardware.Gpu internal sealed class AmdGpu : Hardware { private readonly int _adapterIndex; + + private readonly IntPtr _context = IntPtr.Zero; + private readonly Sensor _controlSensor; private readonly Sensor _coreClock; - private readonly Sensor _socClock; private readonly Sensor _coreLoad; private readonly Sensor _coreVoltage; private readonly int _currentOverdriveApiLevel; private readonly Sensor _fan; private readonly Control _fanControl; private readonly Sensor _memoryClock; + private readonly Sensor _memoryLoad; private readonly Sensor _memoryVoltage; - private readonly Sensor _powerCore; private readonly Sensor _powerPpt; - private readonly Sensor _powerSocket; + private readonly Sensor _powerSoC; private readonly Sensor _powerTotal; - + private readonly Sensor _socClock; + private readonly Sensor _socVoltage; private readonly Sensor _temperatureCore; - private readonly Sensor _temperatureMemory; private readonly Sensor _temperatureHotSpot; private readonly Sensor _temperatureLiquid; + private readonly Sensor _temperatureMemory; private readonly Sensor _temperatureMvdd; private readonly Sensor _temperaturePlx; + private readonly Sensor _temperatureSoC; private readonly Sensor _temperatureVddc; - private readonly IntPtr _context = IntPtr.Zero; - public AmdGpu(string name, int adapterIndex, int busNumber, int deviceNumber, ISettings settings) : base(name, new Identifier("gpu", adapterIndex.ToString(CultureInfo.InvariantCulture)), settings) { @@ -50,45 +53,48 @@ namespace LibreHardwareMonitor.Hardware.Gpu _temperatureMemory = new Sensor("GPU Memory", 1, SensorType.Temperature, this, settings); _temperatureVddc = new Sensor("GPU VR VDDC", 2, SensorType.Temperature, this, settings); _temperatureMvdd = new Sensor("GPU VR MVDD", 3, SensorType.Temperature, this, settings); - _temperatureLiquid = new Sensor("GPU Liquid", 4, SensorType.Temperature, this, settings); - _temperaturePlx = new Sensor("GPU PLX", 5, SensorType.Temperature, this, settings); - _temperatureHotSpot = new Sensor("GPU Hot Spot", 6, SensorType.Temperature, this, settings); + _temperatureSoC = new Sensor("GPU VR SoC", 4, SensorType.Temperature, this, settings); + _temperatureLiquid = new Sensor("GPU Liquid", 5, SensorType.Temperature, this, settings); + _temperaturePlx = new Sensor("GPU PLX", 6, SensorType.Temperature, this, settings); + _temperatureHotSpot = new Sensor("GPU Hot Spot", 7, SensorType.Temperature, this, settings); _coreClock = new Sensor("GPU Core", 0, SensorType.Clock, this, settings); _socClock = new Sensor("GPU SoC", 1, SensorType.Clock, this, settings); _memoryClock = new Sensor("GPU Memory", 2, SensorType.Clock, this, settings); - + _fan = new Sensor("GPU Fan", 0, SensorType.Fan, this, settings); - + _coreVoltage = new Sensor("GPU Core", 0, SensorType.Voltage, this, settings); _memoryVoltage = new Sensor("GPU Memory", 1, SensorType.Voltage, this, settings); + _socVoltage = new Sensor("GPU SoC", 2, SensorType.Voltage, this, settings); _coreLoad = new Sensor("GPU Core", 0, SensorType.Load, this, settings); - + _memoryLoad = new Sensor("GPU Memory", 1, SensorType.Load, this, settings); + _controlSensor = new Sensor("GPU Fan", 0, SensorType.Control, this, settings); _powerCore = new Sensor("GPU Core", 0, SensorType.Power, this, settings); _powerPpt = new Sensor("GPU PPT", 1, SensorType.Power, this, settings); - _powerSocket = new Sensor("GPU Socket", 2, SensorType.Power, this, settings); + _powerSoC = new Sensor("GPU SoC", 2, SensorType.Power, this, settings); _powerTotal = new Sensor("GPU Package", 3, SensorType.Power, this, settings); int supported = 0; int enabled = 0; int version = 0; - if (AtiAdlxx.ADL_Overdrive_Caps(1, ref supported, ref enabled, ref version) == AtiAdlxx.ADL_OK) + if (AtiAdlxx.ADL_Overdrive_Caps(1, ref supported, ref enabled, ref version) == AtiAdlxx.ADLStatus.ADL_OK) _currentOverdriveApiLevel = version; else _currentOverdriveApiLevel = -1; if (_currentOverdriveApiLevel >= 6) { - if (AtiAdlxx.ADL2_Main_Control_Create(AtiAdlxx.Main_Memory_Alloc, adapterIndex, ref _context) == AtiAdlxx.ADL_OK) + if (AtiAdlxx.ADL2_Main_Control_Create(AtiAdlxx.Main_Memory_Alloc, adapterIndex, ref _context) == AtiAdlxx.ADLStatus.ADL_OK) _context = IntPtr.Zero; } AtiAdlxx.ADLFanSpeedInfo fanSpeedInfo = new AtiAdlxx.ADLFanSpeedInfo(); - if (AtiAdlxx.ADL_Overdrive5_FanSpeedInfo_Get(adapterIndex, 0, ref fanSpeedInfo) != AtiAdlxx.ADL_OK) + if (AtiAdlxx.ADL_Overdrive5_FanSpeedInfo_Get(adapterIndex, 0, ref fanSpeedInfo) != AtiAdlxx.ADLStatus.ADL_OK) { fanSpeedInfo.MaxPercent = 100; fanSpeedInfo.MinPercent = 0; @@ -141,6 +147,9 @@ namespace LibreHardwareMonitor.Hardware.Gpu } } + /// + /// Sets the default fan speed. + /// private void SetDefaultFanSpeed() { AtiAdlxx.ADL_Overdrive5_FanSpeedToDefault_Set(_adapterIndex, 0); @@ -152,123 +161,26 @@ namespace LibreHardwareMonitor.Hardware.Gpu { if (_currentOverdriveApiLevel >= 6) { - int powerOf8 = 0; - if (AtiAdlxx.ADL2_Overdrive6_CurrentPower_Get(_context, _adapterIndex, AtiAdlxx.ADLODNCurrentPowerType.ODN_GPU_TOTAL_POWER, ref powerOf8) == AtiAdlxx.ADL_OK) - { - _powerTotal.Value = powerOf8 >> 8; - ActivateSensor(_powerTotal); - } - else - { - _powerTotal.Value = null; - } - - if (AtiAdlxx.ADL2_Overdrive6_CurrentPower_Get(_context, _adapterIndex, AtiAdlxx.ADLODNCurrentPowerType.ODN_GPU_PPT_POWER, ref powerOf8) == AtiAdlxx.ADL_OK) - { - _powerPpt.Value = powerOf8 >> 8; - ActivateSensor(_powerPpt); - } - else - { - _powerPpt.Value = null; - } - - if (AtiAdlxx.ADL2_Overdrive6_CurrentPower_Get(_context, _adapterIndex, AtiAdlxx.ADLODNCurrentPowerType.ODN_GPU_SOCKET_POWER, ref powerOf8) == AtiAdlxx.ADL_OK) - { - _powerSocket.Value = powerOf8 >> 8; - ActivateSensor(_powerSocket); - } - else - { - _powerSocket.Value = null; - } - - if (AtiAdlxx.ADL2_Overdrive6_CurrentPower_Get(_context, _adapterIndex, AtiAdlxx.ADLODNCurrentPowerType.ODN_GPU_CHIP_POWER, ref powerOf8) == AtiAdlxx.ADL_OK) - { - _powerCore.Value = powerOf8 >> 8; - ActivateSensor(_powerCore); - } - else - { - _powerCore.Value = null; - } + GetOD6Power(AtiAdlxx.ADLODNCurrentPowerType.ODN_GPU_TOTAL_POWER, _powerTotal); + GetOD6Power(AtiAdlxx.ADLODNCurrentPowerType.ODN_GPU_PPT_POWER, _powerPpt); + GetOD6Power(AtiAdlxx.ADLODNCurrentPowerType.ODN_GPU_SOCKET_POWER, _powerSoC); + GetOD6Power(AtiAdlxx.ADLODNCurrentPowerType.ODN_GPU_CHIP_POWER, _powerCore); } if (_currentOverdriveApiLevel >= 7) { - // If a sensor isn't available, some cards report 54000 degrees C. 110C is expected for Navi, so 100 more than that should be enough to use as a maximum. - const int maxTemperature = 210; - - int temp = 0; - - if (AtiAdlxx.ADL2_OverdriveN_Temperature_Get(_context, _adapterIndex, AtiAdlxx.ADLODNTemperatureType.EDGE, ref temp) == AtiAdlxx.ADL_OK && temp < (maxTemperature * 1000)) - { - _temperatureCore.Value = 0.001f * temp; - ActivateSensor(_temperatureCore); - } - else - { - _temperatureCore.Value = null; - } - - if (AtiAdlxx.ADL2_OverdriveN_Temperature_Get(_context, _adapterIndex, AtiAdlxx.ADLODNTemperatureType.MEM, ref temp) == AtiAdlxx.ADL_OK && temp < maxTemperature) - { - _temperatureMemory.Value = temp; - ActivateSensor(_temperatureMemory); - } - else - { - _temperatureMemory.Value = null; - } - - if (AtiAdlxx.ADL2_OverdriveN_Temperature_Get(_context, _adapterIndex, AtiAdlxx.ADLODNTemperatureType.VRVDDC, ref temp) == AtiAdlxx.ADL_OK && temp < maxTemperature) - { - _temperatureVddc.Value = temp; - ActivateSensor(_temperatureVddc); - } - else - { - _temperatureVddc.Value = null; - } - - if (AtiAdlxx.ADL2_OverdriveN_Temperature_Get(_context, _adapterIndex, AtiAdlxx.ADLODNTemperatureType.VRMVDD, ref temp) == AtiAdlxx.ADL_OK && temp < maxTemperature) - { - _temperatureMvdd.Value = temp; - ActivateSensor(_temperatureMvdd); - } - else - { - _temperatureMvdd.Value = null; - } - - _temperatureLiquid.Value = null; - if (AtiAdlxx.ADL2_OverdriveN_Temperature_Get(_context, _adapterIndex, AtiAdlxx.ADLODNTemperatureType.LIQUID, ref temp) == AtiAdlxx.ADL_OK && temp > 0 && temp < maxTemperature) - { - _temperatureLiquid.Value = temp; - ActivateSensor(_temperatureLiquid); - } - - _temperaturePlx.Value = null; - if (AtiAdlxx.ADL2_OverdriveN_Temperature_Get(_context, _adapterIndex, AtiAdlxx.ADLODNTemperatureType.PLX, ref temp) == AtiAdlxx.ADL_OK && temp > 0 && temp < maxTemperature) - { - _temperaturePlx.Value = temp; - ActivateSensor(_temperaturePlx); - } - - if (AtiAdlxx.ADL2_OverdriveN_Temperature_Get(_context, _adapterIndex, AtiAdlxx.ADLODNTemperatureType.HOTSPOT, ref temp) == AtiAdlxx.ADL_OK && temp < maxTemperature) - { - _temperatureHotSpot.Value = temp; - ActivateSensor(_temperatureHotSpot); - } - else - { - _temperatureHotSpot.Value = null; - } + GetODNTemperature(AtiAdlxx.ADLODNTemperatureType.EDGE, _temperatureCore); + GetODNTemperature(AtiAdlxx.ADLODNTemperatureType.MEM, _temperatureMemory); + GetODNTemperature(AtiAdlxx.ADLODNTemperatureType.VRVDDC, _temperatureVddc); + GetODNTemperature(AtiAdlxx.ADLODNTemperatureType.VRMVDD, _temperatureMvdd); + GetODNTemperature(AtiAdlxx.ADLODNTemperatureType.LIQUID, _temperatureLiquid); + GetODNTemperature(AtiAdlxx.ADLODNTemperatureType.PLX, _temperaturePlx); + GetODNTemperature(AtiAdlxx.ADLODNTemperatureType.HOTSPOT, _temperatureHotSpot); } else { AtiAdlxx.ADLTemperature temperature = new AtiAdlxx.ADLTemperature(); - if (AtiAdlxx.ADL_Overdrive5_Temperature_Get(_adapterIndex, 0, ref temperature) == AtiAdlxx.ADL_OK) + if (AtiAdlxx.ADL_Overdrive5_Temperature_Get(_adapterIndex, 0, ref temperature) == AtiAdlxx.ADLStatus.ADL_OK) { _temperatureCore.Value = 0.001f * temperature.Temperature; ActivateSensor(_temperatureCore); @@ -280,7 +192,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu } AtiAdlxx.ADLFanSpeedValue fanSpeedValue = new AtiAdlxx.ADLFanSpeedValue { SpeedType = AtiAdlxx.ADL_DL_FANCTRL_SPEED_TYPE_RPM }; - if (AtiAdlxx.ADL_Overdrive5_FanSpeed_Get(_adapterIndex, 0, ref fanSpeedValue) == AtiAdlxx.ADL_OK) + if (AtiAdlxx.ADL_Overdrive5_FanSpeed_Get(_adapterIndex, 0, ref fanSpeedValue) == AtiAdlxx.ADLStatus.ADL_OK) { _fan.Value = fanSpeedValue.FanSpeed; ActivateSensor(_fan); @@ -291,7 +203,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu } fanSpeedValue = new AtiAdlxx.ADLFanSpeedValue { SpeedType = AtiAdlxx.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT }; - if (AtiAdlxx.ADL_Overdrive5_FanSpeed_Get(_adapterIndex, 0, ref fanSpeedValue) == AtiAdlxx.ADL_OK) + if (AtiAdlxx.ADL_Overdrive5_FanSpeed_Get(_adapterIndex, 0, ref fanSpeedValue) == AtiAdlxx.ADLStatus.ADL_OK) { _controlSensor.Value = fanSpeedValue.FanSpeed; ActivateSensor(_controlSensor); @@ -302,7 +214,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu } AtiAdlxx.ADLPMActivity adlpmActivity = new AtiAdlxx.ADLPMActivity(); - if (AtiAdlxx.ADL_Overdrive5_CurrentActivity_Get(_adapterIndex, ref adlpmActivity) == AtiAdlxx.ADL_OK) + if (AtiAdlxx.ADL_Overdrive5_CurrentActivity_Get(_adapterIndex, ref adlpmActivity) == AtiAdlxx.ADLStatus.ADL_OK) { if (adlpmActivity.EngineClock > 0) { @@ -348,86 +260,114 @@ namespace LibreHardwareMonitor.Hardware.Gpu else { AtiAdlxx.ADLPMLogDataOutput logDataOutput = new AtiAdlxx.ADLPMLogDataOutput(); - if (AtiAdlxx.ADL2_New_QueryPMLogData_Get(_context, _adapterIndex, ref logDataOutput) == AtiAdlxx.ADL_OK) + if (AtiAdlxx.ADL2_New_QueryPMLogData_Get(_context, _adapterIndex, ref logDataOutput) == AtiAdlxx.ADLStatus.ADL_OK) { - _temperatureCore.Value = logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_EDGE].value; - ActivateSensor(_temperatureCore); - - _temperatureHotSpot.Value = logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_HOTSPOT].value; - ActivateSensor(_temperatureHotSpot); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_EDGE, _temperatureCore); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_HOTSPOT, _temperatureHotSpot); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_VRVDDC, _temperatureVddc); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_MEM, _temperatureMemory); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_VRMVDD, _temperatureMvdd); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_LIQUID, _temperatureLiquid); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_PLX, _temperaturePlx); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_SOC, _temperatureSoC); - _temperatureVddc.Value = logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_VRVDDC].value; - ActivateSensor(_temperatureVddc); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_CLK_GFXCLK, _coreClock); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_CLK_SOCCLK, _socClock); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_CLK_MEMCLK, _memoryClock); - _temperatureMemory.Value = logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_MEM].value; - ActivateSensor(_temperatureMemory); + const int fanRpmIndex = (int)AtiAdlxx.ADLSensorType.PMLOG_FAN_RPM; + const int fanPercentageIndex = (int)AtiAdlxx.ADLSensorType.PMLOG_FAN_PERCENTAGE; - _temperatureMvdd.Value = null; - if (logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_VRMVDD].value > 0) + if (fanRpmIndex < logDataOutput.sensors.Length && fanPercentageIndex < logDataOutput.sensors.Length && logDataOutput.sensors[fanRpmIndex].value != ushort.MaxValue) { - _temperatureMvdd.Value = logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_VRMVDD].value; - ActivateSensor(_temperatureMvdd); + _fan.Value = logDataOutput.sensors[fanRpmIndex].value; + _controlSensor.Value = logDataOutput.sensors[fanPercentageIndex].value; + + ActivateSensor(_fan); + ActivateSensor(_controlSensor); } - - _temperatureLiquid.Value = null; - if (logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_LIQUID].value > 0) - { - _temperatureLiquid.Value = logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_LIQUID].value; - ActivateSensor(_temperatureLiquid); - } - - _temperaturePlx.Value = null; - if (logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_PLX].value > 0) - { - _temperaturePlx.Value = logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_PLX].value; - ActivateSensor(_temperaturePlx); - } - - _coreClock.Value = logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_CLK_GFXCLK].value; - ActivateSensor(_coreClock); - - _socClock.Value = logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_CLK_SOCCLK].value; - ActivateSensor(_socClock); - - _memoryClock.Value = logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_CLK_MEMCLK].value; - ActivateSensor(_memoryClock); - - - if (logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_FAN_RPM].value != UInt16.MaxValue) - { - _fan.Value = logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_FAN_RPM].value; - _controlSensor.Value = logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_FAN_PERCENTAGE].value; - } else { _fan.Value = null; _controlSensor.Value = null; } - ActivateSensor(_fan); - ActivateSensor(_controlSensor); - _coreVoltage.Value = 0.001f * logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_SOC_VOLTAGE].value; - ActivateSensor(_coreVoltage); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_GFX_VOLTAGE, _coreVoltage, 0.001f); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_SOC_VOLTAGE, _socVoltage, 0.001f); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_MEM_VOLTAGE, _memoryVoltage, 0.001f); - _memoryVoltage.Value = 0.001f * logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_MEM_VOLTAGE].value; - ActivateSensor(_memoryVoltage); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_INFO_ACTIVITY_GFX, _coreLoad); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_INFO_ACTIVITY_MEM, _memoryLoad); - _coreLoad.Value = logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_INFO_ACTIVITY_GFX].value; - ActivateSensor(_coreLoad); - - _powerCore.Value = null; - if (logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_SOC_POWER].value > 0) - { - _powerCore.Value = logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_SOC_POWER].value; - ActivateSensor(_powerCore); - } - - _powerSocket.Value = logDataOutput.sensors[(int)AtiAdlxx.ADLSensorType.PMLOG_ASIC_POWER].value; - ActivateSensor(_powerSocket); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_GFX_POWER, _powerCore); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_SOC_POWER, _powerSoC); + GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_ASIC_POWER, _powerTotal); } } } + /// + /// Gets the OverdriveN temperature. + /// + /// The type. + /// The sensor. + private void GetODNTemperature(AtiAdlxx.ADLODNTemperatureType type, Sensor sensor) + { + // If a sensor isn't available, some cards report 54000 degrees C. 110C is expected for Navi, so 100 more than that should be enough to use as a maximum. + const int maxTemperature = 210 * 1000; + + int temperature = 0; + if (AtiAdlxx.ADL2_OverdriveN_Temperature_Get(_context, _adapterIndex, type, ref temperature) == AtiAdlxx.ADLStatus.ADL_OK && temperature < maxTemperature) + { + sensor.Value = 0.001f * temperature; + ActivateSensor(sensor); + } + else + { + sensor.Value = null; + } + } + + /// + /// Gets a PMLog sensor value. + /// + /// The data. + /// Type of the sensor. + /// The sensor. + /// The factor. + private void GetPMLog(AtiAdlxx.ADLPMLogDataOutput data, AtiAdlxx.ADLSensorType sensorType, Sensor sensor, float factor = 1.0f) + { + int i = (int)sensorType; + if (i < data.sensors.Length && data.sensors[i].supported != 0) + { + sensor.Value = data.sensors[i].value * factor; + ActivateSensor(sensor); + } + else + { + sensor.Value = null; + } + } + + /// + /// Gets the Overdrive6 power. + /// + /// The type. + /// The sensor. + private void GetOD6Power(AtiAdlxx.ADLODNCurrentPowerType type, Sensor sensor) + { + int powerOf8 = 0; + if (AtiAdlxx.ADL2_Overdrive6_CurrentPower_Get(_context, _adapterIndex, type, ref powerOf8) == AtiAdlxx.ADLStatus.ADL_OK) + { + sensor.Value = powerOf8 >> 8; + ActivateSensor(sensor); + } + else + { + sensor.Value = null; + } + } + public override void Close() { _fanControl.ControlModeChanged -= ControlModeChanged; @@ -441,5 +381,279 @@ namespace LibreHardwareMonitor.Hardware.Gpu base.Close(); } + + public override string GetReport() + { + var r = new StringBuilder(); + + r.AppendLine("AMD GPU"); + r.AppendLine(); + + r.Append("AdapterIndex: "); + r.AppendLine(_adapterIndex.ToString(CultureInfo.InvariantCulture)); + r.AppendLine(); + + r.AppendLine("Overdrive Caps"); + r.AppendLine(); + try + { + int supported = 0; + int enabled = 0; + int version = 0; + AtiAdlxx.ADLStatus status = AtiAdlxx.ADL_Overdrive_Caps(_adapterIndex, ref supported, ref enabled, ref version); + r.Append(" Status: "); + r.AppendLine(status.ToString()); + r.Append(" Supported: "); + r.AppendLine(supported.ToString(CultureInfo.InvariantCulture)); + r.Append(" Enabled: "); + r.AppendLine(enabled.ToString(CultureInfo.InvariantCulture)); + r.Append(" Version: "); + r.AppendLine(version.ToString(CultureInfo.InvariantCulture)); + } + catch (Exception e) + { + r.AppendLine(" Status: " + e.Message); + } + + r.AppendLine(); + + r.AppendLine("Overdrive5 Parameters"); + r.AppendLine(); + try + { + AtiAdlxx.ADLStatus status = AtiAdlxx.ADL_Overdrive5_ODParameters_Get(_adapterIndex, out AtiAdlxx.ADLODParameters p); + r.Append(" Status: "); + r.AppendLine(status.ToString()); + r.AppendFormat(" NumberOfPerformanceLevels: {0}{1}", p.NumberOfPerformanceLevels, Environment.NewLine); + r.AppendFormat(" ActivityReportingSupported: {0}{1}", p.ActivityReportingSupported, Environment.NewLine); + r.AppendFormat(" DiscretePerformanceLevels: {0}{1}", p.DiscretePerformanceLevels, Environment.NewLine); + r.AppendFormat(" EngineClock.Min: {0}{1}", p.EngineClock.Min, Environment.NewLine); + r.AppendFormat(" EngineClock.Max: {0}{1}", p.EngineClock.Max, Environment.NewLine); + r.AppendFormat(" EngineClock.Step: {0}{1}", p.EngineClock.Step, Environment.NewLine); + r.AppendFormat(" MemoryClock.Min: {0}{1}", p.MemoryClock.Min, Environment.NewLine); + r.AppendFormat(" MemoryClock.Max: {0}{1}", p.MemoryClock.Max, Environment.NewLine); + r.AppendFormat(" MemoryClock.Step: {0}{1}", p.MemoryClock.Step, Environment.NewLine); + r.AppendFormat(" Vddc.Min: {0}{1}", p.Vddc.Min, Environment.NewLine); + r.AppendFormat(" Vddc.Max: {0}{1}", p.Vddc.Max, Environment.NewLine); + r.AppendFormat(" Vddc.Step: {0}{1}", p.Vddc.Step, Environment.NewLine); + } + catch (Exception e) + { + r.AppendLine(" Status: " + e.Message); + } + + r.AppendLine(); + + r.AppendLine("Overdrive5 Temperature"); + r.AppendLine(); + try + { + var adlt = new AtiAdlxx.ADLTemperature(); + AtiAdlxx.ADLStatus status = AtiAdlxx.ADL_Overdrive5_Temperature_Get(_adapterIndex, 0, ref adlt); + r.Append(" Status: "); + r.AppendLine(status.ToString()); + r.AppendFormat(" Value: {0}{1}", 0.001f * adlt.Temperature, Environment.NewLine); + } + catch (Exception e) + { + r.AppendLine(" Status: " + e.Message); + } + + r.AppendLine(); + + r.AppendLine("Overdrive5 FanSpeed"); + r.AppendLine(); + try + { + var adlf = new AtiAdlxx.ADLFanSpeedValue { SpeedType = AtiAdlxx.ADL_DL_FANCTRL_SPEED_TYPE_RPM }; + var status = AtiAdlxx.ADL_Overdrive5_FanSpeed_Get(_adapterIndex, 0, ref adlf); + r.Append(" Status RPM: "); + r.AppendLine(status.ToString()); + r.AppendFormat(" Value RPM: {0}{1}", adlf.FanSpeed, Environment.NewLine); + + adlf.SpeedType = AtiAdlxx.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT; + status = AtiAdlxx.ADL_Overdrive5_FanSpeed_Get(_adapterIndex, 0, ref adlf); + r.Append(" Status Percent: "); + r.AppendLine(status.ToString()); + r.AppendFormat(" Value Percent: {0}{1}", adlf.FanSpeed, Environment.NewLine); + } + catch (Exception e) + { + r.AppendLine(" Status: " + e.Message); + } + + r.AppendLine(); + + r.AppendLine("Overdrive5 CurrentActivity"); + r.AppendLine(); + try + { + var adlp = new AtiAdlxx.ADLPMActivity(); + AtiAdlxx.ADLStatus status = AtiAdlxx.ADL_Overdrive5_CurrentActivity_Get(_adapterIndex, ref adlp); + + r.Append(" Status: "); + r.AppendLine(status.ToString()); + r.AppendFormat(" EngineClock: {0}{1}", 0.01f * adlp.EngineClock, Environment.NewLine); + r.AppendFormat(" MemoryClock: {0}{1}", 0.01f * adlp.MemoryClock, Environment.NewLine); + r.AppendFormat(" Vddc: {0}{1}", 0.001f * adlp.Vddc, Environment.NewLine); + r.AppendFormat(" ActivityPercent: {0}{1}", adlp.ActivityPercent, Environment.NewLine); + r.AppendFormat(" CurrentPerformanceLevel: {0}{1}", adlp.CurrentPerformanceLevel, Environment.NewLine); + r.AppendFormat(" CurrentBusSpeed: {0}{1}", adlp.CurrentBusSpeed, Environment.NewLine); + r.AppendFormat(" CurrentBusLanes: {0}{1}", adlp.CurrentBusLanes, Environment.NewLine); + r.AppendFormat(" MaximumBusLanes: {0}{1}", adlp.MaximumBusLanes, Environment.NewLine); + } + catch (Exception e) + { + r.AppendLine(" Status: " + e.Message); + } + + r.AppendLine(); + + if (_context != IntPtr.Zero) + { + r.AppendLine("Overdrive6 CurrentPower"); + r.AppendLine(); + try + { + int power = 0; + for (int i = 0; i < 4; i++) + { + string pt = ((AtiAdlxx.ADLODNCurrentPowerType)i).ToString(); + AtiAdlxx.ADLStatus status = AtiAdlxx.ADL2_Overdrive6_CurrentPower_Get(_context, _adapterIndex, (AtiAdlxx.ADLODNCurrentPowerType)i, ref power); + + if (status == AtiAdlxx.ADLStatus.ADL_OK) + { + r.AppendFormat(" Power[{0}].Value: {1}{2}", pt, power * (1.0f / 0xFF), Environment.NewLine); + } + else + { + r.AppendFormat(" Power[{0}].Status: {1}{2}", pt, status.ToString(), Environment.NewLine); + } + } + } + catch (EntryPointNotFoundException) + { + r.AppendLine(" Status: Entry point not found"); + } + catch (Exception e) + { + r.AppendLine(" Status: " + e.Message); + } + + r.AppendLine(); + } + + if (_context != IntPtr.Zero) + { + r.AppendLine("OverdriveN Temperature"); + r.AppendLine(); + try + { + for (int i = 1; i < 8; i++) + { + int temperature = 0; + string tt = ((AtiAdlxx.ADLODNTemperatureType)i).ToString(); + AtiAdlxx.ADLStatus status = AtiAdlxx.ADL2_OverdriveN_Temperature_Get(_context, _adapterIndex, (AtiAdlxx.ADLODNTemperatureType)i, ref temperature); + if (status == AtiAdlxx.ADLStatus.ADL_OK) + { + r.AppendFormat(" Temperature[{0}].Value: {1}{2}", tt, 0.001f * temperature, Environment.NewLine); + } + else + { + r.AppendFormat(" Temperature[{0}].Status: {1}{2}", tt, status.ToString(), Environment.NewLine); + } + } + } + catch (EntryPointNotFoundException) + { + r.AppendLine(" Status: Entry point not found"); + } + catch (Exception e) + { + r.AppendLine(" Status: " + e.Message); + } + + r.AppendLine(); + } + + if (_context != IntPtr.Zero) + { + r.AppendLine("OverdriveN Performance Status"); + r.AppendLine(); + try + { + var status = AtiAdlxx.ADL2_OverdriveN_PerformanceStatus_Get(_context, _adapterIndex, out var ps); + r.Append(" Status: "); + r.AppendLine(status.ToString()); + r.AppendFormat(" CoreClock: {0}{1}", ps.CoreClock, Environment.NewLine); + r.AppendFormat(" MemoryClock: {0}{1}", ps.MemoryClock, Environment.NewLine); + r.AppendFormat(" DCEFClock: {0}{1}", ps.DCEFClock, Environment.NewLine); + r.AppendFormat(" GFXClock: {0}{1}", ps.GFXClock, Environment.NewLine); + r.AppendFormat(" UVDClock: {0}{1}", ps.UVDClock, Environment.NewLine); + r.AppendFormat(" VCEClock: {0}{1}", ps.VCEClock, Environment.NewLine); + r.AppendFormat(" GPUActivityPercent: {0}{1}", ps.GPUActivityPercent, Environment.NewLine); + r.AppendFormat(" CurrentCorePerformanceLevel: {0}{1}", ps.CurrentCorePerformanceLevel, Environment.NewLine); + r.AppendFormat(" CurrentMemoryPerformanceLevel: {0}{1}", ps.CurrentMemoryPerformanceLevel, Environment.NewLine); + r.AppendFormat(" CurrentDCEFPerformanceLevel: {0}{1}", ps.CurrentDCEFPerformanceLevel, Environment.NewLine); + r.AppendFormat(" CurrentGFXPerformanceLevel: {0}{1}", ps.CurrentGFXPerformanceLevel, Environment.NewLine); + r.AppendFormat(" UVDPerformanceLevel: {0}{1}", ps.UVDPerformanceLevel, Environment.NewLine); + r.AppendFormat(" VCEPerformanceLevel: {0}{1}", ps.VCEPerformanceLevel, Environment.NewLine); + r.AppendFormat(" CurrentBusSpeed: {0}{1}", ps.CurrentBusSpeed, Environment.NewLine); + r.AppendFormat(" CurrentBusLanes: {0}{1}", ps.CurrentBusLanes, Environment.NewLine); + r.AppendFormat(" MaximumBusLanes: {0}{1}", ps.MaximumBusLanes, Environment.NewLine); + r.AppendFormat(" VDDC: {0}{1}", ps.VDDC, Environment.NewLine); + r.AppendFormat(" VDDCI: {0}{1}", ps.VDDCI, Environment.NewLine); + } + catch (EntryPointNotFoundException) + { + r.AppendLine(" Status: Entry point not found"); + } + catch (Exception e) + { + r.AppendLine(" Status: " + e.Message); + } + + r.AppendLine(); + } + + if (_context != IntPtr.Zero) + { + r.AppendLine("Performance Metrics"); + r.AppendLine(); + try + { + var data = new AtiAdlxx.ADLPMLogDataOutput(); + AtiAdlxx.ADLStatus status = AtiAdlxx.ADL2_New_QueryPMLogData_Get(_context, _adapterIndex, ref data); + if (status == AtiAdlxx.ADLStatus.ADL_OK) + { + for (int i = 0; i < data.sensors.Length; i++) + { + if (data.sensors[i].supported != 0) + { + string st = ((AtiAdlxx.ADLSensorType)i).ToString(); + r.AppendFormat(" Sensor[{0}].Value: {1}{2}", st, data.sensors[i].value, Environment.NewLine); + } + } + } + else + { + r.Append(" Status: "); + r.AppendLine(status.ToString()); + } + } + catch (EntryPointNotFoundException) + { + r.AppendLine(" Status: Entry point not found"); + } + catch (Exception e) + { + r.AppendLine(" Status: " + e.Message); + } + + r.AppendLine(); + } + + return r.ToString(); + } } } diff --git a/LibreHardwareMonitorLib/Hardware/Gpu/AmdGpuGroup.cs b/LibreHardwareMonitorLib/Hardware/Gpu/AmdGpuGroup.cs index 5f22e34..81c1486 100644 --- a/LibreHardwareMonitorLib/Hardware/Gpu/AmdGpuGroup.cs +++ b/LibreHardwareMonitorLib/Hardware/Gpu/AmdGpuGroup.cs @@ -16,7 +16,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu { private readonly List _hardware = new List(); private readonly StringBuilder _report = new StringBuilder(); - private readonly int _status; + private readonly AtiAdlxx.ADLStatus _status; public AmdGpuGroup(ISettings settings) { @@ -27,10 +27,10 @@ namespace LibreHardwareMonitor.Hardware.Gpu _report.AppendLine("AMD Display Library"); _report.AppendLine(); _report.Append("Status: "); - _report.AppendLine(_status == AtiAdlxx.ADL_OK ? "OK" : _status.ToString(CultureInfo.InvariantCulture)); + _report.AppendLine(_status == AtiAdlxx.ADLStatus.ADL_OK ? "OK" : _status.ToString()); _report.AppendLine(); - if (_status == AtiAdlxx.ADL_OK) + if (_status == AtiAdlxx.ADLStatus.ADL_OK) { int numberOfAdapters = 0; AtiAdlxx.ADL_Adapter_NumberOfAdapters_Get(ref numberOfAdapters); @@ -42,7 +42,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu if (numberOfAdapters > 0) { AtiAdlxx.ADLAdapterInfo[] adapterInfo = new AtiAdlxx.ADLAdapterInfo[numberOfAdapters]; - if (AtiAdlxx.ADL_Adapter_AdapterInfo_Get(adapterInfo) == AtiAdlxx.ADL_OK) + if (AtiAdlxx.ADL_Adapter_AdapterInfo_Get(adapterInfo) == AtiAdlxx.ADLStatus.ADL_OK) for (int i = 0; i < numberOfAdapters; i++) { AtiAdlxx.ADL_Adapter_Active_Get(adapterInfo[i].AdapterIndex, out int isActive); @@ -117,7 +117,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu foreach (AmdGpu gpu in _hardware) gpu.Close(); - if (_status == AtiAdlxx.ADL_OK) + if (_status == AtiAdlxx.ADLStatus.ADL_OK) AtiAdlxx.ADL_Main_Control_Destroy(); } catch (Exception) diff --git a/LibreHardwareMonitorLib/Interop/AtiAdlxx.cs b/LibreHardwareMonitorLib/Interop/AtiAdlxx.cs index bd95475..ebef520 100644 --- a/LibreHardwareMonitorLib/Interop/AtiAdlxx.cs +++ b/LibreHardwareMonitorLib/Interop/AtiAdlxx.cs @@ -33,11 +33,10 @@ namespace LibreHardwareMonitor.Interop public const int ADL_MAX_NUM_DISPLAYMODES = 1024; public const int ADL_MAX_PATH = 256; - public const int ADL_OK = 0; - public const int ADL_ERR = -1; - public const int ATI_VENDOR_ID = 0x1002; + internal const int ADL_PMLOG_MAX_SENSORS = 256; + internal const string DllName = "atiadlxx.dll"; public static Context Context_Alloc = Marshal.AllocHGlobal; @@ -50,83 +49,92 @@ namespace LibreHardwareMonitor.Interop public delegate IntPtr Context(int size); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL_Main_Control_Create(ADL_Main_Memory_AllocDelegate callback, int enumConnectedAdapters); + public static extern ADLStatus ADL_Main_Control_Create(ADL_Main_Memory_AllocDelegate callback, int enumConnectedAdapters); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL_Main_Control_Destroy(); + public static extern ADLStatus ADL_Main_Control_Destroy(); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL_Adapter_AdapterInfo_Get(IntPtr info, int size); + public static extern ADLStatus ADL_Adapter_AdapterInfo_Get(IntPtr info, int size); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL_Adapter_NumberOfAdapters_Get(); + public static extern ADLStatus ADL_Adapter_NumberOfAdapters_Get(); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL_Adapter_NumberOfAdapters_Get(ref int numAdapters); + public static extern ADLStatus ADL_Adapter_NumberOfAdapters_Get(ref int numAdapters); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL_Adapter_ID_Get(int adapterIndex, out int adapterId); + public static extern ADLStatus ADL_Adapter_ID_Get(int adapterIndex, out int adapterId); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL_Display_AdapterID_Get(int adapterIndex, out int adapterId); + public static extern ADLStatus ADL_Display_AdapterID_Get(int adapterIndex, out int adapterId); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL_Adapter_Active_Get(int adapterIndex, out int status); + public static extern ADLStatus ADL_Adapter_Active_Get(int adapterIndex, out int status); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL_Overdrive5_CurrentActivity_Get(int iAdapterIndex, ref ADLPMActivity activity); + public static extern ADLStatus ADL_Overdrive5_ODParameters_Get(int adapterIndex, out ADLODParameters parameters); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL_Overdrive5_Temperature_Get(int adapterIndex, int thermalControllerIndex, ref ADLTemperature temperature); + public static extern ADLStatus ADL_Overdrive5_CurrentActivity_Get(int iAdapterIndex, ref ADLPMActivity activity); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL2_OverdriveN_Temperature_Get(IntPtr context, int adapterIndex, ADLODNTemperatureType iTemperatureType, ref int temp); + public static extern ADLStatus ADL_Overdrive5_Temperature_Get(int adapterIndex, int thermalControllerIndex, ref ADLTemperature temperature); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL_Overdrive5_FanSpeed_Get(int adapterIndex, int thermalControllerIndex, ref ADLFanSpeedValue fanSpeedValue); + public static extern ADLStatus ADL2_OverdriveN_Temperature_Get(IntPtr context, int adapterIndex, ADLODNTemperatureType iTemperatureType, ref int temp); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL_Overdrive5_FanSpeedInfo_Get(int adapterIndex, int thermalControllerIndex, ref ADLFanSpeedInfo fanSpeedInfo); + public static extern ADLStatus ADL_Overdrive5_FanSpeed_Get(int adapterIndex, int thermalControllerIndex, ref ADLFanSpeedValue fanSpeedValue); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL_Overdrive5_FanSpeedToDefault_Set(int adapterIndex, int thermalControllerIndex); + public static extern ADLStatus ADL_Overdrive5_FanSpeedInfo_Get(int adapterIndex, int thermalControllerIndex, ref ADLFanSpeedInfo fanSpeedInfo); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL_Overdrive5_FanSpeed_Set(int adapterIndex, int thermalControllerIndex, ref ADLFanSpeedValue fanSpeedValue); + public static extern ADLStatus ADL_Overdrive5_FanSpeedToDefault_Set(int adapterIndex, int thermalControllerIndex); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL_Overdrive_Caps(int adapterIndex, ref int supported, ref int enabled, ref int version); + public static extern ADLStatus ADL_Overdrive5_FanSpeed_Set(int adapterIndex, int thermalControllerIndex, ref ADLFanSpeedValue fanSpeedValue); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL2_Overdrive6_CurrentPower_Get(IntPtr context, int adapterIndex, ADLODNCurrentPowerType powerType, ref int currentValue); + public static extern ADLStatus ADL2_OverdriveN_PerformanceStatus_Get(IntPtr context, int adapterIndex, out ADLODNPerformanceStatus performanceStatus); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL2_Main_Control_Create(ADL_Main_Memory_AllocDelegate callback, int connectedAdapters, ref IntPtr context); + public static extern ADLStatus ADL_Overdrive_Caps(int adapterIndex, ref int supported, ref int enabled, ref int version); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL2_Main_Control_Destroy(IntPtr context); + public static extern ADLStatus ADL2_Overdrive6_CurrentPower_Get(IntPtr context, int adapterIndex, ADLODNCurrentPowerType powerType, ref int currentValue); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] - public static extern int ADL2_New_QueryPMLogData_Get(IntPtr context, int adapterIndex, ref ADLPMLogDataOutput aDLPMLogDataOutput); + public static extern ADLStatus ADL2_Main_Control_Create(ADL_Main_Memory_AllocDelegate callback, int connectedAdapters, ref IntPtr context); - public static int ADL_Main_Control_Create(int enumConnectedAdapters) + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern ADLStatus ADL2_Main_Control_Destroy(IntPtr context); + + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern ADLStatus ADL2_New_QueryPMLogData_Get(IntPtr context, int adapterIndex, ref ADLPMLogDataOutput aDLPMLogDataOutput); + + [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] + public static extern ADLStatus ADL_Graphics_Versions_Get(out ADLVersionsInfo versionInfo); + + public static ADLStatus ADL_Main_Control_Create(int enumConnectedAdapters) { try { - return Kernel32.LoadLibrary(DllName) != IntPtr.Zero ? ADL_Main_Control_Create(Main_Memory_Alloc, enumConnectedAdapters) : ADL_ERR; + return Kernel32.LoadLibrary(DllName) != IntPtr.Zero ? ADL_Main_Control_Create(Main_Memory_Alloc, enumConnectedAdapters) : ADLStatus.ADL_ERR; } catch { - return ADL_ERR; + return ADLStatus.ADL_ERR; } } - public static int ADL_Adapter_AdapterInfo_Get(ADLAdapterInfo[] info) + public static ADLStatus ADL_Adapter_AdapterInfo_Get(ADLAdapterInfo[] info) { int elementSize = Marshal.SizeOf(typeof(ADLAdapterInfo)); int size = info.Length * elementSize; IntPtr ptr = Marshal.AllocHGlobal(size); - int result = ADL_Adapter_AdapterInfo_Get(ptr, size); + var result = ADL_Adapter_AdapterInfo_Get(ptr, size); for (int i = 0; i < info.Length; i++) info[i] = (ADLAdapterInfo)Marshal.PtrToStructure((IntPtr)((long)ptr + i * elementSize), typeof(ADLAdapterInfo)); @@ -161,6 +169,106 @@ namespace LibreHardwareMonitor.Interop Marshal.FreeHGlobal(buffer); } + internal enum ADLStatus + { + /// + /// All OK, but need to wait. + /// + ADL_OK_WAIT = 4, + + /// + /// All OK, but need restart. + /// + ADL_OK_RESTART = 3, + + /// + /// All OK but need mode change. + /// + ADL_OK_MODE_CHANGE = 2, + + /// + /// All OK, but with warning. + /// + ADL_OK_WARNING = 1, + + /// + /// ADL function completed successfully. + /// + ADL_OK = 0, + + /// + /// Generic Error. Most likely one or more of the Escape calls to the driver + /// failed! + /// + ADL_ERR = -1, + + /// + /// ADL not initialized. + /// + ADL_ERR_NOT_INIT = -2, + + /// + /// One of the parameter passed is invalid. + /// + ADL_ERR_INVALID_PARAM = -3, + + /// + /// One of the parameter size is invalid. + /// + ADL_ERR_INVALID_PARAM_SIZE = -4, + + /// + /// Invalid ADL index passed. + /// + ADL_ERR_INVALID_ADL_IDX = -5, + + /// + /// Invalid controller index passed. + /// + ADL_ERR_INVALID_CONTROLLER_IDX = -6, + + /// + /// Invalid display index passed. + /// + ADL_ERR_INVALID_DIPLAY_IDX = -7, + + /// + /// Function not supported by the driver. + /// + ADL_ERR_NOT_SUPPORTED = -8, + + /// + /// Null Pointer error. + /// + ADL_ERR_NULL_POINTER = -9, + + /// + /// Call can't be made due to disabled adapter. + /// + ADL_ERR_DISABLED_ADAPTER = -10, + + /// + /// Invalid Callback. + /// + ADL_ERR_INVALID_CALLBACK = -11, + + /// + /// Display Resource conflict. + /// + ADL_ERR_RESOURCE_CONFLICT = -12, + + /// + /// Failed to update some of the values. Can be returned by set request that + /// include multiple values if not all values were successfully committed. + /// + ADL_ERR_SET_INCOMPLETE = -20, + + /// + /// There's no Linux XDisplay in Linux Console environment. + /// + ADL_ERR_NO_XDISPLAY = -21 + } + [StructLayout(LayoutKind.Sequential)] internal struct ADLAdapterInfo { @@ -196,6 +304,27 @@ namespace LibreHardwareMonitor.Interop public int OSDisplayIndex; } + [StructLayout(LayoutKind.Sequential)] + internal struct ADLODParameterRange + { + public int Min; + public int Max; + public int Step; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct ADLODParameters + { + public int Size; + public int NumberOfPerformanceLevels; + public int ActivityReportingSupported; + public int DiscretePerformanceLevels; + public int Reserved; + public ADLODParameterRange EngineClock; + public ADLODParameterRange MemoryClock; + public ADLODParameterRange Vddc; + } + [StructLayout(LayoutKind.Sequential)] internal struct ADLPMActivity { @@ -226,7 +355,7 @@ namespace LibreHardwareMonitor.Interop public int FanSpeed; public int Flags; } - + [StructLayout(LayoutKind.Sequential)] internal struct ADLFanSpeedInfo { @@ -246,6 +375,42 @@ namespace LibreHardwareMonitor.Interop ODN_GPU_CHIP_POWER } + [StructLayout(LayoutKind.Sequential)] + internal struct ADLVersionsInfo + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string DriverVer; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string CatalystVersion; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string CatalystWebLink; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct ADLODNPerformanceStatus + { + public int CoreClock; + public int MemoryClock; + public int DCEFClock; + public int GFXClock; + public int UVDClock; + public int VCEClock; + public int GPUActivityPercent; + public int CurrentCorePerformanceLevel; + public int CurrentMemoryPerformanceLevel; + public int CurrentDCEFPerformanceLevel; + public int CurrentGFXPerformanceLevel; + public int UVDPerformanceLevel; + public int VCEPerformanceLevel; + public int CurrentBusSpeed; + public int CurrentBusLanes; + public int MaximumBusLanes; + public int VDDC; + public int VDDCI; + } + internal enum ADLODNTemperatureType { // This typed is named like this in the documentation but for some reason AMD failed to include it... @@ -259,8 +424,6 @@ namespace LibreHardwareMonitor.Interop HOTSPOT = 7 } - internal const int ADL_PMLOG_MAX_SENSORS = 256; - [StructLayout(LayoutKind.Sequential)] internal struct ADLSingleSensorData { @@ -272,6 +435,7 @@ namespace LibreHardwareMonitor.Interop internal struct ADLPMLogDataOutput { public int size; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = ADL_PMLOG_MAX_SENSORS)] public ADLSingleSensorData[] sensors; } @@ -305,7 +469,20 @@ namespace LibreHardwareMonitor.Interop PMLOG_TEMPERATURE_VRSOC = 24, PMLOG_TEMPERATURE_VRMVDD0 = 25, PMLOG_TEMPERATURE_VRMVDD1 = 26, - PMLOG_TEMPERATURE_HOTSPOT = 27 + 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 } } }