@@ -23,8 +23,10 @@ namespace LibreHardwareMonitor.Hardware
|
||||
float minSoftwareValue,
|
||||
float maxSoftwareValue)
|
||||
{
|
||||
Identifier = new Identifier(sensor.Identifier, "control");
|
||||
_settings = settings;
|
||||
|
||||
Identifier = new Identifier(sensor.Identifier, "control");
|
||||
Sensor = sensor;
|
||||
MinSoftwareValue = minSoftwareValue;
|
||||
MaxSoftwareValue = maxSoftwareValue;
|
||||
|
||||
@@ -42,6 +44,10 @@ namespace LibreHardwareMonitor.Hardware
|
||||
_mode = (ControlMode)mode;
|
||||
}
|
||||
|
||||
internal event ControlEventHandler ControlModeChanged;
|
||||
|
||||
internal event ControlEventHandler SoftwareControlValueChanged;
|
||||
|
||||
public ControlMode ControlMode
|
||||
{
|
||||
get { return _mode; }
|
||||
@@ -62,6 +68,8 @@ namespace LibreHardwareMonitor.Hardware
|
||||
|
||||
public float MinSoftwareValue { get; }
|
||||
|
||||
public ISensor Sensor { get; }
|
||||
|
||||
public float SoftwareValue
|
||||
{
|
||||
get { return _softwareValue; }
|
||||
@@ -86,9 +94,5 @@ namespace LibreHardwareMonitor.Hardware
|
||||
ControlMode = ControlMode.Software;
|
||||
SoftwareValue = value;
|
||||
}
|
||||
|
||||
internal event ControlEventHandler ControlModeChanged;
|
||||
|
||||
internal event ControlEventHandler SoftwareControlValueChanged;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,16 @@
|
||||
// All Rights Reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using LibreHardwareMonitor.Interop;
|
||||
using Microsoft.Win32;
|
||||
using NvAPIWrapper.GPU;
|
||||
using NvAPIWrapper.Native.Exceptions;
|
||||
using NvAPIWrapper.Native.GPU;
|
||||
using NvAPIWrapper.Native.GPU.Structures;
|
||||
|
||||
namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
{
|
||||
@@ -16,109 +22,184 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
{
|
||||
private readonly int _adapterIndex;
|
||||
private readonly Sensor[] _clocks;
|
||||
private readonly Sensor _control;
|
||||
private readonly NvApi.NvDisplayHandle? _displayHandle;
|
||||
private readonly Sensor _fan;
|
||||
private readonly Control _fanControl;
|
||||
private readonly Sensor[] _controls;
|
||||
private readonly Control[] _fanControls;
|
||||
private readonly Sensor[] _fans;
|
||||
private readonly Sensor _gpuDedicatedMemoryUsage;
|
||||
private readonly Sensor[] _gpuNodeUsage;
|
||||
private readonly DateTime[] _gpuNodeUsagePrevTick;
|
||||
private readonly long[] _gpuNodeUsagePrevValue;
|
||||
private readonly Sensor _gpuSharedMemoryUsage;
|
||||
private readonly NvApi.NvPhysicalGpuHandle _handle;
|
||||
private readonly Sensor[] _loads;
|
||||
private readonly Sensor _memoryAvail;
|
||||
private readonly Sensor _memoryFree;
|
||||
private readonly Sensor _memoryLoad;
|
||||
private readonly int _memorySensorIndex;
|
||||
private readonly Sensor _memoryTotal;
|
||||
private readonly Sensor _memoryUsed;
|
||||
private readonly int _nodeSensorIndex;
|
||||
private readonly NvidiaML.NvmlDevice? _nvmlDevice;
|
||||
private readonly Sensor _pcieThroughputRx;
|
||||
private readonly Sensor _pcieThroughputTx;
|
||||
private readonly PhysicalGPU _physicalGpu;
|
||||
private readonly Sensor[] _powers;
|
||||
private readonly Sensor _powerUsage;
|
||||
private readonly Sensor[] _temperatures;
|
||||
private readonly string _windowsDeviceName;
|
||||
|
||||
public NvidiaGpu(int adapterIndex, NvApi.NvPhysicalGpuHandle handle, NvApi.NvDisplayHandle? displayHandle, ISettings settings)
|
||||
: base(GetName(handle), new Identifier("gpu-nvidia", adapterIndex.ToString(CultureInfo.InvariantCulture)), settings)
|
||||
public NvidiaGpu(int adapterIndex, PhysicalGPU physicalGpu, ISettings settings)
|
||||
: base(GetName(physicalGpu),
|
||||
new Identifier("gpu-nvidia", adapterIndex.ToString(CultureInfo.InvariantCulture)),
|
||||
settings)
|
||||
{
|
||||
_adapterIndex = adapterIndex;
|
||||
_handle = handle;
|
||||
_displayHandle = displayHandle;
|
||||
_physicalGpu = physicalGpu;
|
||||
|
||||
bool hasPciBusId = NvApi.NvAPI_GPU_GetBusId(handle, out uint busId) == NvApi.NvStatus.OK;
|
||||
int busId = -1;
|
||||
|
||||
NvApi.NvGPUThermalSettings thermalSettings = GetThermalSettings();
|
||||
_temperatures = new Sensor[thermalSettings.Count];
|
||||
for (int i = 0; i < _temperatures.Length; i++)
|
||||
try
|
||||
{
|
||||
NvApi.NvSensor sensor = thermalSettings.Sensor[i];
|
||||
string name;
|
||||
switch (sensor.Target)
|
||||
busId = physicalGpu.BusInformation.BusId;
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
try
|
||||
{
|
||||
GPUThermalSensor[] thermalSensors = physicalGpu.ThermalInformation.ThermalSensors.ToArray();
|
||||
_temperatures = new Sensor[thermalSensors.Length];
|
||||
|
||||
for (int i = 0; i < thermalSensors.Length; i++)
|
||||
{
|
||||
case NvApi.NvThermalTarget.BOARD:
|
||||
name = "GPU Board";
|
||||
break;
|
||||
case NvApi.NvThermalTarget.GPU:
|
||||
name = "GPU Core";
|
||||
break;
|
||||
case NvApi.NvThermalTarget.MEMORY:
|
||||
name = "GPU Memory";
|
||||
break;
|
||||
case NvApi.NvThermalTarget.POWER_SUPPLY:
|
||||
name = "GPU Power Supply";
|
||||
break;
|
||||
case NvApi.NvThermalTarget.UNKNOWN:
|
||||
name = "GPU Unknown";
|
||||
break;
|
||||
default:
|
||||
name = "GPU";
|
||||
break;
|
||||
GPUThermalSensor sensor = thermalSensors[i];
|
||||
|
||||
string name = sensor.Target switch
|
||||
{
|
||||
ThermalSettingsTarget.GPU => "GPU Core",
|
||||
ThermalSettingsTarget.Memory => "GPU Memory",
|
||||
ThermalSettingsTarget.PowerSupply => "GPU Power Supply",
|
||||
ThermalSettingsTarget.Board => "GPU Board",
|
||||
ThermalSettingsTarget.VisualComputingBoard => "GPU Visual Computing Board",
|
||||
ThermalSettingsTarget.VisualComputingInlet => "GPU Visual Computing Inlet",
|
||||
ThermalSettingsTarget.VisualComputingOutlet => "GPU Visual Computing Outlet",
|
||||
_ => "GPU"
|
||||
};
|
||||
|
||||
_temperatures[i] = new Sensor(name, i, SensorType.Temperature, this, new ParameterDescription[0], settings);
|
||||
ActivateSensor(_temperatures[i]);
|
||||
}
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
try
|
||||
{
|
||||
KeyValuePair<PublicClockDomain, ClockDomainInfo>[] clocks = physicalGpu.CurrentClockFrequencies.Clocks.OrderBy(x => x.Key).ToArray();
|
||||
_clocks = new Sensor[clocks.Length];
|
||||
|
||||
for (int i = 0; i < clocks.Length; i++)
|
||||
{
|
||||
KeyValuePair<PublicClockDomain, ClockDomainInfo> clock = clocks[i];
|
||||
|
||||
string name = clock.Key switch
|
||||
{
|
||||
PublicClockDomain.Graphics => "GPU Core",
|
||||
PublicClockDomain.Memory => "GPU Memory",
|
||||
PublicClockDomain.Processor => "GPU Shader",
|
||||
PublicClockDomain.Video => "GPU Video",
|
||||
_ => null
|
||||
};
|
||||
|
||||
_clocks[i] = new Sensor(name, i, SensorType.Clock, this, settings);
|
||||
ActivateSensor(_clocks[i]);
|
||||
}
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
try
|
||||
{
|
||||
GPUUsageDomainStatus[] usages = physicalGpu.UsageInformation.UtilizationDomainsStatus.ToArray();
|
||||
_loads = new Sensor[usages.Length + 1];
|
||||
|
||||
for (int i = 0; i < usages.Length; i++)
|
||||
{
|
||||
string name = usages[i].Domain switch
|
||||
{
|
||||
UtilizationDomain.GPU => "GPU Core",
|
||||
UtilizationDomain.FrameBuffer => "GPU Memory Controller",
|
||||
UtilizationDomain.VideoEngine => "GPU Video Engine",
|
||||
UtilizationDomain.BusInterface => "GPU Bus",
|
||||
_ => null
|
||||
};
|
||||
|
||||
_loads[i] = new Sensor(name, i, SensorType.Load, this, settings);
|
||||
ActivateSensor(_loads[i]);
|
||||
}
|
||||
|
||||
_temperatures[i] = new Sensor(name, i, SensorType.Temperature, this, new ParameterDescription[0], settings);
|
||||
ActivateSensor(_temperatures[i]);
|
||||
_loads[_loads.Length - 1] = new Sensor("GPU Memory", _loads.Length - 1, SensorType.Load, this, settings);
|
||||
ActivateSensor(_loads[_loads.Length - 1]);
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
if (NvApi.NvAPI_GPU_GetTachReading != null && NvApi.NvAPI_GPU_GetTachReading(handle, out _) == NvApi.NvStatus.OK)
|
||||
_fan = new Sensor("GPU", 0, SensorType.Fan, this, settings);
|
||||
else if (NvApi.NvAPI_GPU_ClientFanCoolersGetStatus != null && GetCoolerSettings().Count > 0)
|
||||
_fan = new Sensor("GPU", 0, SensorType.Fan, this, settings);
|
||||
|
||||
_clocks = new Sensor[3];
|
||||
_clocks[0] = new Sensor("GPU Core", 0, SensorType.Clock, this, settings);
|
||||
_clocks[1] = new Sensor("GPU Memory", 1, SensorType.Clock, this, settings);
|
||||
_clocks[2] = new Sensor("GPU Shader", 2, SensorType.Clock, this, settings);
|
||||
for (int i = 0; i < _clocks.Length; i++)
|
||||
ActivateSensor(_clocks[i]);
|
||||
|
||||
_loads = new Sensor[4];
|
||||
_loads[0] = new Sensor("GPU Core", 0, SensorType.Load, this, settings);
|
||||
_loads[1] = new Sensor("GPU Memory Controller", 1, SensorType.Load, this, settings);
|
||||
_loads[2] = new Sensor("GPU Video Engine", 2, SensorType.Load, this, settings);
|
||||
_loads[3] = new Sensor("GPU Bus", 4, SensorType.Load, this, settings);
|
||||
|
||||
_memoryLoad = new Sensor("GPU Memory", 3, SensorType.Load, this, settings);
|
||||
_memoryFree = new Sensor("GPU Memory Free", 1, SensorType.SmallData, this, settings);
|
||||
_memoryUsed = new Sensor("GPU Memory Used", 2, SensorType.SmallData, this, settings);
|
||||
_memoryAvail = new Sensor("GPU Memory Total", 3, SensorType.SmallData, this, settings);
|
||||
|
||||
_control = new Sensor("GPU Fan", 0, SensorType.Control, this, settings);
|
||||
|
||||
NvApi.NvGPUCoolerSettings coolerSettings = GetCoolerSettings();
|
||||
if (coolerSettings.Count > 0)
|
||||
try
|
||||
{
|
||||
_fanControl = new Control(_control, settings, coolerSettings.Cooler[0].DefaultMin, coolerSettings.Cooler[0].DefaultMax);
|
||||
_fanControl.ControlModeChanged += ControlModeChanged;
|
||||
_fanControl.SoftwareControlValueChanged += SoftwareControlValueChanged;
|
||||
ControlModeChanged(_fanControl);
|
||||
_control.Control = _fanControl;
|
||||
GPUCooler[] coolers = physicalGpu.CoolerInformation.Coolers.ToArray();
|
||||
if (coolers.Length > 0)
|
||||
{
|
||||
_controls = new Sensor[coolers.Length];
|
||||
_fanControls = new Control[coolers.Length];
|
||||
_fans = new Sensor[coolers.Length];
|
||||
|
||||
for (int i = 0; i < coolers.Length; i++)
|
||||
{
|
||||
GPUCooler cooler = coolers[i];
|
||||
string name = "GPU Fan" + (coolers.Length > 1 ? " " + (cooler.CoolerId) : string.Empty);
|
||||
|
||||
_fans[i] = new Sensor(name, i, SensorType.Fan, this, settings);
|
||||
ActivateSensor(_fans[i]);
|
||||
|
||||
_controls[i] = new Sensor(name, i, SensorType.Control, this, settings);
|
||||
ActivateSensor(_controls[i]);
|
||||
|
||||
_fanControls[i] = new Control(_controls[i], settings, cooler.DefaultMinimumLevel, cooler.DefaultMaximumLevel);
|
||||
_fanControls[i].ControlModeChanged += ControlModeChanged;
|
||||
_fanControls[i].SoftwareControlValueChanged += SoftwareControlValueChanged;
|
||||
_controls[i].Control = _fanControls[i];
|
||||
|
||||
ControlModeChanged(_fanControls[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
try
|
||||
{
|
||||
GPUPowerTopologyStatus[] powerTopologies = physicalGpu.PowerTopologyInformation.PowerTopologyEntries.ToArray();
|
||||
if (powerTopologies.Length > 0)
|
||||
{
|
||||
_powers = new Sensor[powerTopologies.Length];
|
||||
|
||||
for (int i = 0; i < powerTopologies.Length; i++)
|
||||
{
|
||||
GPUPowerTopologyStatus powerTopology = powerTopologies[i];
|
||||
|
||||
string name = powerTopology.Domain switch
|
||||
{
|
||||
PowerTopologyDomain.GPU => "GPU Power",
|
||||
PowerTopologyDomain.Board => "GPU Board Power",
|
||||
_ => null
|
||||
};
|
||||
|
||||
_powers[i] = new Sensor(name, i + (_loads?.Length ?? 0), SensorType.Load, this, settings);
|
||||
ActivateSensor(_powers[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
if (NvidiaML.IsAvailable || NvidiaML.Initialize())
|
||||
{
|
||||
if (hasPciBusId)
|
||||
if (busId != -1)
|
||||
_nvmlDevice = NvidiaML.NvmlDeviceGetHandleByPciBusId($" 0000:{busId:X2}:00.0") ?? NvidiaML.NvmlDeviceGetHandleByIndex(_adapterIndex);
|
||||
else
|
||||
_nvmlDevice = NvidiaML.NvmlDeviceGetHandleByIndex(_adapterIndex);
|
||||
@@ -203,10 +284,13 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
if (isMatch && D3DDisplayDevice.GetDeviceInfoByIdentifier(deviceIdentifier, out D3DDisplayDevice.D3DDeviceInfo deviceInfo))
|
||||
{
|
||||
int nodeSensorIndex = (_loads?.Length ?? 0) + (_powers?.Length ?? 0);
|
||||
int memorySensorIndex = 3; // There are three normal GPU memory sensors.
|
||||
|
||||
_windowsDeviceName = deviceIdentifier;
|
||||
|
||||
_gpuDedicatedMemoryUsage = new Sensor("D3D Dedicated Memory Used", _memorySensorIndex++, SensorType.SmallData, this, settings);
|
||||
_gpuSharedMemoryUsage = new Sensor("D3D Shared Memory Used", _memorySensorIndex++, SensorType.SmallData, this, settings);
|
||||
_gpuDedicatedMemoryUsage = new Sensor("D3D Dedicated Memory Used", memorySensorIndex++, SensorType.SmallData, this, settings);
|
||||
_gpuSharedMemoryUsage = new Sensor("D3D Shared Memory Used", memorySensorIndex, SensorType.SmallData, this, settings);
|
||||
|
||||
_gpuNodeUsage = new Sensor[deviceInfo.Nodes.Length];
|
||||
_gpuNodeUsagePrevValue = new long[deviceInfo.Nodes.Length];
|
||||
@@ -214,7 +298,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
foreach (D3DDisplayDevice.D3DDeviceNodeInfo node in deviceInfo.Nodes)
|
||||
{
|
||||
_gpuNodeUsage[node.Id] = new Sensor(node.Name, _nodeSensorIndex++, SensorType.Load, this, settings);
|
||||
_gpuNodeUsage[node.Id] = new Sensor(node.Name, nodeSensorIndex++, SensorType.Load, this, settings);
|
||||
_gpuNodeUsagePrevValue[node.Id] = node.RunningTime;
|
||||
_gpuNodeUsagePrevTick[node.Id] = node.QueryTime;
|
||||
}
|
||||
@@ -227,6 +311,10 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
}
|
||||
}
|
||||
|
||||
_memoryFree = new Sensor("GPU Memory Free", 0, SensorType.SmallData, this, settings);
|
||||
_memoryUsed = new Sensor("GPU Memory Used", 1, SensorType.SmallData, this, settings);
|
||||
_memoryTotal = new Sensor("GPU Memory Total", 2, SensorType.SmallData, this, settings);
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
@@ -235,67 +323,24 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
get { return HardwareType.GpuNvidia; }
|
||||
}
|
||||
|
||||
private static string GetName(NvApi.NvPhysicalGpuHandle handle)
|
||||
private static string GetName(PhysicalGPU physicalGpu)
|
||||
{
|
||||
if (NvApi.NvAPI_GPU_GetFullName(handle, out string gpuName) == NvApi.NvStatus.OK)
|
||||
{
|
||||
gpuName = gpuName.Trim();
|
||||
if (gpuName.StartsWith("NVIDIA", StringComparison.OrdinalIgnoreCase))
|
||||
return gpuName;
|
||||
string gpuName = null;
|
||||
|
||||
return "NVIDIA " + gpuName.Trim();
|
||||
try
|
||||
{
|
||||
gpuName = physicalGpu.FullName?.Trim();
|
||||
}
|
||||
catch (NVIDIAApiException)
|
||||
{ }
|
||||
|
||||
return "NVIDIA";
|
||||
}
|
||||
gpuName ??= "Unknown";
|
||||
|
||||
private NvApi.NvGPUThermalSettings GetThermalSettings()
|
||||
{
|
||||
NvApi.NvGPUThermalSettings settings = new()
|
||||
{
|
||||
Version = NvApi.GPU_THERMAL_SETTINGS_VER, Count = NvApi.MAX_THERMAL_SENSORS_PER_GPU, Sensor = new NvApi.NvSensor[NvApi.MAX_THERMAL_SENSORS_PER_GPU]
|
||||
};
|
||||
if (gpuName.StartsWith("NVIDIA", StringComparison.OrdinalIgnoreCase))
|
||||
return gpuName;
|
||||
|
||||
if (!(NvApi.NvAPI_GPU_GetThermalSettings != null && NvApi.NvAPI_GPU_GetThermalSettings(_handle, (int)NvApi.NvThermalTarget.ALL, ref settings) == NvApi.NvStatus.OK))
|
||||
{
|
||||
settings.Count = 0;
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
private NvApi.NvFanCoolersStatus GetFanCoolersStatus()
|
||||
{
|
||||
var coolers = new NvApi.NvFanCoolersStatus { Version = NvApi.GPU_FAN_COOLERS_STATUS_VER, Items = new NvApi.NvFanCoolersStatusItem[NvApi.MAX_FAN_COOLERS_STATUS_ITEMS] };
|
||||
|
||||
if (!(NvApi.NvAPI_GPU_ClientFanCoolersGetStatus != null && NvApi.NvAPI_GPU_ClientFanCoolersGetStatus(_handle, ref coolers) == NvApi.NvStatus.OK))
|
||||
{
|
||||
coolers.Count = 0;
|
||||
}
|
||||
|
||||
return coolers;
|
||||
}
|
||||
|
||||
private NvApi.NvGPUCoolerSettings GetCoolerSettings()
|
||||
{
|
||||
NvApi.NvGPUCoolerSettings settings = new() { Version = NvApi.GPU_COOLER_SETTINGS_VER, Cooler = new NvApi.NvCooler[NvApi.MAX_COOLER_PER_GPU] };
|
||||
if (!(NvApi.NvAPI_GPU_GetCoolerSettings != null && NvApi.NvAPI_GPU_GetCoolerSettings(_handle, 0, ref settings) == NvApi.NvStatus.OK))
|
||||
{
|
||||
settings.Count = 0;
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
private uint[] GetClocks()
|
||||
{
|
||||
NvApi.NvClocks allClocks = new() { Version = NvApi.GPU_CLOCKS_VER, Clock = new uint[NvApi.MAX_CLOCKS_PER_GPU] };
|
||||
if (NvApi.NvAPI_GPU_GetAllClocks != null && NvApi.NvAPI_GPU_GetAllClocks(_handle, ref allClocks) == NvApi.NvStatus.OK)
|
||||
{
|
||||
return allClocks.Clock;
|
||||
}
|
||||
|
||||
return null;
|
||||
return "NVIDIA " + gpuName.Trim();
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
@@ -319,111 +364,100 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
}
|
||||
}
|
||||
|
||||
NvApi.NvGPUThermalSettings settings = GetThermalSettings();
|
||||
// settings.Count is 0 when no valid data available, this happens when you try to read out this value with a high polling interval.
|
||||
if (settings.Count > 0)
|
||||
try
|
||||
{
|
||||
foreach (Sensor sensor in _temperatures)
|
||||
sensor.Value = settings.Sensor[sensor.Index].CurrentTemp;
|
||||
}
|
||||
|
||||
bool readTach = false;
|
||||
if (_fan != null)
|
||||
{
|
||||
if (NvApi.NvAPI_GPU_GetTachReading(_handle, out int value) == NvApi.NvStatus.OK)
|
||||
if (_temperatures is { Length: > 0 })
|
||||
{
|
||||
_fan.Value = value;
|
||||
ActivateSensor(_fan);
|
||||
|
||||
readTach = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint[] values = GetClocks();
|
||||
if (values != null)
|
||||
{
|
||||
_clocks[1].Value = 0.001f * values[8];
|
||||
if (values[30] != 0)
|
||||
{
|
||||
_clocks[0].Value = 0.0005f * values[30];
|
||||
_clocks[2].Value = 0.001f * values[30];
|
||||
}
|
||||
else
|
||||
{
|
||||
_clocks[0].Value = 0.001f * values[0];
|
||||
_clocks[2].Value = 0.001f * values[14];
|
||||
}
|
||||
}
|
||||
|
||||
NvApi.NvPStates states = new() { Version = NvApi.GPU_PSTATES_VER, PStates = new NvApi.NvPState[NvApi.MAX_PSTATES_PER_GPU] };
|
||||
if (NvApi.NvAPI_GPU_GetPStates != null && NvApi.NvAPI_GPU_GetPStates(_handle, ref states) == NvApi.NvStatus.OK)
|
||||
{
|
||||
for (int i = 0; i < _loads.Length; i++)
|
||||
{
|
||||
if (states.PStates[i].Present)
|
||||
GPUThermalSensor[] thermalSensors = _physicalGpu.ThermalInformation.ThermalSensors.ToArray();
|
||||
for (int i = 0; i < thermalSensors.Length; i++)
|
||||
{
|
||||
_loads[i].Value = states.PStates[i].Percentage;
|
||||
ActivateSensor(_loads[i]);
|
||||
GPUThermalSensor sensor = thermalSensors[i];
|
||||
_temperatures[i].Value = sensor.CurrentTemperature;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
try
|
||||
{
|
||||
NvApi.NvUsages usages = new() { Version = NvApi.GPU_USAGES_VER, Usage = new uint[NvApi.MAX_USAGES_PER_GPU] };
|
||||
if (NvApi.NvAPI_GPU_GetUsages != null && NvApi.NvAPI_GPU_GetUsages(_handle, ref usages) == NvApi.NvStatus.OK)
|
||||
if (_clocks is { Length: > 0 })
|
||||
{
|
||||
_loads[0].Value = usages.Usage[2];
|
||||
_loads[1].Value = usages.Usage[6];
|
||||
_loads[2].Value = usages.Usage[10];
|
||||
for (int i = 0; i < 3; i++)
|
||||
ActivateSensor(_loads[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool readCoolerSettings = false;
|
||||
NvApi.NvGPUCoolerSettings coolerSettings = GetCoolerSettings();
|
||||
if (coolerSettings.Count > 0)
|
||||
{
|
||||
_control.Value = coolerSettings.Cooler[0].CurrentLevel;
|
||||
ActivateSensor(_control);
|
||||
|
||||
readCoolerSettings = true;
|
||||
}
|
||||
|
||||
if (!readTach || !readCoolerSettings)
|
||||
{
|
||||
NvApi.NvFanCoolersStatus coolersStatus = GetFanCoolersStatus();
|
||||
if (coolersStatus.Count > 0)
|
||||
{
|
||||
if (!readCoolerSettings)
|
||||
KeyValuePair<PublicClockDomain, ClockDomainInfo>[] clocks = _physicalGpu.CurrentClockFrequencies.Clocks.OrderBy(x => x.Key).ToArray();
|
||||
for (int i = 0; i < clocks.Length; i++)
|
||||
{
|
||||
_control.Value = coolersStatus.Items[0].CurrentLevel;
|
||||
ActivateSensor(_control);
|
||||
}
|
||||
|
||||
if (!readTach && _fan != null)
|
||||
{
|
||||
_fan.Value = coolersStatus.Items[0].CurrentRpm;
|
||||
ActivateSensor(_fan);
|
||||
KeyValuePair<PublicClockDomain, ClockDomainInfo> clock = clocks[i];
|
||||
_clocks[i].Value = clock.Value.Frequency / 1000f;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
NvApi.NvMemoryInfo memoryInfo = new() { Version = NvApi.GPU_MEMORY_INFO_VER, Values = new uint[NvApi.MAX_MEMORY_VALUES_PER_GPU] };
|
||||
if (NvApi.NvAPI_GPU_GetMemoryInfo != null && _displayHandle.HasValue && NvApi.NvAPI_GPU_GetMemoryInfo(_displayHandle.Value, ref memoryInfo) == NvApi.NvStatus.OK)
|
||||
GPUMemoryInformation memoryInformation = _physicalGpu.MemoryInformation;
|
||||
|
||||
try
|
||||
{
|
||||
uint totalMemory = memoryInfo.Values[0];
|
||||
uint freeMemory = memoryInfo.Values[4];
|
||||
float usedMemory = Math.Max(totalMemory - freeMemory, 0);
|
||||
_memoryFree.Value = (float)freeMemory / 1024;
|
||||
_memoryAvail.Value = (float)totalMemory / 1024;
|
||||
_memoryUsed.Value = usedMemory / 1024;
|
||||
_memoryLoad.Value = 100f * usedMemory / totalMemory;
|
||||
ActivateSensor(_memoryAvail);
|
||||
GPUUsageDomainStatus[] usages = _physicalGpu.UsageInformation.UtilizationDomainsStatus.ToArray();
|
||||
for (int i = 0; i < usages.Length; i++)
|
||||
_loads[i].Value = usages[i].Percentage;
|
||||
|
||||
uint current = memoryInformation.CurrentAvailableDedicatedVideoMemoryInkB;
|
||||
uint total = memoryInformation.DedicatedVideoMemoryInkB;
|
||||
|
||||
_loads[_loads.Length - 1].Value = 100f * (total - current) / total;
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
try
|
||||
{
|
||||
GPUCooler[] coolers = _physicalGpu.CoolerInformation.Coolers.ToArray();
|
||||
if (coolers.Length > 0)
|
||||
{
|
||||
for (int i = 0; i < coolers.Length; i++)
|
||||
{
|
||||
GPUCooler cooler = coolers[i];
|
||||
|
||||
_fans[i].Value = cooler.CurrentFanSpeedInRPM;
|
||||
_controls[i].Value = cooler.CurrentLevel;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
try
|
||||
{
|
||||
GPUPowerTopologyStatus[] powerTopologies = _physicalGpu.PowerTopologyInformation.PowerTopologyEntries.ToArray();
|
||||
if (powerTopologies.Length > 0)
|
||||
{
|
||||
for (int i = 0; i < powerTopologies.Length; i++)
|
||||
{
|
||||
GPUPowerTopologyStatus powerTopology = powerTopologies[i];
|
||||
_powers[i].Value = powerTopology.PowerUsageInPercent;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
try
|
||||
{
|
||||
uint current = memoryInformation.CurrentAvailableDedicatedVideoMemoryInkB;
|
||||
uint total = memoryInformation.DedicatedVideoMemoryInkB;
|
||||
|
||||
_memoryTotal.Value = total / 1024;
|
||||
ActivateSensor(_memoryTotal);
|
||||
|
||||
_memoryUsed.Value = current / 1024;
|
||||
ActivateSensor(_memoryUsed);
|
||||
|
||||
_memoryFree.Value = (total - current) / 1024;
|
||||
ActivateSensor(_memoryFree);
|
||||
ActivateSensor(_memoryLoad);
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
if (NvidiaML.IsAvailable && _nvmlDevice.HasValue)
|
||||
{
|
||||
@@ -460,271 +494,139 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
r.AppendFormat("Name: {0}{1}", _name, Environment.NewLine);
|
||||
r.AppendFormat("Index: {0}{1}", _adapterIndex, Environment.NewLine);
|
||||
|
||||
if (_displayHandle.HasValue && NvApi.NvAPI_GetDisplayDriverVersion != null)
|
||||
try
|
||||
{
|
||||
NvApi.NvDisplayDriverVersion driverVersion = new() { Version = NvApi.DISPLAY_DRIVER_VERSION_VER };
|
||||
if (NvApi.NvAPI_GetDisplayDriverVersion(_displayHandle.Value, ref driverVersion) == NvApi.NvStatus.OK)
|
||||
{
|
||||
r.Append("Driver Version: ");
|
||||
r.Append(driverVersion.DriverVersion / 100);
|
||||
r.Append(".");
|
||||
r.Append((driverVersion.DriverVersion % 100).ToString("00", CultureInfo.InvariantCulture));
|
||||
r.AppendLine();
|
||||
r.Append("Driver Branch: ");
|
||||
r.AppendLine(driverVersion.BuildBranch);
|
||||
}
|
||||
PCIIdentifiers pciIdentifiers = _physicalGpu.BusInformation.PCIIdentifiers;
|
||||
r.Append("DeviceID: 0x");
|
||||
r.AppendLine(pciIdentifiers.DeviceId.ToString("X", CultureInfo.InvariantCulture));
|
||||
r.Append("SubSystemID: 0x");
|
||||
r.AppendLine(pciIdentifiers.SubSystemId.ToString("X", CultureInfo.InvariantCulture));
|
||||
r.Append("RevisionID: 0x");
|
||||
r.AppendLine(pciIdentifiers.RevisionId.ToString("X", CultureInfo.InvariantCulture));
|
||||
r.Append("ExtDeviceID: 0x");
|
||||
r.AppendLine(pciIdentifiers.ExternalDeviceId.ToString("X", CultureInfo.InvariantCulture));
|
||||
r.AppendLine();
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
r.AppendLine();
|
||||
|
||||
if (NvApi.NvAPI_GPU_GetPCIIdentifiers != null)
|
||||
try
|
||||
{
|
||||
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetPCIIdentifiers(_handle, out uint deviceId, out uint subSystemId, out uint revisionId, out uint extDeviceId);
|
||||
if (status == NvApi.NvStatus.OK)
|
||||
{
|
||||
r.Append("DeviceID: 0x");
|
||||
r.AppendLine(deviceId.ToString("X", CultureInfo.InvariantCulture));
|
||||
r.Append("SubSystemID: 0x");
|
||||
r.AppendLine(subSystemId.ToString("X", CultureInfo.InvariantCulture));
|
||||
r.Append("RevisionID: 0x");
|
||||
r.AppendLine(revisionId.ToString("X", CultureInfo.InvariantCulture));
|
||||
r.Append("ExtDeviceID: 0x");
|
||||
r.AppendLine(extDeviceId.ToString("X", CultureInfo.InvariantCulture));
|
||||
r.AppendLine();
|
||||
}
|
||||
}
|
||||
GPUThermalSensor[] thermalSensors = _physicalGpu.ThermalInformation.ThermalSensors.ToArray();
|
||||
|
||||
if (NvApi.NvAPI_GPU_GetThermalSettings != null)
|
||||
{
|
||||
NvApi.NvGPUThermalSettings settings = new()
|
||||
{
|
||||
Version = NvApi.GPU_THERMAL_SETTINGS_VER, Count = NvApi.MAX_THERMAL_SENSORS_PER_GPU, Sensor = new NvApi.NvSensor[NvApi.MAX_THERMAL_SENSORS_PER_GPU]
|
||||
};
|
||||
|
||||
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetThermalSettings(_handle, (int)NvApi.NvThermalTarget.ALL, ref settings);
|
||||
r.AppendLine("Thermal Settings");
|
||||
r.AppendLine();
|
||||
if (status == NvApi.NvStatus.OK)
|
||||
|
||||
for (int i = 0; i < thermalSensors.Length; i++)
|
||||
{
|
||||
for (int i = 0; i < settings.Count; i++)
|
||||
{
|
||||
r.AppendFormat(" Sensor[{0}].Controller: {1}{2}", i, settings.Sensor[i].Controller, Environment.NewLine);
|
||||
r.AppendFormat(" Sensor[{0}].DefaultMinTemp: {1}{2}", i, settings.Sensor[i].DefaultMinTemp, Environment.NewLine);
|
||||
r.AppendFormat(" Sensor[{0}].DefaultMaxTemp: {1}{2}", i, settings.Sensor[i].DefaultMaxTemp, Environment.NewLine);
|
||||
r.AppendFormat(" Sensor[{0}].CurrentTemp: {1}{2}", i, settings.Sensor[i].CurrentTemp, Environment.NewLine);
|
||||
r.AppendFormat(" Sensor[{0}].Target: {1}{2}", i, settings.Sensor[i].Target, Environment.NewLine);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
r.Append(" Status: ");
|
||||
r.AppendLine(status.ToString());
|
||||
r.AppendFormat(" Sensor[{0}].Target: {1}{2}", i, thermalSensors[i].Target, Environment.NewLine);
|
||||
r.AppendFormat(" Sensor[{0}].SensorId: {1}{2}", i, thermalSensors[i].SensorId, Environment.NewLine);
|
||||
r.AppendFormat(" Sensor[{0}].DefaultMinimumTemperature: {1}{2}", i, thermalSensors[i].DefaultMinimumTemperature, Environment.NewLine);
|
||||
r.AppendFormat(" Sensor[{0}].DefaultMaximumTemperature: {1}{2}", i, thermalSensors[i].DefaultMaximumTemperature, Environment.NewLine);
|
||||
r.AppendFormat(" Sensor[{0}].CurrentTemperature: {1}{2}", i, thermalSensors[i].CurrentTemperature, Environment.NewLine);
|
||||
}
|
||||
|
||||
r.AppendLine();
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
if (NvApi.NvAPI_GPU_GetAllClocks != null)
|
||||
try
|
||||
{
|
||||
NvApi.NvClocks allClocks = new() { Version = NvApi.GPU_CLOCKS_VER, Clock = new uint[NvApi.MAX_CLOCKS_PER_GPU] };
|
||||
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetAllClocks(_handle, ref allClocks);
|
||||
KeyValuePair<PublicClockDomain, ClockDomainInfo>[] clocks = _physicalGpu.CurrentClockFrequencies.Clocks.OrderBy(x => x.Key).ToArray();
|
||||
|
||||
r.AppendLine("Clocks");
|
||||
r.AppendLine();
|
||||
if (status == NvApi.NvStatus.OK)
|
||||
|
||||
for (int i = 0; i < clocks.Length; i++)
|
||||
{
|
||||
for (int i = 0; i < allClocks.Clock.Length; i++)
|
||||
if (allClocks.Clock[i] > 0)
|
||||
{
|
||||
r.AppendFormat(" Clock[{0}]: {1}{2}", i, allClocks.Clock[i], Environment.NewLine);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
r.Append(" Status: ");
|
||||
r.AppendLine(status.ToString());
|
||||
KeyValuePair<PublicClockDomain, ClockDomainInfo> clock = clocks[i];
|
||||
r.AppendFormat(" Clock[{0}]: {1}{2}", i, clock, Environment.NewLine);
|
||||
}
|
||||
|
||||
r.AppendLine();
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
if (NvApi.NvAPI_GPU_GetTachReading != null)
|
||||
try
|
||||
{
|
||||
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetTachReading(_handle, out int tachValue);
|
||||
GPUCooler[] coolers = _physicalGpu.CoolerInformation.Coolers.ToArray();
|
||||
|
||||
r.AppendLine("Tachometer");
|
||||
r.AppendLine("Coolers");
|
||||
r.AppendLine();
|
||||
if (status == NvApi.NvStatus.OK)
|
||||
{
|
||||
r.AppendFormat(" Value: {0}{1}", tachValue, Environment.NewLine);
|
||||
}
|
||||
else
|
||||
{
|
||||
r.Append(" Status: ");
|
||||
r.AppendLine(status.ToString());
|
||||
}
|
||||
|
||||
r.AppendLine();
|
||||
}
|
||||
|
||||
if (NvApi.NvAPI_GPU_GetPStates != null)
|
||||
{
|
||||
NvApi.NvPStates states = new() { Version = NvApi.GPU_PSTATES_VER, PStates = new NvApi.NvPState[NvApi.MAX_PSTATES_PER_GPU] };
|
||||
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetPStates(_handle, ref states);
|
||||
|
||||
r.AppendLine("P-States");
|
||||
r.AppendLine();
|
||||
if (status == NvApi.NvStatus.OK)
|
||||
if (coolers.Length > 0)
|
||||
{
|
||||
for (int i = 0; i < states.PStates.Length; i++)
|
||||
for (int i = 0; i < coolers.Length; i++)
|
||||
{
|
||||
if (states.PStates[i].Present)
|
||||
r.AppendFormat(" Percentage[{0}]: {1}{2}", i, states.PStates[i].Percentage, Environment.NewLine);
|
||||
GPUCooler cooler = coolers[i];
|
||||
|
||||
r.AppendFormat(" Cooler[{0}].CoolerId: {1}{2}", i, cooler.CoolerId, Environment.NewLine);
|
||||
r.AppendFormat(" Cooler[{0}].CoolerType: {1}{2}", i, cooler.CoolerType, Environment.NewLine);
|
||||
r.AppendFormat(" Cooler[{0}].ControlMode: {1}{2}", i, cooler.ControlMode, Environment.NewLine);
|
||||
r.AppendFormat(" Cooler[{0}].CurrentPolicy: {1}{2}", i, cooler.CurrentPolicy, Environment.NewLine);
|
||||
r.AppendFormat(" Cooler[{0}].CurrentLevel: {1}{2}", i, cooler.CurrentLevel, Environment.NewLine);
|
||||
r.AppendFormat(" Cooler[{0}].CurrentFanSpeedInRPM: {1}{2}", i, cooler.CurrentFanSpeedInRPM, Environment.NewLine);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
r.Append(" Status: ");
|
||||
r.AppendLine(status.ToString());
|
||||
}
|
||||
|
||||
r.AppendLine();
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
if (NvApi.NvAPI_GPU_GetUsages != null)
|
||||
try
|
||||
{
|
||||
NvApi.NvUsages usages = new() { Version = NvApi.GPU_USAGES_VER, Usage = new uint[NvApi.MAX_USAGES_PER_GPU] };
|
||||
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetUsages(_handle, ref usages);
|
||||
GPUUsageDomainStatus[] usages = _physicalGpu.UsageInformation.UtilizationDomainsStatus.ToArray();
|
||||
|
||||
r.AppendLine("Usages");
|
||||
r.AppendLine();
|
||||
if (status == NvApi.NvStatus.OK)
|
||||
|
||||
for (int i = 0; i < usages.Length; i++)
|
||||
{
|
||||
for (int i = 0; i < usages.Usage.Length; i++)
|
||||
{
|
||||
if (usages.Usage[i] > 0)
|
||||
r.AppendFormat(" Usage[{0}]: {1}{2}", i, usages.Usage[i], Environment.NewLine);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
r.Append(" Status: ");
|
||||
r.AppendLine(status.ToString());
|
||||
GPUUsageDomainStatus usage = usages[i];
|
||||
|
||||
r.AppendFormat(" Usage[{0}].Domain: {1}{2}", i, usage.Domain, Environment.NewLine);
|
||||
r.AppendFormat(" Usage[{0}].Percentage: {1}{2}", i, usage.Percentage, Environment.NewLine);
|
||||
}
|
||||
|
||||
r.AppendLine();
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
if (NvApi.NvAPI_GPU_GetCoolerSettings != null)
|
||||
try
|
||||
{
|
||||
NvApi.NvGPUCoolerSettings settings = new() { Version = NvApi.GPU_COOLER_SETTINGS_VER, Cooler = new NvApi.NvCooler[NvApi.MAX_COOLER_PER_GPU] };
|
||||
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetCoolerSettings(_handle, 0, ref settings);
|
||||
r.AppendLine("Cooler Settings");
|
||||
r.AppendLine();
|
||||
if (status == NvApi.NvStatus.OK)
|
||||
{
|
||||
for (int i = 0; i < settings.Count; i++)
|
||||
{
|
||||
r.AppendFormat(" Cooler[{0}].Type: {1}{2}", i, settings.Cooler[i].Type, Environment.NewLine);
|
||||
r.AppendFormat(" Cooler[{0}].Controller: {1}{2}", i, settings.Cooler[i].Controller, Environment.NewLine);
|
||||
r.AppendFormat(" Cooler[{0}].DefaultMin: {1}{2}", i, settings.Cooler[i].DefaultMin, Environment.NewLine);
|
||||
r.AppendFormat(" Cooler[{0}].DefaultMax: {1}{2}", i, settings.Cooler[i].DefaultMax, Environment.NewLine);
|
||||
r.AppendFormat(" Cooler[{0}].CurrentMin: {1}{2}", i, settings.Cooler[i].CurrentMin, Environment.NewLine);
|
||||
r.AppendFormat(" Cooler[{0}].CurrentMax: {1}{2}", i, settings.Cooler[i].CurrentMax, Environment.NewLine);
|
||||
r.AppendFormat(" Cooler[{0}].CurrentLevel: {1}{2}", i, settings.Cooler[i].CurrentLevel, Environment.NewLine);
|
||||
r.AppendFormat(" Cooler[{0}].DefaultPolicy: {1}{2}", i, settings.Cooler[i].DefaultPolicy, Environment.NewLine);
|
||||
r.AppendFormat(" Cooler[{0}].CurrentPolicy: {1}{2}", i, settings.Cooler[i].CurrentPolicy, Environment.NewLine);
|
||||
r.AppendFormat(" Cooler[{0}].Target: {1}{2}", i, settings.Cooler[i].Target, Environment.NewLine);
|
||||
r.AppendFormat(" Cooler[{0}].ControlType: {1}{2}", i, settings.Cooler[i].ControlType, Environment.NewLine);
|
||||
r.AppendFormat(" Cooler[{0}].Active: {1}{2}", i, settings.Cooler[i].Active, Environment.NewLine);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
r.Append(" Status: ");
|
||||
r.AppendLine(status.ToString());
|
||||
}
|
||||
|
||||
r.AppendLine();
|
||||
}
|
||||
|
||||
if (NvApi.NvAPI_GPU_ClientFanCoolersGetStatus != null)
|
||||
{
|
||||
var coolers = new NvApi.NvFanCoolersStatus { Version = NvApi.GPU_FAN_COOLERS_STATUS_VER, Items = new NvApi.NvFanCoolersStatusItem[NvApi.MAX_FAN_COOLERS_STATUS_ITEMS] };
|
||||
|
||||
NvApi.NvStatus status = NvApi.NvAPI_GPU_ClientFanCoolersGetStatus(_handle, ref coolers);
|
||||
|
||||
r.AppendLine("Fan Coolers Status");
|
||||
r.AppendLine();
|
||||
if (status == NvApi.NvStatus.OK)
|
||||
{
|
||||
for (int i = 0; i < coolers.Count; i++)
|
||||
{
|
||||
r.AppendFormat(" Items[{0}].Type: {1}{2}",
|
||||
i,
|
||||
coolers.Items[i].Type,
|
||||
Environment.NewLine);
|
||||
|
||||
r.AppendFormat(" Items[{0}].CurrentRpm: {1}{2}",
|
||||
i,
|
||||
coolers.Items[i].CurrentRpm,
|
||||
Environment.NewLine);
|
||||
|
||||
r.AppendFormat(" Items[{0}].CurrentMinLevel: {1}{2}",
|
||||
i,
|
||||
coolers.Items[i].CurrentMinLevel,
|
||||
Environment.NewLine);
|
||||
|
||||
r.AppendFormat(" Items[{0}].CurrentMaxLevel: {1}{2}",
|
||||
i,
|
||||
coolers.Items[i].CurrentMaxLevel,
|
||||
Environment.NewLine);
|
||||
|
||||
r.AppendFormat(" Items[{0}].CurrentLevel: {1}{2}",
|
||||
i,
|
||||
coolers.Items[i].CurrentLevel,
|
||||
Environment.NewLine);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
r.Append(" Status: ");
|
||||
r.AppendLine(status.ToString());
|
||||
}
|
||||
|
||||
r.AppendLine();
|
||||
}
|
||||
|
||||
if (NvApi.NvAPI_GPU_GetMemoryInfo != null && _displayHandle.HasValue)
|
||||
{
|
||||
NvApi.NvMemoryInfo memoryInfo = new() { Version = NvApi.GPU_MEMORY_INFO_VER, Values = new uint[NvApi.MAX_MEMORY_VALUES_PER_GPU] };
|
||||
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetMemoryInfo(_displayHandle.Value, ref memoryInfo);
|
||||
GPUMemoryInformation memoryInformation = _physicalGpu.MemoryInformation;
|
||||
|
||||
r.AppendLine("Memory Info");
|
||||
r.AppendLine();
|
||||
if (status == NvApi.NvStatus.OK)
|
||||
{
|
||||
for (int i = 0; i < memoryInfo.Values.Length; i++)
|
||||
r.AppendFormat(" Value[{0}]: {1}{2}", i, memoryInfo.Values[i], Environment.NewLine);
|
||||
}
|
||||
else
|
||||
{
|
||||
r.Append(" Status: ");
|
||||
r.AppendLine(status.ToString());
|
||||
}
|
||||
|
||||
r.AppendFormat(" DedicatedVideoMemoryInkB: {0}{1}", memoryInformation.DedicatedVideoMemoryInkB, Environment.NewLine);
|
||||
r.AppendFormat(" CurrentAvailableDedicatedVideoMemoryInkB: {0}{1}", memoryInformation.CurrentAvailableDedicatedVideoMemoryInkB, Environment.NewLine);
|
||||
r.AppendFormat(" AvailableDedicatedVideoMemoryInkB: {0}{1}", memoryInformation.AvailableDedicatedVideoMemoryInkB, Environment.NewLine);
|
||||
r.AppendLine();
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or NVIDIANotSupportedException)
|
||||
{ }
|
||||
|
||||
return r.ToString();
|
||||
}
|
||||
|
||||
private void SoftwareControlValueChanged(IControl control)
|
||||
{
|
||||
NvApi.NvGPUCoolerLevels coolerLevels = new() { Version = NvApi.GPU_COOLER_LEVELS_VER, Levels = new NvApi.NvLevel[NvApi.MAX_COOLER_PER_GPU] };
|
||||
coolerLevels.Levels[0].Level = (int)control.SoftwareValue;
|
||||
coolerLevels.Levels[0].Policy = 1;
|
||||
NvApi.NvAPI_GPU_SetCoolerLevels(_handle, 0, ref coolerLevels);
|
||||
int coolerId = -1;
|
||||
int index = control.Sensor.Index;
|
||||
|
||||
GPUCooler[] coolers = _physicalGpu.CoolerInformation.Coolers.ToArray();
|
||||
if (coolers.Length > index)
|
||||
{
|
||||
GPUCooler cooler = coolers[index];
|
||||
coolerId = cooler.CoolerId;
|
||||
}
|
||||
|
||||
_physicalGpu.CoolerInformation.SetCoolerSettings(coolerId, CoolerPolicy.Manual, (int)control.SoftwareValue);
|
||||
}
|
||||
|
||||
private void ControlModeChanged(IControl control)
|
||||
@@ -732,33 +634,53 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
switch (control.ControlMode)
|
||||
{
|
||||
case ControlMode.Undefined:
|
||||
{
|
||||
return;
|
||||
}
|
||||
case ControlMode.Default:
|
||||
SetDefaultFanSpeed();
|
||||
{
|
||||
RestoreDefaultFanBehavior(control.Sensor.Index);
|
||||
break;
|
||||
}
|
||||
case ControlMode.Software:
|
||||
{
|
||||
SoftwareControlValueChanged(control);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetDefaultFanSpeed()
|
||||
private void RestoreDefaultFanBehavior(int index)
|
||||
{
|
||||
NvApi.NvGPUCoolerLevels coolerLevels = new() { Version = NvApi.GPU_COOLER_LEVELS_VER, Levels = new NvApi.NvLevel[NvApi.MAX_COOLER_PER_GPU] };
|
||||
coolerLevels.Levels[0].Policy = 0x20;
|
||||
NvApi.NvAPI_GPU_SetCoolerLevels(_handle, 0, ref coolerLevels);
|
||||
int coolerId = -1;
|
||||
|
||||
GPUCooler[] coolers = _physicalGpu.CoolerInformation.Coolers.ToArray();
|
||||
if (coolers.Length > index)
|
||||
{
|
||||
GPUCooler cooler = coolers[index];
|
||||
coolerId = cooler.CoolerId;
|
||||
}
|
||||
|
||||
if (coolerId != -1)
|
||||
_physicalGpu.CoolerInformation.RestoreCoolerSettingsToDefault(coolerId);
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
if (_fanControl != null)
|
||||
if (_fanControls != null)
|
||||
{
|
||||
_fanControl.ControlModeChanged -= ControlModeChanged;
|
||||
_fanControl.SoftwareControlValueChanged -= SoftwareControlValueChanged;
|
||||
if (_fanControl.ControlMode != ControlMode.Undefined)
|
||||
SetDefaultFanSpeed();
|
||||
for (int i = 0; i < _fanControls.Length; i++)
|
||||
{
|
||||
_fanControls[i].ControlModeChanged -= ControlModeChanged;
|
||||
_fanControls[i].SoftwareControlValueChanged -= SoftwareControlValueChanged;
|
||||
|
||||
if (_fanControls[i].ControlMode != ControlMode.Undefined)
|
||||
RestoreDefaultFanBehavior(i);
|
||||
}
|
||||
}
|
||||
|
||||
base.Close();
|
||||
|
||||
@@ -4,10 +4,14 @@
|
||||
// Partial Copyright (C) Michael Möller <mmoeller@openhardwaremonitor.org> and Contributors.
|
||||
// All Rights Reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using LibreHardwareMonitor.Interop;
|
||||
using NvAPIWrapper;
|
||||
using NvAPIWrapper.GPU;
|
||||
using NvAPIWrapper.Native.Exceptions;
|
||||
|
||||
namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
{
|
||||
@@ -15,72 +19,66 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
{
|
||||
private readonly List<Hardware> _hardware = new();
|
||||
private readonly StringBuilder _report = new();
|
||||
private readonly bool _initialized;
|
||||
|
||||
public NvidiaGroup(ISettings settings)
|
||||
{
|
||||
if (!NvApi.IsAvailable)
|
||||
return;
|
||||
|
||||
|
||||
_report.AppendLine("NvApi");
|
||||
_report.AppendLine();
|
||||
|
||||
if (NvApi.NvAPI_GetInterfaceVersionString(out string version) == NvApi.NvStatus.OK)
|
||||
try
|
||||
{
|
||||
NVIDIA.Initialize();
|
||||
_initialized = true;
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or DllNotFoundException)
|
||||
{
|
||||
// No NVIDIA devices.
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string interfaceVersion = NVIDIA.InterfaceVersionString;
|
||||
|
||||
_report.Append("Version: ");
|
||||
_report.AppendLine(version);
|
||||
_report.AppendLine(interfaceVersion);
|
||||
}
|
||||
catch (NVIDIAApiException)
|
||||
{ }
|
||||
|
||||
NvApi.NvPhysicalGpuHandle[] handles = new NvApi.NvPhysicalGpuHandle[NvApi.MAX_PHYSICAL_GPUS];
|
||||
if (NvApi.NvAPI_EnumPhysicalGPUs == null)
|
||||
try
|
||||
{
|
||||
_report.AppendLine("Error: NvAPI_EnumPhysicalGPUs not available");
|
||||
_report.AppendLine();
|
||||
return;
|
||||
string driverVersion = NVIDIA.DriverVersion.ToString();
|
||||
|
||||
_report.Append("Driver: ");
|
||||
_report.AppendLine(driverVersion);
|
||||
}
|
||||
catch (NVIDIAApiException)
|
||||
{ }
|
||||
|
||||
NvApi.NvStatus status = NvApi.NvAPI_EnumPhysicalGPUs(handles, out int count);
|
||||
if (status != NvApi.NvStatus.OK)
|
||||
try
|
||||
{
|
||||
_report.AppendLine("Status: " + status);
|
||||
_report.AppendLine();
|
||||
return;
|
||||
string driverBranch = NVIDIA.DriverBranchVersion;
|
||||
|
||||
_report.Append("Driver branch: ");
|
||||
_report.AppendLine(driverBranch);
|
||||
}
|
||||
catch (NVIDIAApiException)
|
||||
{ }
|
||||
|
||||
IDictionary<NvApi.NvPhysicalGpuHandle, NvApi.NvDisplayHandle> displayHandles = new Dictionary<NvApi.NvPhysicalGpuHandle, NvApi.NvDisplayHandle>();
|
||||
if (NvApi.NvAPI_EnumNvidiaDisplayHandle != null && NvApi.NvAPI_GetPhysicalGPUsFromDisplay != null)
|
||||
try
|
||||
{
|
||||
status = NvApi.NvStatus.OK;
|
||||
int i = 0;
|
||||
while (status == NvApi.NvStatus.OK)
|
||||
{
|
||||
NvApi.NvDisplayHandle displayHandle = new();
|
||||
status = NvApi.NvAPI_EnumNvidiaDisplayHandle(i, ref displayHandle);
|
||||
i++;
|
||||
|
||||
if (status == NvApi.NvStatus.OK)
|
||||
{
|
||||
NvApi.NvPhysicalGpuHandle[] handlesFromDisplay = new NvApi.NvPhysicalGpuHandle[NvApi.MAX_PHYSICAL_GPUS];
|
||||
if (NvApi.NvAPI_GetPhysicalGPUsFromDisplay(displayHandle, handlesFromDisplay, out uint countFromDisplay) == NvApi.NvStatus.OK)
|
||||
{
|
||||
for (int j = 0; j < countFromDisplay; j++)
|
||||
{
|
||||
if (!displayHandles.ContainsKey(handlesFromDisplay[j]))
|
||||
displayHandles.Add(handlesFromDisplay[j], displayHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PhysicalGPU[] physicalGpus = PhysicalGPU.GetPhysicalGPUs();
|
||||
|
||||
_report.Append("Number of GPUs: ");
|
||||
_report.AppendLine(count.ToString(CultureInfo.InvariantCulture));
|
||||
_report.Append("Number of GPUs: ");
|
||||
_report.AppendLine(physicalGpus.Length.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
displayHandles.TryGetValue(handles[i], out NvApi.NvDisplayHandle displayHandle);
|
||||
_hardware.Add(new NvidiaGpu(i, handles[i], displayHandle, settings));
|
||||
for (int i = 0; i < physicalGpus.Length; i++)
|
||||
_hardware.Add(new NvidiaGpu(i, physicalGpus[i], settings));
|
||||
}
|
||||
catch (NVIDIAApiException)
|
||||
{ }
|
||||
|
||||
_report.AppendLine();
|
||||
}
|
||||
@@ -94,10 +92,21 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (!_initialized)
|
||||
return;
|
||||
|
||||
|
||||
foreach (Hardware gpu in _hardware)
|
||||
gpu.Close();
|
||||
|
||||
NvidiaML.Close();
|
||||
|
||||
try
|
||||
{
|
||||
NVIDIA.Unload();
|
||||
}
|
||||
catch (Exception e) when (e is NVIDIAApiException or DllNotFoundException)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace LibreHardwareMonitor.Hardware
|
||||
|
||||
float MinSoftwareValue { get; }
|
||||
|
||||
ISensor Sensor { get; }
|
||||
|
||||
float SoftwareValue { get; }
|
||||
|
||||
void SetDefault();
|
||||
|
||||
@@ -1,440 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
// Copyright (C) LibreHardwareMonitor and Contributors.
|
||||
// All Rights Reserved.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace LibreHardwareMonitor.Interop
|
||||
{
|
||||
internal static class NvApi
|
||||
{
|
||||
public const int MAX_CLOCKS_PER_GPU = 0x120;
|
||||
public const int MAX_COOLER_PER_GPU = 20;
|
||||
public const int MAX_FAN_COOLERS_STATUS_ITEMS = 32;
|
||||
public const int MAX_MEMORY_VALUES_PER_GPU = 5;
|
||||
public const int MAX_PHYSICAL_GPUS = 64;
|
||||
public const int MAX_PSTATES_PER_GPU = 8;
|
||||
public const int MAX_THERMAL_SENSORS_PER_GPU = 3;
|
||||
public const int MAX_USAGES_PER_GPU = 33;
|
||||
public const int SHORT_STRING_MAX = 64;
|
||||
|
||||
public static readonly uint DISPLAY_DRIVER_VERSION_VER = (uint)Marshal.SizeOf(typeof(NvDisplayDriverVersion)) | 0x10000;
|
||||
public static readonly uint GPU_CLOCKS_VER = (uint)Marshal.SizeOf(typeof(NvClocks)) | 0x20000;
|
||||
public static readonly uint GPU_COOLER_LEVELS_VER = (uint)Marshal.SizeOf(typeof(NvGPUCoolerLevels)) | 0x10000;
|
||||
public static readonly uint GPU_COOLER_SETTINGS_VER = (uint)Marshal.SizeOf(typeof(NvGPUCoolerSettings)) | 0x20000;
|
||||
public static readonly uint GPU_MEMORY_INFO_VER = (uint)Marshal.SizeOf(typeof(NvMemoryInfo)) | 0x20000;
|
||||
public static readonly uint GPU_PSTATES_VER = (uint)Marshal.SizeOf(typeof(NvPStates)) | 0x10000;
|
||||
public static readonly uint GPU_THERMAL_SETTINGS_VER = (uint)Marshal.SizeOf(typeof(NvGPUThermalSettings)) | 0x10000;
|
||||
public static readonly uint GPU_USAGES_VER = (uint)Marshal.SizeOf(typeof(NvUsages)) | 0x10000;
|
||||
public static readonly uint GPU_FAN_COOLERS_STATUS_VER = (uint)Marshal.SizeOf(typeof(NvFanCoolersStatus)) | 0x10000;
|
||||
|
||||
public static readonly NvAPI_EnumNvidiaDisplayHandleDelegate NvAPI_EnumNvidiaDisplayHandle;
|
||||
public static readonly NvAPI_EnumPhysicalGPUsDelegate NvAPI_EnumPhysicalGPUs;
|
||||
public static readonly NvAPI_GetDisplayDriverVersionDelegate NvAPI_GetDisplayDriverVersion;
|
||||
public static readonly NvAPI_GetPhysicalGPUsFromDisplayDelegate NvAPI_GetPhysicalGPUsFromDisplay;
|
||||
public static readonly NvAPI_GPU_GetAllClocksDelegate NvAPI_GPU_GetAllClocks;
|
||||
public static readonly NvAPI_GPU_GetBusIdDelegate NvAPI_GPU_GetBusId;
|
||||
public static readonly NvAPI_GPU_GetCoolerSettingsDelegate NvAPI_GPU_GetCoolerSettings;
|
||||
public static readonly NvAPI_GPU_GetMemoryInfoDelegate NvAPI_GPU_GetMemoryInfo;
|
||||
public static readonly NvAPI_GPU_GetPCIIdentifiersDelegate NvAPI_GPU_GetPCIIdentifiers;
|
||||
public static readonly NvAPI_GPU_GetPStatesDelegate NvAPI_GPU_GetPStates;
|
||||
public static readonly NvAPI_GPU_GetTachReadingDelegate NvAPI_GPU_GetTachReading;
|
||||
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_ClientFanCoolersGetStatusDelegate NvAPI_GPU_ClientFanCoolersGetStatus;
|
||||
|
||||
private static readonly NvAPI_GetInterfaceVersionStringDelegate _nvAPI_GetInterfaceVersionString;
|
||||
private static readonly NvAPI_GPU_GetFullNameDelegate _nvAPI_GPU_GetFullName;
|
||||
|
||||
static NvApi()
|
||||
{
|
||||
NvAPI_InitializeDelegate nvApiInitialize;
|
||||
|
||||
try
|
||||
{
|
||||
GetDelegate(0x0150E828, out nvApiInitialize);
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
catch (EntryPointNotFoundException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
catch (ArgumentNullException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (nvApiInitialize() == NvStatus.OK)
|
||||
{
|
||||
GetDelegate(0xE3640A56, out NvAPI_GPU_GetThermalSettings);
|
||||
GetDelegate(0xCEEE8E9F, out _nvAPI_GPU_GetFullName);
|
||||
GetDelegate(0x9ABDD40D, out NvAPI_EnumNvidiaDisplayHandle);
|
||||
GetDelegate(0x34EF9506, out NvAPI_GetPhysicalGPUsFromDisplay);
|
||||
GetDelegate(0xE5AC921F, out NvAPI_EnumPhysicalGPUs);
|
||||
GetDelegate(0x5F608315, out NvAPI_GPU_GetTachReading);
|
||||
GetDelegate(0x1BD69F49, out NvAPI_GPU_GetAllClocks);
|
||||
GetDelegate(0x60DED2ED, out NvAPI_GPU_GetPStates);
|
||||
GetDelegate(0x189A1FDF, out NvAPI_GPU_GetUsages);
|
||||
GetDelegate(0xDA141340, out NvAPI_GPU_GetCoolerSettings);
|
||||
GetDelegate(0x891FA0AE, out NvAPI_GPU_SetCoolerLevels);
|
||||
GetDelegate(0x774AA982, out NvAPI_GPU_GetMemoryInfo);
|
||||
GetDelegate(0xF951A4D1, out NvAPI_GetDisplayDriverVersion);
|
||||
GetDelegate(0x01053FA5, out _nvAPI_GetInterfaceVersionString);
|
||||
GetDelegate(0x2DDFB66E, out NvAPI_GPU_GetPCIIdentifiers);
|
||||
GetDelegate(0x1BE0B8E5, out NvAPI_GPU_GetBusId);
|
||||
GetDelegate(0x35AED5E8, out NvAPI_GPU_ClientFanCoolersGetStatus);
|
||||
|
||||
IsAvailable = true;
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_EnumNvidiaDisplayHandleDelegate(int thisEnum, ref NvDisplayHandle displayHandle);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_EnumPhysicalGPUsDelegate([Out] NvPhysicalGpuHandle[] gpuHandles, out int gpuCount);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GetDisplayDriverVersionDelegate(NvDisplayHandle displayHandle, [In, Out] ref NvDisplayDriverVersion nvDisplayDriverVersion);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GetInterfaceVersionStringDelegate(StringBuilder version);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GetPhysicalGPUsFromDisplayDelegate(NvDisplayHandle displayHandle, [Out] NvPhysicalGpuHandle[] gpuHandles, out uint gpuCount);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GPU_GetAllClocksDelegate(NvPhysicalGpuHandle gpuHandle, ref NvClocks nvClocks);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GPU_GetBusIdDelegate(NvPhysicalGpuHandle gpuHandle, out uint busId);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GPU_GetCoolerSettingsDelegate(NvPhysicalGpuHandle gpuHandle, int coolerIndex, ref NvGPUCoolerSettings nvGPUCoolerSettings);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GPU_GetMemoryInfoDelegate(NvDisplayHandle displayHandle, ref NvMemoryInfo nvMemoryInfo);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GPU_GetPCIIdentifiersDelegate(NvPhysicalGpuHandle gpuHandle, out uint deviceId, out uint subSystemId, out uint revisionId, out uint extDeviceId);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GPU_GetPStatesDelegate(NvPhysicalGpuHandle gpuHandle, ref NvPStates nvPStates);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GPU_GetTachReadingDelegate(NvPhysicalGpuHandle gpuHandle, out int value);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GPU_GetThermalSettingsDelegate(NvPhysicalGpuHandle gpuHandle, int sensorIndex, ref NvGPUThermalSettings nvGPUThermalSettings);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GPU_GetUsagesDelegate(NvPhysicalGpuHandle gpuHandle, ref NvUsages nvUsages);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GPU_SetCoolerLevelsDelegate(NvPhysicalGpuHandle gpuHandle, int coolerIndex, ref NvGPUCoolerLevels NvGPUCoolerLevels);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GPU_ClientFanCoolersGetStatusDelegate(NvPhysicalGpuHandle gpuHandle, ref NvFanCoolersStatus fanCoolersStatus);
|
||||
|
||||
public static bool IsAvailable { get; }
|
||||
|
||||
[DllImport(@"nvapi.dll", EntryPoint = @"nvapi_QueryInterface", CallingConvention = CallingConvention.Cdecl, PreserveSig = true)]
|
||||
private static extern IntPtr NvAPI32_QueryInterface(uint interfaceId);
|
||||
|
||||
[DllImport(@"nvapi64.dll", EntryPoint = @"nvapi_QueryInterface", CallingConvention = CallingConvention.Cdecl, PreserveSig = true)]
|
||||
private static extern IntPtr NvAPI64_QueryInterface(uint interfaceId);
|
||||
|
||||
public static NvStatus NvAPI_GPU_GetFullName(NvPhysicalGpuHandle gpuHandle, out string name)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(SHORT_STRING_MAX);
|
||||
NvStatus status = _nvAPI_GPU_GetFullName?.Invoke(gpuHandle, builder) ?? NvStatus.FUNCTION_NOT_FOUND;
|
||||
|
||||
name = builder.ToString();
|
||||
return status;
|
||||
}
|
||||
|
||||
public static NvStatus NvAPI_GetInterfaceVersionString(out string version)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder(SHORT_STRING_MAX);
|
||||
NvStatus status = _nvAPI_GetInterfaceVersionString?.Invoke(builder) ?? NvStatus.FUNCTION_NOT_FOUND;
|
||||
|
||||
version = builder.ToString();
|
||||
return status;
|
||||
}
|
||||
|
||||
private static void GetDelegate<T>(uint id, out T newDelegate) where T : class
|
||||
{
|
||||
IntPtr ptr = IntPtr.Size == 4 ? NvAPI32_QueryInterface(id) : NvAPI64_QueryInterface(id);
|
||||
|
||||
if (ptr != IntPtr.Zero)
|
||||
newDelegate = Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T;
|
||||
else
|
||||
newDelegate = null;
|
||||
}
|
||||
|
||||
internal enum NvStatus
|
||||
{
|
||||
OK = 0,
|
||||
ERROR = -1,
|
||||
LIBRARY_NOT_FOUND = -2,
|
||||
NO_IMPLEMENTATION = -3,
|
||||
API_NOT_INTIALIZED = -4,
|
||||
INVALID_ARGUMENT = -5,
|
||||
NVIDIA_DEVICE_NOT_FOUND = -6,
|
||||
END_ENUMERATION = -7,
|
||||
INVALID_HANDLE = -8,
|
||||
INCOMPATIBLE_STRUCT_VERSION = -9,
|
||||
HANDLE_INVALIDATED = -10,
|
||||
OPENGL_CONTEXT_NOT_CURRENT = -11,
|
||||
NO_GL_EXPERT = -12,
|
||||
INSTRUMENTATION_DISABLED = -13,
|
||||
EXPECTED_LOGICAL_GPU_HANDLE = -100,
|
||||
EXPECTED_PHYSICAL_GPU_HANDLE = -101,
|
||||
EXPECTED_DISPLAY_HANDLE = -102,
|
||||
INVALID_COMBINATION = -103,
|
||||
NOT_SUPPORTED = -104,
|
||||
PORTID_NOT_FOUND = -105,
|
||||
EXPECTED_UNATTACHED_DISPLAY_HANDLE = -106,
|
||||
INVALID_PERF_LEVEL = -107,
|
||||
DEVICE_BUSY = -108,
|
||||
NV_PERSIST_FILE_NOT_FOUND = -109,
|
||||
PERSIST_DATA_NOT_FOUND = -110,
|
||||
EXPECTED_TV_DISPLAY = -111,
|
||||
EXPECTED_TV_DISPLAY_ON_DCONNECTOR = -112,
|
||||
NO_ACTIVE_SLI_TOPOLOGY = -113,
|
||||
SLI_RENDERING_MODE_NOTALLOWED = -114,
|
||||
EXPECTED_DIGITAL_FLAT_PANEL = -115,
|
||||
ARGUMENT_EXCEED_MAX_SIZE = -116,
|
||||
DEVICE_SWITCHING_NOT_ALLOWED = -117,
|
||||
TESTING_CLOCKS_NOT_SUPPORTED = -118,
|
||||
UNKNOWN_UNDERSCAN_CONFIG = -119,
|
||||
TIMEOUT_RECONFIGURING_GPU_TOPO = -120,
|
||||
DATA_NOT_FOUND = -121,
|
||||
EXPECTED_ANALOG_DISPLAY = -122,
|
||||
NO_VIDLINK = -123,
|
||||
REQUIRES_REBOOT = -124,
|
||||
INVALID_HYBRID_MODE = -125,
|
||||
MIXED_TARGET_TYPES = -126,
|
||||
SYSWOW64_NOT_SUPPORTED = -127,
|
||||
IMPLICIT_SET_GPU_TOPOLOGY_CHANGE_NOT_ALLOWED = -128,
|
||||
REQUEST_USER_TO_CLOSE_NON_MIGRATABLE_APPS = -129,
|
||||
OUT_OF_MEMORY = -130,
|
||||
WAS_STILL_DRAWING = -131,
|
||||
FILE_NOT_FOUND = -132,
|
||||
TOO_MANY_UNIQUE_STATE_OBJECTS = -133,
|
||||
INVALID_CALL = -134,
|
||||
D3D10_1_LIBRARY_NOT_FOUND = -135,
|
||||
FUNCTION_NOT_FOUND = -136
|
||||
}
|
||||
|
||||
internal enum NvThermalController
|
||||
{
|
||||
NONE = 0,
|
||||
GPU_INTERNAL,
|
||||
ADM1032,
|
||||
MAX6649,
|
||||
MAX1617,
|
||||
LM99,
|
||||
LM89,
|
||||
LM64,
|
||||
ADT7473,
|
||||
SBMAX6649,
|
||||
VBIOSEVT,
|
||||
OS,
|
||||
UNKNOWN = -1
|
||||
}
|
||||
|
||||
internal enum NvThermalTarget
|
||||
{
|
||||
NONE = 0,
|
||||
GPU = 1,
|
||||
MEMORY = 2,
|
||||
POWER_SUPPLY = 4,
|
||||
BOARD = 8,
|
||||
ALL = 15,
|
||||
UNKNOWN = -1
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal struct NvSensor
|
||||
{
|
||||
public NvThermalController Controller;
|
||||
public uint DefaultMinTemp;
|
||||
public uint DefaultMaxTemp;
|
||||
public uint CurrentTemp;
|
||||
public NvThermalTarget Target;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal struct NvGPUThermalSettings
|
||||
{
|
||||
public uint Version;
|
||||
public uint Count;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_THERMAL_SENSORS_PER_GPU)]
|
||||
public NvSensor[] Sensor;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct NvDisplayHandle
|
||||
{
|
||||
private readonly IntPtr ptr;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct NvPhysicalGpuHandle
|
||||
{
|
||||
private readonly IntPtr ptr;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal struct NvClocks
|
||||
{
|
||||
public uint Version;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_CLOCKS_PER_GPU)]
|
||||
public uint[] Clock;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal struct NvPState
|
||||
{
|
||||
public bool Present;
|
||||
public int Percentage;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal struct NvPStates
|
||||
{
|
||||
public uint Version;
|
||||
public uint Flags;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_PSTATES_PER_GPU)]
|
||||
public NvPState[] PStates;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal struct NvUsages
|
||||
{
|
||||
public uint Version;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_USAGES_PER_GPU)]
|
||||
public uint[] Usage;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal struct NvCooler
|
||||
{
|
||||
public int Type;
|
||||
public int Controller;
|
||||
public int DefaultMin;
|
||||
public int DefaultMax;
|
||||
public int CurrentMin;
|
||||
public int CurrentMax;
|
||||
public int CurrentLevel;
|
||||
public int DefaultPolicy;
|
||||
public int CurrentPolicy;
|
||||
public int Target;
|
||||
public int ControlType;
|
||||
public int Active;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal struct NvFanCoolersStatus
|
||||
{
|
||||
public uint Version;
|
||||
public uint Count;
|
||||
|
||||
public ulong Reserved1;
|
||||
public ulong Reserved2;
|
||||
public ulong Reserved3;
|
||||
public ulong Reserved4;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_FAN_COOLERS_STATUS_ITEMS)]
|
||||
internal NvFanCoolersStatusItem[] Items;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal struct NvFanCoolersStatusItem
|
||||
{
|
||||
public uint Type;
|
||||
public uint CurrentRpm;
|
||||
public uint CurrentMinLevel;
|
||||
public uint CurrentMaxLevel;
|
||||
public uint CurrentLevel;
|
||||
|
||||
public uint Reserved1;
|
||||
public uint Reserved2;
|
||||
public uint Reserved3;
|
||||
public uint Reserved4;
|
||||
public uint Reserved5;
|
||||
public uint Reserved6;
|
||||
public uint Reserved7;
|
||||
public uint Reserved8;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal struct NvGPUCoolerSettings
|
||||
{
|
||||
public uint Version;
|
||||
public uint Count;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_COOLER_PER_GPU)]
|
||||
public NvCooler[] Cooler;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal struct NvLevel
|
||||
{
|
||||
public int Level;
|
||||
public int Policy;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal struct NvGPUCoolerLevels
|
||||
{
|
||||
public uint Version;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_COOLER_PER_GPU)]
|
||||
public NvLevel[] Levels;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal struct NvMemoryInfo
|
||||
{
|
||||
public uint Version;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_MEMORY_VALUES_PER_GPU)]
|
||||
public uint[] Values;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8)]
|
||||
internal struct NvDisplayDriverVersion
|
||||
{
|
||||
public uint Version;
|
||||
public uint DriverVersion;
|
||||
public uint BldChangeListNum;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = SHORT_STRING_MAX)]
|
||||
public string BuildBranch;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = SHORT_STRING_MAX)]
|
||||
public string Adapter;
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate NvStatus NvAPI_InitializeDelegate();
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate NvStatus NvAPI_GPU_GetFullNameDelegate(NvPhysicalGpuHandle gpuHandle, StringBuilder name);
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="HidSharp" Version="2.1.0" />
|
||||
<PackageReference Include="NvAPIWrapper.Net" Version="0.8.1.101" />
|
||||
<PackageReference Include="System.Management" Version="4.7.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user