mirror of
https://github.com/openhardwaremonitor/openhardwaremonitor
synced 2025-08-22 09:57:20 +00:00
243 lines
6.9 KiB
C#
243 lines
6.9 KiB
C#
/*
|
|
|
|
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() {
|
|
if (OperatingSystem.IsUnix)
|
|
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
|
|
};
|
|
|
|
}
|
|
}
|