@@ -40,6 +40,9 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
private readonly Sensor[] _powers;
|
||||
private readonly Sensor _powerUsage;
|
||||
private readonly Sensor[] _temperatures;
|
||||
private uint _thermalSensorsMask;
|
||||
private readonly Sensor _hotSpotTemperature;
|
||||
private readonly Sensor _memoryJunctionTemperature;
|
||||
|
||||
public NvidiaGpu(int adapterIndex, NvApi.NvPhysicalGpuHandle handle, NvApi.NvDisplayHandle? displayHandle, ISettings settings)
|
||||
: base(GetName(handle),
|
||||
@@ -79,6 +82,32 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
}
|
||||
}
|
||||
|
||||
// Thermal sensors.
|
||||
_hotSpotTemperature = new Sensor("GPU Hot Spot", (int)thermalSettings.Count + 1, SensorType.Temperature, this, settings);
|
||||
_memoryJunctionTemperature = new Sensor("GPU Memory Junction", (int)thermalSettings.Count + 2, SensorType.Temperature, this, settings);
|
||||
bool hasAnyThermalSensor = false;
|
||||
|
||||
for (int thermalSensorsMaxBit = 0; thermalSensorsMaxBit < 32; thermalSensorsMaxBit++)
|
||||
{
|
||||
// Find the maximum thermal sensor mask value.
|
||||
_thermalSensorsMask = 1u << thermalSensorsMaxBit;
|
||||
|
||||
GetThermalSensors(_thermalSensorsMask, out NvApi.NvStatus thermalSensorsStatus);
|
||||
if (thermalSensorsStatus == NvApi.NvStatus.OK)
|
||||
{
|
||||
hasAnyThermalSensor = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
_thermalSensorsMask--;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!hasAnyThermalSensor)
|
||||
{
|
||||
_thermalSensorsMask = 0;
|
||||
}
|
||||
|
||||
// Clock frequencies.
|
||||
for (int clockVersion = 1; clockVersion <= 3; clockVersion++)
|
||||
{
|
||||
@@ -434,6 +463,28 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
}
|
||||
}
|
||||
|
||||
if (_thermalSensorsMask > 0)
|
||||
{
|
||||
NvApi.NvThermalSensors thermalSensors = GetThermalSensors(_thermalSensorsMask, out status);
|
||||
|
||||
if (status == NvApi.NvStatus.OK)
|
||||
{
|
||||
_hotSpotTemperature.Value = thermalSensors.Temperatures[1] / 256.0f;
|
||||
_memoryJunctionTemperature.Value = thermalSensors.Temperatures[9] / 256.0f;
|
||||
}
|
||||
|
||||
if (_hotSpotTemperature.Value != 0)
|
||||
ActivateSensor(_hotSpotTemperature);
|
||||
|
||||
if (_memoryJunctionTemperature.Value != 0)
|
||||
ActivateSensor(_memoryJunctionTemperature);
|
||||
}
|
||||
else
|
||||
{
|
||||
_hotSpotTemperature.Value = null;
|
||||
_memoryJunctionTemperature.Value = null;
|
||||
}
|
||||
|
||||
if (_clocks is { Length: > 0 })
|
||||
{
|
||||
NvApi.NvGpuClockFrequencies clockFrequencies = GetClockFrequencies(out status);
|
||||
@@ -928,6 +979,24 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
return status == NvApi.NvStatus.OK ? settings : default;
|
||||
}
|
||||
|
||||
private NvApi.NvThermalSensors GetThermalSensors(uint mask, out NvApi.NvStatus status)
|
||||
{
|
||||
if (NvApi.NvAPI_GPU_ThermalGetSensors == null)
|
||||
{
|
||||
status = NvApi.NvStatus.Error;
|
||||
return default;
|
||||
}
|
||||
|
||||
var thermalSensors = new NvApi.NvThermalSensors()
|
||||
{
|
||||
Version = (uint)NvApi.MAKE_NVAPI_VERSION<NvApi.NvThermalSensors>(2),
|
||||
Mask = mask
|
||||
};
|
||||
|
||||
status = NvApi.NvAPI_GPU_ThermalGetSensors(_handle, ref thermalSensors);
|
||||
return status == NvApi.NvStatus.OK ? thermalSensors : default;
|
||||
}
|
||||
|
||||
private NvApi.NvFanCoolersStatus GetFanCoolersStatus(out NvApi.NvStatus status)
|
||||
{
|
||||
if (NvApi.NvAPI_GPU_ClientFanCoolersGetStatus == null)
|
||||
@@ -938,7 +1007,8 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
var coolers = new NvApi.NvFanCoolersStatus
|
||||
{
|
||||
Version = (uint)NvApi.MAKE_NVAPI_VERSION<NvApi.NvFanCoolersStatus>(1), Items = new NvApi.NvFanCoolersStatusItem[NvApi.MAX_FAN_COOLERS_STATUS_ITEMS]
|
||||
Version = (uint)NvApi.MAKE_NVAPI_VERSION<NvApi.NvFanCoolersStatus>(1),
|
||||
Items = new NvApi.NvFanCoolersStatusItem[NvApi.MAX_FAN_COOLERS_STATUS_ITEMS]
|
||||
};
|
||||
|
||||
status = NvApi.NvAPI_GPU_ClientFanCoolersGetStatus(_handle, ref coolers);
|
||||
@@ -983,7 +1053,8 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
NvApi.NvDynamicPStatesInfo pStatesInfo = new()
|
||||
{
|
||||
Version = (uint)NvApi.MAKE_NVAPI_VERSION<NvApi.NvDynamicPStatesInfo>(1), Utilizations = new NvApi.NvDynamicPState[NvApi.MAX_GPU_UTILIZATIONS]
|
||||
Version = (uint)NvApi.MAKE_NVAPI_VERSION<NvApi.NvDynamicPStatesInfo>(1),
|
||||
Utilizations = new NvApi.NvDynamicPState[NvApi.MAX_GPU_UTILIZATIONS]
|
||||
};
|
||||
|
||||
status = NvApi.NvAPI_GPU_GetDynamicPstatesInfoEx(_handle, ref pStatesInfo);
|
||||
|
||||
@@ -17,6 +17,8 @@ namespace LibreHardwareMonitor.Interop
|
||||
public const int MAX_POWER_TOPOLOGIES = 4;
|
||||
public const int MAX_THERMAL_SENSORS_PER_GPU = 3;
|
||||
public const int MAX_USAGES_PER_GPU = 8;
|
||||
public const int THERMAL_SENSOR_RESERVED_COUNT = 8;
|
||||
public const int THERMAL_SENSOR_TEMPERATURE_COUNT = 32;
|
||||
|
||||
public const int SHORT_STRING_MAX = 64;
|
||||
|
||||
@@ -39,6 +41,7 @@ namespace LibreHardwareMonitor.Interop
|
||||
public static readonly NvAPI_GPU_GetThermalSettingsDelegate NvAPI_GPU_GetThermalSettings;
|
||||
public static readonly NvAPI_GPU_GetUsagesDelegate NvAPI_GPU_GetUsages;
|
||||
public static readonly NvAPI_GPU_SetCoolerLevelsDelegate NvAPI_GPU_SetCoolerLevels;
|
||||
public static readonly NvAPI_GPU_GetThermalSensorsDelegate NvAPI_GPU_ThermalGetSensors;
|
||||
|
||||
private static readonly NvAPI_GetInterfaceVersionStringDelegate _nvAPI_GetInterfaceVersionString;
|
||||
private static readonly NvAPI_GPU_GetFullNameDelegate _nvAPI_GPU_GetFullName;
|
||||
@@ -87,6 +90,7 @@ namespace LibreHardwareMonitor.Interop
|
||||
GetDelegate(0x814B209F, out NvAPI_GPU_ClientFanCoolersGetControl);
|
||||
GetDelegate(0xA58971A5, out NvAPI_GPU_ClientFanCoolersSetControl);
|
||||
GetDelegate(0x0EDCF624E, out NvAPI_GPU_ClientPowerTopologyGetStatus);
|
||||
GetDelegate(0x65FE3AAD, out NvAPI_GPU_ThermalGetSensors);
|
||||
|
||||
IsAvailable = true;
|
||||
}
|
||||
@@ -152,6 +156,9 @@ namespace LibreHardwareMonitor.Interop
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GPU_SetCoolerLevelsDelegate(NvPhysicalGpuHandle gpuHandle, int coolerIndex, ref NvCoolerLevels NvCoolerLevels);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GPU_GetThermalSensorsDelegate(NvPhysicalGpuHandle gpuHandle, ref NvThermalSensors nvThermalSensors);
|
||||
|
||||
public enum NvFanControlMode : uint
|
||||
{
|
||||
Auto = 0,
|
||||
@@ -502,6 +509,19 @@ namespace LibreHardwareMonitor.Interop
|
||||
public NvLevel[] Levels;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
public struct NvThermalSensors
|
||||
{
|
||||
internal uint Version;
|
||||
internal uint Mask;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = THERMAL_SENSOR_RESERVED_COUNT)]
|
||||
internal int[] Reserved;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = THERMAL_SENSOR_TEMPERATURE_COUNT)]
|
||||
internal int[] Temperatures;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal struct NvMemoryInfo
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user