Add sensors for Astral GPUs (#2168)
* Add sensors for Astral GPUs * Clean up imports * Code clean-up --------- Co-authored-by: PhyxionNL <7643972+PhyxionNL@users.noreply.github.com>
This commit is contained in:
@@ -45,6 +45,21 @@ internal sealed class NvidiaGpu : GenericGpu
|
||||
private readonly Sensor _coreVoltage;
|
||||
private readonly Sensor[] _temperatures;
|
||||
private readonly uint _thermalSensorsMask;
|
||||
private readonly Sensor[] _12VHPwrPinCurrentSensors;
|
||||
private readonly Sensor[] _12VHPwrPinVoltageSensors;
|
||||
private readonly Sensor[] _12VHPwrPinPowerSensors;
|
||||
private readonly Sensor _12VHPwrConnectorPowerSensor;
|
||||
private readonly Sensor _12VHPwrConnectorCurrentSensor;
|
||||
|
||||
// ASUS Astral subsystem IDs for 12VHPwr pin monitoring
|
||||
private static readonly uint[] AstralSubSystemIds =
|
||||
[
|
||||
0x89EA1043, // Astral 5090D OC
|
||||
0x8A611043, // Astral 5090 Matrix
|
||||
0x89EC1043, // Astral 5090 LC
|
||||
0x89E31043, // Astral 5090 OC
|
||||
0x89DE1043, // Astral 5080 OC
|
||||
];
|
||||
|
||||
public NvidiaGpu(int adapterIndex, NvApi.NvPhysicalGpuHandle handle, NvApi.NvDisplayHandle? displayHandle, ISettings settings)
|
||||
: base(GetName(handle),
|
||||
@@ -434,6 +449,58 @@ internal sealed class NvidiaGpu : GenericGpu
|
||||
_memoryTotal = new Sensor("GPU Memory Total", 2, SensorType.SmallData, this, settings);
|
||||
_memoryLoad = new Sensor("GPU Memory", 3, SensorType.Load, this, settings);
|
||||
|
||||
// Pin power sensors for NVIDIA RTX Astral series from ASUS
|
||||
if (NvApi.NvAPI_I2CReadEx != null && NvApi.NvAPI_GPU_GetPCIIdentifiers != null)
|
||||
{
|
||||
NvApi.NvStatus pciIdentifierStatus = NvApi.NvAPI_GPU_GetPCIIdentifiers(_handle, out _, out uint subSystemId, out _, out _);
|
||||
|
||||
if (pciIdentifierStatus == NvApi.NvStatus.OK && AstralSubSystemIds.Contains(subSystemId))
|
||||
{
|
||||
_12VHPwrPinVoltageSensors =
|
||||
[
|
||||
new Sensor("12VHPWR Pin 1", 0, SensorType.Voltage, this, settings),
|
||||
new Sensor("12VHPWR Pin 2", 1, SensorType.Voltage, this, settings),
|
||||
new Sensor("12VHPWR Pin 3", 2, SensorType.Voltage, this, settings),
|
||||
new Sensor("12VHPWR Pin 4", 3, SensorType.Voltage, this, settings),
|
||||
new Sensor("12VHPWR Pin 5", 4, SensorType.Voltage, this, settings),
|
||||
new Sensor("12VHPWR Pin 6", 5, SensorType.Voltage, this, settings),
|
||||
];
|
||||
_12VHPwrPinCurrentSensors =
|
||||
[
|
||||
new Sensor("12VHPWR Pin 1", 1, SensorType.Current, this, settings),
|
||||
new Sensor("12VHPWR Pin 2", 2, SensorType.Current, this, settings),
|
||||
new Sensor("12VHPWR Pin 3", 3, SensorType.Current, this, settings),
|
||||
new Sensor("12VHPWR Pin 4", 4, SensorType.Current, this, settings),
|
||||
new Sensor("12VHPWR Pin 5", 5, SensorType.Current, this, settings),
|
||||
new Sensor("12VHPWR Pin 6", 6, SensorType.Current, this, settings),
|
||||
];
|
||||
_12VHPwrPinPowerSensors =
|
||||
[
|
||||
new Sensor("12VHPWR Pin 1", 2, SensorType.Power, this, settings),
|
||||
new Sensor("12VHPWR Pin 2", 3, SensorType.Power, this, settings),
|
||||
new Sensor("12VHPWR Pin 3", 4, SensorType.Power, this, settings),
|
||||
new Sensor("12VHPWR Pin 4", 5, SensorType.Power, this, settings),
|
||||
new Sensor("12VHPWR Pin 5", 6, SensorType.Power, this, settings),
|
||||
new Sensor("12VHPWR Pin 6", 7, SensorType.Power, this, settings),
|
||||
];
|
||||
|
||||
foreach (Sensor sensor in _12VHPwrPinVoltageSensors)
|
||||
ActivateSensor(sensor);
|
||||
|
||||
foreach (Sensor sensor in _12VHPwrPinCurrentSensors)
|
||||
ActivateSensor(sensor);
|
||||
|
||||
foreach (Sensor sensor in _12VHPwrPinPowerSensors)
|
||||
ActivateSensor(sensor);
|
||||
|
||||
_12VHPwrConnectorPowerSensor = new Sensor("12VHPWR Connector", 1, SensorType.Power, this, settings);
|
||||
_12VHPwrConnectorCurrentSensor = new Sensor("12VHPWR Connector", 0, SensorType.Current, this, settings);
|
||||
|
||||
ActivateSensor(_12VHPwrConnectorPowerSensor);
|
||||
ActivateSensor(_12VHPwrConnectorCurrentSensor);
|
||||
}
|
||||
}
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
@@ -681,6 +748,75 @@ internal sealed class NvidiaGpu : GenericGpu
|
||||
ActivateSensor(_pcieThroughputTx);
|
||||
}
|
||||
}
|
||||
|
||||
// Astral specific
|
||||
if (_12VHPwrPinCurrentSensors is { Length: > 0 } && TryReadAstral12VHPwrPinSensors(out ushort[] pinSensorValues))
|
||||
{
|
||||
float connectorCurrent = 0;
|
||||
float connectorPower = 0;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
float current = pinSensorValues[i * 2] / 1000f;
|
||||
float voltage = pinSensorValues[i * 2 + 1] / 1000f;
|
||||
_12VHPwrPinVoltageSensors[i].Value = voltage;
|
||||
_12VHPwrPinCurrentSensors[i].Value = current;
|
||||
_12VHPwrPinPowerSensors[i].Value = voltage * current;
|
||||
|
||||
connectorCurrent += current;
|
||||
connectorPower += voltage * current;
|
||||
}
|
||||
|
||||
_12VHPwrConnectorCurrentSensor.Value = connectorCurrent;
|
||||
_12VHPwrConnectorPowerSensor.Value = connectorPower;
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryReadAstral12VHPwrPinSensors(out ushort[] data)
|
||||
{
|
||||
data = null;
|
||||
|
||||
if (NvApi.NvAPI_I2CReadEx == null)
|
||||
return false;
|
||||
|
||||
byte[] dataBuffer = new byte[24];
|
||||
byte[] regAddress = [0x80];
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* pData = dataBuffer)
|
||||
fixed (byte* pRegAddr = regAddress)
|
||||
{
|
||||
NvApi.NvI2CInfo i2cInfo = new()
|
||||
{
|
||||
Version = (uint)NvApi.MAKE_NVAPI_VERSION<NvApi.NvI2CInfo>(3),
|
||||
DisplayMask = 0,
|
||||
IsDDCPort = 0,
|
||||
I2CDevAddress = 0x2B << 1,
|
||||
I2CRegAddress = (IntPtr)pRegAddr,
|
||||
RegAddrSize = 1,
|
||||
Data = (IntPtr)pData,
|
||||
Size = 24,
|
||||
I2CSpeed = NvApi.NVAPI_I2C_SPEED_DEPRECATED,
|
||||
I2CSpeedKhz = NvApi.NvI2CSpeed.Speed100Khz,
|
||||
PortId = 0x1,
|
||||
IsPortIdSet = 1
|
||||
};
|
||||
|
||||
uint readData = 0;
|
||||
if (NvApi.NvAPI_I2CReadEx(_handle, ref i2cInfo, ref readData) != NvApi.NvStatus.OK)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse 12 x u16 big-endian (as mV and mA) values in reverse order
|
||||
data = new ushort[12];
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
int pinIndex = 11 - i;
|
||||
data[i] = (ushort)((dataBuffer[pinIndex * 2] << 8) | dataBuffer[pinIndex * 2 + 1]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string GetReport()
|
||||
|
||||
@@ -23,6 +23,8 @@ internal static class NvApi
|
||||
public const int THERMAL_SENSOR_RESERVED_COUNT = 8;
|
||||
public const int THERMAL_SENSOR_TEMPERATURE_COUNT = 32;
|
||||
|
||||
public const uint NVAPI_I2C_SPEED_DEPRECATED = 0xFFFF;
|
||||
|
||||
private const string DllName = "nvapi.dll";
|
||||
private const string DllName64 = "nvapi64.dll";
|
||||
|
||||
@@ -46,6 +48,7 @@ internal static class NvApi
|
||||
public static NvAPI_GPU_GetUsagesDelegate NvAPI_GPU_GetUsages { get; internal set; }
|
||||
public static NvAPI_GPU_SetCoolerLevelsDelegate NvAPI_GPU_SetCoolerLevels { get; internal set; }
|
||||
public static NvAPI_GPU_GetThermalSensorsDelegate NvAPI_GPU_GetThermalSensors { get; internal set; }
|
||||
public static NvAPI_I2CReadExDelegate NvAPI_I2CReadEx { get; internal set; }
|
||||
public static NvAPI_GPU_ClientVoltRailsGetStatusDelegate NvAPI_GPU_ClientVoltRailsGetStatus { get; internal set; }
|
||||
|
||||
private static NvAPI_GetInterfaceVersionStringDelegate _nvAPI_GetInterfaceVersionString;
|
||||
@@ -91,6 +94,7 @@ internal static class NvApi
|
||||
NvAPI_GPU_ClientFanCoolersSetControl = GetDelegate<NvAPI_GPU_ClientFanCoolersSetControlDelegate>(0xA58971A5);
|
||||
NvAPI_GPU_ClientPowerTopologyGetStatus = GetDelegate<NvAPI_GPU_ClientPowerTopologyGetStatusDelegate>(0x0EDCF624E);
|
||||
NvAPI_GPU_GetThermalSensors = GetDelegate<NvAPI_GPU_GetThermalSensorsDelegate>(0x65FE3AAD);
|
||||
NvAPI_I2CReadEx = GetDelegate<NvAPI_I2CReadExDelegate>(0x4D7B0709);
|
||||
NvAPI_GPU_ClientVoltRailsGetStatus = GetDelegate<NvAPI_GPU_ClientVoltRailsGetStatusDelegate>(0x465F9BCF);
|
||||
|
||||
IsAvailable = true;
|
||||
@@ -160,6 +164,9 @@ internal static class NvApi
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GPU_SetCoolerLevelsDelegate(NvPhysicalGpuHandle gpuHandle, int coolerIndex, ref NvCoolerLevels NvCoolerLevels);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_I2CReadExDelegate(NvPhysicalGpuHandle gpuHandle, ref NvI2CInfo i2cInfo, ref uint readData);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GPU_ClientVoltRailsGetStatusDelegate(NvPhysicalGpuHandle gpuHandle, ref NvGpuClientVoltRailsStatus status);
|
||||
|
||||
@@ -194,6 +201,17 @@ internal static class NvApi
|
||||
BusInterface // Bus
|
||||
}
|
||||
|
||||
public enum NvI2CSpeed : uint
|
||||
{
|
||||
Default = 0,
|
||||
Speed3Khz = 1,
|
||||
Speed10Khz = 2,
|
||||
Speed33Khz = 3,
|
||||
Speed100Khz = 4,
|
||||
Speed200Khz = 5,
|
||||
Speed400Khz = 6
|
||||
}
|
||||
|
||||
public static bool IsAvailable { get; private set; }
|
||||
|
||||
[DllImport(DllName, EntryPoint = "nvapi_QueryInterface", CallingConvention = CallingConvention.Cdecl, PreserveSig = true)]
|
||||
@@ -628,6 +646,23 @@ internal static class NvApi
|
||||
public bool IsPresent => (_isPresent & 1) != 0;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal struct NvI2CInfo
|
||||
{
|
||||
public uint Version;
|
||||
public uint DisplayMask;
|
||||
public byte IsDDCPort;
|
||||
public byte I2CDevAddress;
|
||||
public IntPtr I2CRegAddress;
|
||||
public uint RegAddrSize;
|
||||
public IntPtr Data;
|
||||
public uint Size;
|
||||
public uint I2CSpeed;
|
||||
public NvI2CSpeed I2CSpeedKhz;
|
||||
public byte PortId;
|
||||
public uint IsPortIdSet;
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate NvStatus NvAPI_InitializeDelegate();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user