mirror of
https://github.com/openhardwaremonitor/openhardwaremonitor
synced 2025-08-22 01:47:36 +00:00
Added support for the NVML (NVIDIA Management Library). Added support for power and PCIE throughput sensors on NVIDIA GPUs.
This commit is contained in:
parent
0a8923a998
commit
8e9bea8b6c
@ -8,11 +8,9 @@
|
||||
|
||||
*/
|
||||
|
||||
using OpenHardwareMonitor.Hardware;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Collections.Generic;
|
||||
using OpenHardwareMonitor.Hardware;
|
||||
using OpenHardwareMonitor.Utilities;
|
||||
|
||||
namespace OpenHardwareMonitor.GUI {
|
||||
public class SensorNode : Node {
|
||||
@ -20,18 +18,26 @@ namespace OpenHardwareMonitor.GUI {
|
||||
private ISensor sensor;
|
||||
private PersistentSettings settings;
|
||||
private UnitManager unitManager;
|
||||
private string format;
|
||||
private string fixedFormat;
|
||||
private bool plot = false;
|
||||
private Color? penColor = null;
|
||||
|
||||
public string ValueToString(float? value) {
|
||||
if (value.HasValue) {
|
||||
if (sensor.SensorType == SensorType.Temperature &&
|
||||
unitManager.TemperatureUnit == TemperatureUnit.Fahrenheit) {
|
||||
return string.Format("{0:F1} °F", value * 1.8 + 32);
|
||||
} else {
|
||||
return string.Format(format, value);
|
||||
}
|
||||
switch (sensor.SensorType) {
|
||||
case SensorType.Temperature:
|
||||
if (unitManager.TemperatureUnit == TemperatureUnit.Fahrenheit)
|
||||
return string.Format("{0:F1} °F", value * 1.8 + 32);
|
||||
else
|
||||
return string.Format("{0:F1} °C", value);
|
||||
case SensorType.Throughput:
|
||||
if (value < 1)
|
||||
return string.Format("{0:F1} KB/s", value * 0x400);
|
||||
else
|
||||
return string.Format("{0:F1} MB/s", value);
|
||||
default:
|
||||
return string.Format(fixedFormat, value);
|
||||
}
|
||||
} else
|
||||
return "-";
|
||||
}
|
||||
@ -42,18 +48,18 @@ namespace OpenHardwareMonitor.GUI {
|
||||
this.settings = settings;
|
||||
this.unitManager = unitManager;
|
||||
switch (sensor.SensorType) {
|
||||
case SensorType.Voltage: format = "{0:F3} V"; break;
|
||||
case SensorType.Clock: format = "{0:F1} MHz"; break;
|
||||
case SensorType.Load: format = "{0:F1} %"; break;
|
||||
case SensorType.Temperature: format = "{0:F1} °C"; break;
|
||||
case SensorType.Fan: format = "{0:F0} RPM"; break;
|
||||
case SensorType.Flow: format = "{0:F0} L/h"; break;
|
||||
case SensorType.Control: format = "{0:F1} %"; break;
|
||||
case SensorType.Level: format = "{0:F1} %"; break;
|
||||
case SensorType.Power: format = "{0:F1} W"; break;
|
||||
case SensorType.Data: format = "{0:F1} GB"; break;
|
||||
case SensorType.SmallData: format = "{0:F1} MB"; break;
|
||||
case SensorType.Factor: format = "{0:F3}"; break;
|
||||
case SensorType.Voltage: fixedFormat = "{0:F3} V"; break;
|
||||
case SensorType.Clock: fixedFormat = "{0:F1} MHz"; break;
|
||||
case SensorType.Load: fixedFormat = "{0:F1} %"; break;
|
||||
case SensorType.Fan: fixedFormat = "{0:F0} RPM"; break;
|
||||
case SensorType.Flow: fixedFormat = "{0:F0} L/h"; break;
|
||||
case SensorType.Control: fixedFormat = "{0:F1} %"; break;
|
||||
case SensorType.Level: fixedFormat = "{0:F1} %"; break;
|
||||
case SensorType.Power: fixedFormat = "{0:F1} W"; break;
|
||||
case SensorType.Data: fixedFormat = "{0:F1} GB"; break;
|
||||
case SensorType.SmallData: fixedFormat = "{0:F1} MB"; break;
|
||||
case SensorType.Factor: fixedFormat = "{0:F3}"; break;
|
||||
default: fixedFormat = ""; break;
|
||||
}
|
||||
|
||||
bool hidden = settings.GetValue(new Identifier(sensor.Identifier,
|
||||
|
@ -69,6 +69,10 @@ namespace OpenHardwareMonitor.GUI {
|
||||
this.Image = Utilities.EmbeddedResources.GetImage("factor.png");
|
||||
this.Text = "Factors";
|
||||
break;
|
||||
case SensorType.Throughput:
|
||||
this.Image = Utilities.EmbeddedResources.GetImage("throughput.png");
|
||||
this.Text = "Throughput";
|
||||
break;
|
||||
}
|
||||
|
||||
NodeAdded += new NodeEventHandler(TypeNode_NodeAdded);
|
||||
|
@ -27,6 +27,7 @@ namespace OpenHardwareMonitor.Hardware {
|
||||
Power, // W
|
||||
Data, // GB = 2^30 Bytes
|
||||
SmallData, // MB = 2^20 Bytes
|
||||
Throughput, // MB/s = 2^20 Bytes/s
|
||||
}
|
||||
|
||||
public struct SensorValue {
|
||||
|
@ -4,7 +4,7 @@
|
||||
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) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
|
||||
Copyright (C) 2009-2020 Michael Möller <mmoeller@openhardwaremonitor.org>
|
||||
Copyright (C) 2011 Christian Vallières
|
||||
|
||||
*/
|
||||
@ -307,6 +307,10 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
|
||||
NvPhysicalGpuHandle gpuHandle, out uint deviceId, out uint subSystemId,
|
||||
out uint revisionId, out uint extDeviceId);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvStatus NvAPI_GPU_GetBusIdDelegate(
|
||||
NvPhysicalGpuHandle gpuHandle, out uint busId);
|
||||
|
||||
private static readonly bool available;
|
||||
private static readonly nvapi_QueryInterfaceDelegate nvapi_QueryInterface;
|
||||
private static readonly NvAPI_InitializeDelegate NvAPI_Initialize;
|
||||
@ -341,6 +345,8 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
|
||||
NvAPI_GetDisplayDriverVersion;
|
||||
public static readonly NvAPI_GPU_GetPCIIdentifiersDelegate
|
||||
NvAPI_GPU_GetPCIIdentifiers;
|
||||
public static readonly NvAPI_GPU_GetBusIdDelegate
|
||||
NvAPI_GPU_GetBusId;
|
||||
|
||||
private NVAPI() { }
|
||||
|
||||
@ -416,6 +422,7 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
|
||||
GetDelegate(0xF951A4D1, out NvAPI_GetDisplayDriverVersion);
|
||||
GetDelegate(0x01053FA5, out _NvAPI_GetInterfaceVersionString);
|
||||
GetDelegate(0x2DDFB66E, out NvAPI_GPU_GetPCIIdentifiers);
|
||||
GetDelegate(0x1BE0B8E5, out NvAPI_GPU_GetBusId);
|
||||
|
||||
available = true;
|
||||
}
|
||||
|
243
Hardware/Nvidia/NVML.cs
Normal file
243
Hardware/Nvidia/NVML.cs
Normal file
@ -0,0 +1,243 @@
|
||||
/*
|
||||
|
||||
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) 2020 Michael Möller <mmoeller@openhardwaremonitor.org>
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenHardwareMonitor.Hardware.Nvidia {
|
||||
internal class NVML {
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate NvmlReturn nvmlInitDelegate();
|
||||
private static readonly nvmlInitDelegate nvmlInit;
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate NvmlReturn nvmlInit_v2Delegate();
|
||||
private static readonly nvmlInit_v2Delegate nvmlInit_v2;
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvmlReturn nvmlShutdownDelegate();
|
||||
public static readonly nvmlShutdownDelegate NvmlShutdown;
|
||||
|
||||
public delegate NvmlReturn nvmlDeviceGetHandleByPciBusIdDelegate(
|
||||
string pciBusId, out NvmlDevice device);
|
||||
public static readonly nvmlDeviceGetHandleByPciBusIdDelegate
|
||||
NvmlDeviceGetHandleByPciBusId;
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvmlReturn nvmlDeviceGetPowerUsageDelegate(
|
||||
NvmlDevice device, out int power);
|
||||
public static readonly nvmlDeviceGetPowerUsageDelegate
|
||||
NvmlDeviceGetPowerUsage;
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate NvmlReturn nvmlDeviceGetPcieThroughputDelegate(
|
||||
NvmlDevice devicee, NvmlPcieUtilCounter counter, out uint value);
|
||||
public static readonly nvmlDeviceGetPcieThroughputDelegate
|
||||
NvmlDeviceGetPcieThroughput;
|
||||
|
||||
|
||||
public static NvmlReturn NvmlInit() {
|
||||
try {
|
||||
var result = nvmlInit_v2();
|
||||
initialized = result == NvmlReturn.Success;
|
||||
return result;
|
||||
} catch {
|
||||
try {
|
||||
var result = nvmlInit();
|
||||
initialized = result == NvmlReturn.Success;
|
||||
return result;
|
||||
} catch {
|
||||
return NvmlReturn.ErrorLibraryNotFound;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetDllName() {
|
||||
int p = (int)Environment.OSVersion.Platform;
|
||||
if ((p == 4) || (p == 128))
|
||||
return "libnvidia-ml.so";
|
||||
else
|
||||
return "nvml.dll";
|
||||
}
|
||||
|
||||
private static T CreateDelegate<T>(string entryPoint) where T : Delegate {
|
||||
var attribute = new DllImportAttribute(GetDllName()) {
|
||||
CallingConvention = CallingConvention.Cdecl,
|
||||
PreserveSig = true,
|
||||
EntryPoint = entryPoint
|
||||
};
|
||||
PInvokeDelegateFactory.CreateDelegate(attribute, out T newDelegate);
|
||||
return newDelegate;
|
||||
}
|
||||
|
||||
static NVML() {
|
||||
nvmlInit =
|
||||
CreateDelegate<nvmlInitDelegate>(
|
||||
"nvmlInit");
|
||||
nvmlInit_v2 =
|
||||
CreateDelegate<nvmlInit_v2Delegate>(
|
||||
"nvmlInit_v2");
|
||||
NvmlShutdown =
|
||||
CreateDelegate<nvmlShutdownDelegate>(
|
||||
"nvmlShutdown");
|
||||
NvmlDeviceGetHandleByPciBusId =
|
||||
CreateDelegate<nvmlDeviceGetHandleByPciBusIdDelegate>(
|
||||
"nvmlDeviceGetHandleByPciBusId_v2");
|
||||
NvmlDeviceGetPowerUsage =
|
||||
CreateDelegate<nvmlDeviceGetPowerUsageDelegate>(
|
||||
"nvmlDeviceGetPowerUsage");
|
||||
NvmlDeviceGetPcieThroughput =
|
||||
CreateDelegate<nvmlDeviceGetPcieThroughputDelegate>(
|
||||
"nvmlDeviceGetPcieThroughput");
|
||||
}
|
||||
|
||||
private static bool initialized;
|
||||
public static bool IsInitialized {
|
||||
get { return initialized; }
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct NvmlDevice {
|
||||
private readonly IntPtr ptr;
|
||||
}
|
||||
|
||||
internal enum NvmlPcieUtilCounter {
|
||||
TxBytes = 0,
|
||||
RxBytes = 1
|
||||
}
|
||||
|
||||
internal enum NvmlReturn {
|
||||
/// <summary>
|
||||
/// The operation was successful
|
||||
/// </summary>
|
||||
Success = 0,
|
||||
|
||||
/// <summary>
|
||||
/// NVML was not first initialized with nvmlInit()
|
||||
/// </summary>
|
||||
ErrorUninitialized = 1,
|
||||
|
||||
/// <summary>
|
||||
/// A supplied argument is invalid
|
||||
/// </summary>
|
||||
ErrorInvalidArgument = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The requested operation is not available on target device
|
||||
/// </summary>
|
||||
ErrorNotSupported = 3,
|
||||
|
||||
/// <summary>
|
||||
/// The current user does not have permission for operation
|
||||
/// </summary>
|
||||
ErrorNoPermission = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Deprecated: Multiple initializations are now allowed through ref
|
||||
/// counting
|
||||
/// </summary>
|
||||
ErrorAlreadyInitialized = 5,
|
||||
|
||||
/// <summary>
|
||||
/// A query to find an object was unsuccessful
|
||||
/// </summary>
|
||||
ErrorNotFound = 6,
|
||||
|
||||
/// <summary>
|
||||
/// An input argument is not large enough
|
||||
/// </summary>
|
||||
ErrorInsufficientSize = 7,
|
||||
|
||||
/// <summary>
|
||||
/// A device's external power cables are not properly attached
|
||||
/// </summary>
|
||||
ErrorInsufficientPower = 8,
|
||||
|
||||
/// <summary>
|
||||
/// NVIDIA driver is not loaded
|
||||
/// </summary>
|
||||
ErrorDriverNotLoaded = 9,
|
||||
|
||||
/// <summary>
|
||||
/// User provided timeout passed
|
||||
/// </summary>
|
||||
ErrorTimeout = 10,
|
||||
|
||||
/// <summary>
|
||||
/// NVIDIA Kernel detected an interrupt issue with a GPU
|
||||
/// </summary>
|
||||
ErrorIrqIssue = 11,
|
||||
|
||||
/// <summary>
|
||||
/// NVML Shared Library couldn't be found or loaded
|
||||
/// </summary>
|
||||
ErrorLibraryNotFound = 12,
|
||||
|
||||
/// <summary>
|
||||
/// Local version of NVML doesn't implement this function
|
||||
/// </summary>
|
||||
ErrorFunctionNotFound = 13,
|
||||
|
||||
/// <summary>
|
||||
/// infoROM is corruptedinfoROM is corrupted
|
||||
/// </summary>
|
||||
ErrorCorruptedInforom = 14,
|
||||
|
||||
/// <summary>
|
||||
/// The GPU has fallen off the bus or has otherwise become inaccessible
|
||||
/// </summary>
|
||||
ErrorGpuIsLost = 15,
|
||||
|
||||
/// <summary>
|
||||
/// The GPU requires a reset before it can be used again
|
||||
/// </summary>
|
||||
ErrorResetRequired = 16,
|
||||
|
||||
/// <summary>
|
||||
/// The GPU control device has been blocked by the operating
|
||||
/// system/cgroups
|
||||
/// </summary>
|
||||
ErrorOperatingSystem = 17,
|
||||
|
||||
/// <summary>
|
||||
/// RM detects a driver/library version mismatch
|
||||
/// </summary>
|
||||
ErrorLibRmVersionMismatch = 18,
|
||||
|
||||
/// <summary>
|
||||
/// An operation cannot be performed because the GPU is currently in use
|
||||
/// </summary>
|
||||
ErrorInUse = 19,
|
||||
|
||||
/// <summary>
|
||||
/// Insufficient memory
|
||||
/// </summary>
|
||||
ErrorMemory = 20,
|
||||
|
||||
/// <summary>
|
||||
/// No data
|
||||
/// </summary>
|
||||
ErrorNoData = 21,
|
||||
|
||||
/// <summary>
|
||||
/// The requested vgpu operation is not available on target device,
|
||||
/// becasue ECC is enabled
|
||||
/// </summary>
|
||||
ErrorvGpuEccNotSupported = 22,
|
||||
|
||||
/// <summary>
|
||||
/// An internal driver error occurred
|
||||
/// </summary>
|
||||
ErrorUnknown = 999
|
||||
};
|
||||
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
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) 2009-2015 Michael Möller <mmoeller@openhardwaremonitor.org>
|
||||
Copyright (C) 2009-2020 Michael Möller <mmoeller@openhardwaremonitor.org>
|
||||
Copyright (C) 2011 Christian Vallières
|
||||
|
||||
*/
|
||||
@ -19,6 +19,7 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
|
||||
private readonly int adapterIndex;
|
||||
private readonly NvPhysicalGpuHandle handle;
|
||||
private readonly NvDisplayHandle? displayHandle;
|
||||
private readonly NVML.NvmlDevice? device;
|
||||
|
||||
private readonly Sensor[] temperatures;
|
||||
private readonly Sensor fan;
|
||||
@ -29,12 +30,16 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
|
||||
private readonly Sensor memoryUsed;
|
||||
private readonly Sensor memoryFree;
|
||||
private readonly Sensor memoryAvail;
|
||||
private readonly Sensor power;
|
||||
private readonly Sensor pcieThroughputRx;
|
||||
private readonly Sensor pcieThroughputTx;
|
||||
private readonly Control fanControl;
|
||||
|
||||
public NvidiaGPU(int adapterIndex, NvPhysicalGpuHandle handle,
|
||||
NvDisplayHandle? displayHandle, ISettings settings)
|
||||
: base(GetName(handle), new Identifier("nvidiagpu",
|
||||
adapterIndex.ToString(CultureInfo.InvariantCulture)), settings) {
|
||||
adapterIndex.ToString(CultureInfo.InvariantCulture)), settings)
|
||||
{
|
||||
this.adapterIndex = adapterIndex;
|
||||
this.handle = handle;
|
||||
this.displayHandle = displayHandle;
|
||||
@ -57,13 +62,11 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
|
||||
ActivateSensor(temperatures[i]);
|
||||
}
|
||||
|
||||
int value;
|
||||
if (NVAPI.NvAPI_GPU_GetTachReading != null &&
|
||||
NVAPI.NvAPI_GPU_GetTachReading(handle, out value) == NvStatus.OK) {
|
||||
if (value >= 0) {
|
||||
fan = new Sensor("GPU", 0, SensorType.Fan, this, settings);
|
||||
ActivateSensor(fan);
|
||||
}
|
||||
NVAPI.NvAPI_GPU_GetTachReading(handle, out _) == NvStatus.OK)
|
||||
{
|
||||
fan = new Sensor("GPU", 0, SensorType.Fan, this, settings);
|
||||
ActivateSensor(fan);
|
||||
}
|
||||
|
||||
clocks = new Sensor[3];
|
||||
@ -93,6 +96,24 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
|
||||
ControlModeChanged(fanControl);
|
||||
control.Control = fanControl;
|
||||
}
|
||||
|
||||
if (NVML.IsInitialized) {
|
||||
if (NVAPI.NvAPI_GPU_GetBusId != null &&
|
||||
NVAPI.NvAPI_GPU_GetBusId(handle, out uint busId) == NvStatus.OK) {
|
||||
if (NVML.NvmlDeviceGetHandleByPciBusId(
|
||||
"0000:" + busId.ToString("X2") + ":00.0", out var result)
|
||||
== NVML.NvmlReturn.Success)
|
||||
{
|
||||
device = result;
|
||||
power = new Sensor("GPU Power", 0, SensorType.Power, this, settings);
|
||||
pcieThroughputRx = new Sensor("GPU PCIE Rx", 0,
|
||||
SensorType.Throughput, this, settings);
|
||||
pcieThroughputTx = new Sensor("GPU PCIE Tx", 1,
|
||||
SensorType.Throughput, this, settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Update();
|
||||
}
|
||||
|
||||
@ -152,10 +173,10 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
|
||||
foreach (Sensor sensor in temperatures)
|
||||
sensor.Value = settings.Sensor[sensor.Index].CurrentTemp;
|
||||
|
||||
if (fan != null) {
|
||||
int value = 0;
|
||||
NVAPI.NvAPI_GPU_GetTachReading(handle, out value);
|
||||
fan.Value = value;
|
||||
if (fan != null && NVAPI.NvAPI_GPU_GetTachReading(handle, out int fanValue)
|
||||
== NvStatus.OK)
|
||||
{
|
||||
fan.Value = fanValue;
|
||||
}
|
||||
|
||||
uint[] values = GetClocks();
|
||||
@ -219,6 +240,34 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
|
||||
ActivateSensor(memoryFree);
|
||||
ActivateSensor(memoryLoad);
|
||||
}
|
||||
|
||||
if (power != null) {
|
||||
if (NVML.NvmlDeviceGetPowerUsage(device.Value, out int powerValue)
|
||||
== NVML.NvmlReturn.Success)
|
||||
{
|
||||
power.Value = powerValue * 0.001f;
|
||||
ActivateSensor(power);
|
||||
}
|
||||
}
|
||||
|
||||
if (pcieThroughputRx != null) {
|
||||
if (NVML.NvmlDeviceGetPcieThroughput(device.Value,
|
||||
NVML.NvmlPcieUtilCounter.RxBytes, out uint value)
|
||||
== NVML.NvmlReturn.Success)
|
||||
{
|
||||
pcieThroughputRx.Value = value * (1.0f / 0x400);
|
||||
ActivateSensor(pcieThroughputRx);
|
||||
}
|
||||
}
|
||||
|
||||
if (pcieThroughputTx != null) {
|
||||
if (NVML.NvmlDeviceGetPcieThroughput(device.Value,
|
||||
NVML.NvmlPcieUtilCounter.TxBytes, out uint value)
|
||||
== NVML.NvmlReturn.Success) {
|
||||
pcieThroughputTx.Value = value * (1.0f / 0x400);
|
||||
ActivateSensor(pcieThroughputTx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetReport() {
|
||||
|
@ -4,7 +4,7 @@
|
||||
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) 2009-2011 Michael Möller <mmoeller@openhardwaremonitor.org>
|
||||
Copyright (C) 2009-2020 Michael Möller <mmoeller@openhardwaremonitor.org>
|
||||
|
||||
*/
|
||||
|
||||
@ -28,7 +28,7 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
|
||||
|
||||
string version;
|
||||
if (NVAPI.NvAPI_GetInterfaceVersionString(out version) == NvStatus.OK) {
|
||||
report.Append("Version: ");
|
||||
report.Append(" Version: ");
|
||||
report.AppendLine(version);
|
||||
}
|
||||
|
||||
@ -36,18 +36,26 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
|
||||
new NvPhysicalGpuHandle[NVAPI.MAX_PHYSICAL_GPUS];
|
||||
int count;
|
||||
if (NVAPI.NvAPI_EnumPhysicalGPUs == null) {
|
||||
report.AppendLine("Error: NvAPI_EnumPhysicalGPUs not available");
|
||||
report.AppendLine(" Error: NvAPI_EnumPhysicalGPUs not available");
|
||||
report.AppendLine();
|
||||
return;
|
||||
} else {
|
||||
NvStatus status = NVAPI.NvAPI_EnumPhysicalGPUs(handles, out count);
|
||||
if (status != NvStatus.OK) {
|
||||
report.AppendLine("Status: " + status);
|
||||
report.AppendLine(" Status: " + status);
|
||||
report.AppendLine();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var result = NVML.NvmlInit();
|
||||
|
||||
report.AppendLine();
|
||||
report.AppendLine("NVML");
|
||||
report.AppendLine();
|
||||
report.AppendLine(" Status: " + result);
|
||||
report.AppendLine();
|
||||
|
||||
IDictionary<NvPhysicalGpuHandle, NvDisplayHandle> displayHandles =
|
||||
new Dictionary<NvPhysicalGpuHandle, NvDisplayHandle>();
|
||||
|
||||
@ -100,7 +108,11 @@ namespace OpenHardwareMonitor.Hardware.Nvidia {
|
||||
|
||||
public void Close() {
|
||||
foreach (Hardware gpu in hardware)
|
||||
gpu.Close();
|
||||
gpu.Close();
|
||||
|
||||
if (NVML.IsInitialized) {
|
||||
NVML.NvmlShutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -295,6 +295,9 @@
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\ram.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources\throughput.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio AllowExistingFolder="true" />
|
||||
|
@ -94,6 +94,7 @@
|
||||
<Compile Include="Hardware\LPC\NCT677X.cs" />
|
||||
<Compile Include="Hardware\Mainboard\GigabyteTAMG.cs" />
|
||||
<Compile Include="Hardware\Mainboard\Identification.cs" />
|
||||
<Compile Include="Hardware\Nvidia\NVML.cs" />
|
||||
<Compile Include="Hardware\Opcode.cs" />
|
||||
<Compile Include="Hardware\OperatingSystem.cs" />
|
||||
<Compile Include="Hardware\RAM\GenericRAM.cs" />
|
||||
|
BIN
Resources/throughput.png
Normal file
BIN
Resources/throughput.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 369 B |
Loading…
x
Reference in New Issue
Block a user