@@ -0,0 +1,238 @@
|
||||
// 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.
|
||||
// Ported from: https://github.com/processhacker/processhacker/blob/master/plugins/ExtendedTools/gpumon.c
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using LibreHardwareMonitor.Interop;
|
||||
|
||||
namespace LibreHardwareMonitor.Hardware
|
||||
{
|
||||
internal static class D3DDisplayDevice
|
||||
{
|
||||
public static string[] GetDeviceIdentifiers()
|
||||
{
|
||||
if (CfgMgr32.CM_Get_Device_Interface_List_Size(out uint size, ref CfgMgr32.GUID_DISPLAY_DEVICE_ARRIVAL, null, CfgMgr32.CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CfgMgr32.CR_SUCCESS)
|
||||
return null;
|
||||
|
||||
|
||||
char[] data = new char[size];
|
||||
if (CfgMgr32.CM_Get_Device_Interface_List(ref CfgMgr32.GUID_DISPLAY_DEVICE_ARRIVAL, null, data, (uint)data.Length, CfgMgr32.CM_GET_DEVICE_INTERFACE_LIST_PRESENT) == CfgMgr32.CR_SUCCESS)
|
||||
return new string(data).Split('\0').Where(m => !string.IsNullOrEmpty(m)).ToArray();
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static bool GetDeviceInfoByIdentifier(string deviceIdentifier, out D3DDeviceInfo deviceInfo)
|
||||
{
|
||||
deviceInfo = new D3DDeviceInfo();
|
||||
|
||||
OpenAdapterFromDeviceName(out uint status, deviceIdentifier, out D3dkmth.D3DKMT_OPENADAPTERFROMDEVICENAME adapter);
|
||||
if (status != WinNt.STATUS_SUCCESS)
|
||||
return false;
|
||||
|
||||
|
||||
GetAdapterType(out status, adapter, out D3dkmth.D3DKMT_ADAPTERTYPE adapterType);
|
||||
if (status != WinNt.STATUS_SUCCESS)
|
||||
return false;
|
||||
|
||||
if (!adapterType.Value.HasFlag(D3dkmth.D3DKMT_ADAPTERTYPE_FLAGS.SoftwareDevice))
|
||||
return false;
|
||||
|
||||
|
||||
GetQueryStatisticsAdapterInformation(out status, adapter, out D3dkmth.D3DKMT_QUERYSTATISTICS_ADAPTER_INFORMATION adapterInformation);
|
||||
if (status != WinNt.STATUS_SUCCESS)
|
||||
return false;
|
||||
|
||||
|
||||
uint segmentCount = adapterInformation.NbSegments;
|
||||
uint nodeCount = adapterInformation.NodeCount;
|
||||
|
||||
deviceInfo.Nodes = new D3DDeviceNodeInfo[nodeCount];
|
||||
|
||||
for (uint nodeId = 0; nodeId < nodeCount; nodeId++)
|
||||
{
|
||||
GetNodeMetaData(out status, adapter, nodeId, out D3dkmth.D3DKMT_NODEMETADATA nodeMetaData);
|
||||
if (status != WinNt.STATUS_SUCCESS)
|
||||
return false;
|
||||
|
||||
|
||||
GetQueryStatisticsNode(out status, adapter, nodeId, out D3dkmth.D3DKMT_QUERYSTATISTICS_NODE_INFORMATION nodeInformation);
|
||||
if (status != WinNt.STATUS_SUCCESS)
|
||||
return false;
|
||||
|
||||
|
||||
deviceInfo.Nodes[nodeId] = new D3DDeviceNodeInfo
|
||||
{
|
||||
Id = nodeId, Name = GetNodeEngineTypeString(nodeMetaData), RunningTime = nodeInformation.GlobalInformation.RunningTime.QuadPart, QueryTime = DateTime.Now
|
||||
};
|
||||
}
|
||||
|
||||
for (uint segmentId = 0; segmentId < segmentCount; segmentId++)
|
||||
{
|
||||
GetQueryStatisticsSegment(out status, adapter, segmentId, out D3dkmth.D3DKMT_QUERYSTATISTICS_SEGMENT_INFORMATION segmentInformation);
|
||||
if (status != WinNt.STATUS_SUCCESS)
|
||||
return false;
|
||||
|
||||
|
||||
ulong commitLimit = segmentInformation.CommitLimit;
|
||||
ulong bytesResident = segmentInformation.BytesResident;
|
||||
ulong bytesCommitted = segmentInformation.BytesCommitted;
|
||||
|
||||
uint aperture = segmentInformation.Aperture;
|
||||
|
||||
if (aperture == 1)
|
||||
{
|
||||
deviceInfo.GpuSharedLimit += commitLimit;
|
||||
deviceInfo.GpuSharedUsed += bytesResident;
|
||||
deviceInfo.GpuSharedMax += bytesCommitted;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceInfo.GpuDedicatedLimit += commitLimit;
|
||||
deviceInfo.GpuDedicatedUsed += bytesResident;
|
||||
deviceInfo.GpuDedicatedMax += bytesCommitted;
|
||||
}
|
||||
}
|
||||
|
||||
CloseAdapter(out status, adapter);
|
||||
return status == WinNt.STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
private static string GetNodeEngineTypeString(D3dkmth.D3DKMT_NODEMETADATA nodeMetaData)
|
||||
{
|
||||
return nodeMetaData.NodeData.EngineType switch
|
||||
{
|
||||
D3dkmdt.DXGK_ENGINE_TYPE.DXGK_ENGINE_TYPE_OTHER => "D3D " + nodeMetaData.NodeData.FriendlyName,
|
||||
D3dkmdt.DXGK_ENGINE_TYPE.DXGK_ENGINE_TYPE_3D => "D3D 3D",
|
||||
D3dkmdt.DXGK_ENGINE_TYPE.DXGK_ENGINE_TYPE_VIDEO_DECODE => "D3D Video Decode",
|
||||
D3dkmdt.DXGK_ENGINE_TYPE.DXGK_ENGINE_TYPE_VIDEO_ENCODE => "D3D Video Encode",
|
||||
D3dkmdt.DXGK_ENGINE_TYPE.DXGK_ENGINE_TYPE_VIDEO_PROCESSING => "D3D Video Processing",
|
||||
D3dkmdt.DXGK_ENGINE_TYPE.DXGK_ENGINE_TYPE_SCENE_ASSEMBLY => "D3D Scene Assembly",
|
||||
D3dkmdt.DXGK_ENGINE_TYPE.DXGK_ENGINE_TYPE_COPY => "D3D Copy",
|
||||
D3dkmdt.DXGK_ENGINE_TYPE.DXGK_ENGINE_TYPE_OVERLAY => "D3D Overlay",
|
||||
D3dkmdt.DXGK_ENGINE_TYPE.DXGK_ENGINE_TYPE_CRYPTO => "D3D Crypto",
|
||||
_ => "D3D Unknown",
|
||||
};
|
||||
}
|
||||
|
||||
private static void GetNodeMetaData(out uint status, D3dkmth.D3DKMT_OPENADAPTERFROMDEVICENAME adapter, uint nodeId, out D3dkmth.D3DKMT_NODEMETADATA nodeMetaDataResult)
|
||||
{
|
||||
IntPtr nodeMetaDataPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(D3dkmth.D3DKMT_NODEMETADATA)));
|
||||
nodeMetaDataResult = new D3dkmth.D3DKMT_NODEMETADATA { NodeOrdinalAndAdapterIndex = nodeId };
|
||||
Marshal.StructureToPtr(nodeMetaDataResult, nodeMetaDataPtr, true);
|
||||
|
||||
var queryAdapterInfo = new D3dkmth.D3DKMT_QUERYADAPTERINFO
|
||||
{
|
||||
hAdapter = adapter.hAdapter,
|
||||
Type = D3dkmth.KMTQUERYADAPTERINFOTYPE.KMTQAITYPE_NODEMETADATA,
|
||||
pPrivateDriverData = nodeMetaDataPtr,
|
||||
PrivateDriverDataSize = Marshal.SizeOf(typeof(D3dkmth.D3DKMT_NODEMETADATA))
|
||||
};
|
||||
|
||||
status = Gdi32.D3DKMTQueryAdapterInfo(ref queryAdapterInfo);
|
||||
nodeMetaDataResult = Marshal.PtrToStructure<D3dkmth.D3DKMT_NODEMETADATA>(nodeMetaDataPtr);
|
||||
Marshal.FreeHGlobal(nodeMetaDataPtr);
|
||||
}
|
||||
|
||||
private static void GetQueryStatisticsNode(out uint status, D3dkmth.D3DKMT_OPENADAPTERFROMDEVICENAME adapter, uint nodeId, out D3dkmth.D3DKMT_QUERYSTATISTICS_NODE_INFORMATION nodeInformation)
|
||||
{
|
||||
var queryElement = new D3dkmth.D3DKMT_QUERYSTATISTICS_QUERY_ELEMENT { QueryNode = { NodeId = nodeId } };
|
||||
|
||||
var queryStatistics = new D3dkmth.D3DKMT_QUERYSTATISTICS
|
||||
{
|
||||
AdapterLuid = adapter.AdapterLuid, Type = D3dkmth.D3DKMT_QUERYSTATISTICS_TYPE.D3DKMT_QUERYSTATISTICS_NODE, QueryElement = queryElement
|
||||
};
|
||||
|
||||
status = Gdi32.D3DKMTQueryStatistics(ref queryStatistics);
|
||||
|
||||
nodeInformation = queryStatistics.QueryResult.NodeInformation;
|
||||
}
|
||||
|
||||
private static void GetQueryStatisticsSegment
|
||||
(
|
||||
out uint status,
|
||||
D3dkmth.D3DKMT_OPENADAPTERFROMDEVICENAME adapter,
|
||||
uint segmentId,
|
||||
out D3dkmth.D3DKMT_QUERYSTATISTICS_SEGMENT_INFORMATION segmentInformation)
|
||||
{
|
||||
var queryElement = new D3dkmth.D3DKMT_QUERYSTATISTICS_QUERY_ELEMENT { QuerySegment = { SegmentId = segmentId } };
|
||||
|
||||
var queryStatistics = new D3dkmth.D3DKMT_QUERYSTATISTICS
|
||||
{
|
||||
AdapterLuid = adapter.AdapterLuid, Type = D3dkmth.D3DKMT_QUERYSTATISTICS_TYPE.D3DKMT_QUERYSTATISTICS_SEGMENT, QueryElement = queryElement
|
||||
};
|
||||
|
||||
status = Gdi32.D3DKMTQueryStatistics(ref queryStatistics);
|
||||
|
||||
segmentInformation = queryStatistics.QueryResult.SegmentInformation;
|
||||
}
|
||||
|
||||
private static void GetQueryStatisticsAdapterInformation
|
||||
(
|
||||
out uint status,
|
||||
D3dkmth.D3DKMT_OPENADAPTERFROMDEVICENAME adapter,
|
||||
out D3dkmth.D3DKMT_QUERYSTATISTICS_ADAPTER_INFORMATION adapterInformation)
|
||||
{
|
||||
var queryStatistics = new D3dkmth.D3DKMT_QUERYSTATISTICS { AdapterLuid = adapter.AdapterLuid, Type = D3dkmth.D3DKMT_QUERYSTATISTICS_TYPE.D3DKMT_QUERYSTATISTICS_ADAPTER, };
|
||||
|
||||
status = Gdi32.D3DKMTQueryStatistics(ref queryStatistics);
|
||||
|
||||
adapterInformation = queryStatistics.QueryResult.AdapterInformation;
|
||||
}
|
||||
|
||||
private static void GetAdapterType(out uint status, D3dkmth.D3DKMT_OPENADAPTERFROMDEVICENAME adapter, out D3dkmth.D3DKMT_ADAPTERTYPE adapterTypeResult)
|
||||
{
|
||||
IntPtr adapterTypePtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(D3dkmth.D3DKMT_ADAPTERTYPE)));
|
||||
var queryAdapterInfo = new D3dkmth.D3DKMT_QUERYADAPTERINFO
|
||||
{
|
||||
hAdapter = adapter.hAdapter,
|
||||
Type = D3dkmth.KMTQUERYADAPTERINFOTYPE.KMTQAITYPE_ADAPTERTYPE,
|
||||
pPrivateDriverData = adapterTypePtr,
|
||||
PrivateDriverDataSize = Marshal.SizeOf(typeof(D3dkmth.D3DKMT_ADAPTERTYPE))
|
||||
};
|
||||
|
||||
status = Gdi32.D3DKMTQueryAdapterInfo(ref queryAdapterInfo);
|
||||
adapterTypeResult = Marshal.PtrToStructure<D3dkmth.D3DKMT_ADAPTERTYPE>(adapterTypePtr);
|
||||
Marshal.FreeHGlobal(adapterTypePtr);
|
||||
}
|
||||
|
||||
private static void OpenAdapterFromDeviceName(out uint status, string displayDeviceName, out D3dkmth.D3DKMT_OPENADAPTERFROMDEVICENAME adapter)
|
||||
{
|
||||
adapter = new D3dkmth.D3DKMT_OPENADAPTERFROMDEVICENAME { pDeviceName = displayDeviceName };
|
||||
status = Gdi32.D3DKMTOpenAdapterFromDeviceName(ref adapter);
|
||||
}
|
||||
|
||||
private static void CloseAdapter(out uint status, D3dkmth.D3DKMT_OPENADAPTERFROMDEVICENAME adapter)
|
||||
{
|
||||
var closeAdapter = new D3dkmth.D3DKMT_CLOSEADAPTER { hAdapter = adapter.hAdapter };
|
||||
status = Gdi32.D3DKMTCloseAdapter(ref closeAdapter);
|
||||
}
|
||||
|
||||
public struct D3DDeviceNodeInfo
|
||||
{
|
||||
public ulong Id;
|
||||
public string Name;
|
||||
public long RunningTime;
|
||||
public DateTime QueryTime;
|
||||
}
|
||||
|
||||
public struct D3DDeviceInfo
|
||||
{
|
||||
public ulong GpuSharedLimit;
|
||||
public ulong GpuDedicatedLimit;
|
||||
|
||||
public ulong GpuSharedUsed;
|
||||
public ulong GpuDedicatedUsed;
|
||||
|
||||
public ulong GpuSharedMax;
|
||||
public ulong GpuDedicatedMax;
|
||||
|
||||
public D3DDeviceNodeInfo[] Nodes;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,19 +16,26 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
private readonly int _adapterIndex;
|
||||
|
||||
private readonly IntPtr _context = IntPtr.Zero;
|
||||
private readonly bool _framemetricsStarted = false;
|
||||
|
||||
private readonly Sensor _controlSensor;
|
||||
private readonly Sensor _coreClock;
|
||||
private readonly Sensor _coreLoad;
|
||||
private readonly Sensor _coreVoltage;
|
||||
private readonly bool _overdriveApiSupported;
|
||||
private readonly int _currentOverdriveApiLevel;
|
||||
private readonly Sensor _fan;
|
||||
private readonly Control _fanControl;
|
||||
private readonly bool _frameMetricsStarted;
|
||||
private readonly Sensor _fullscreenFps;
|
||||
private readonly Sensor _gpuDedicatedMemoryUsage;
|
||||
private readonly Sensor[] _gpuNodeUsage;
|
||||
private readonly DateTime[] _gpuNodeUsagePrevTick;
|
||||
private readonly long[] _gpuNodeUsagePrevValue;
|
||||
private readonly Sensor _gpuSharedMemoryUsage;
|
||||
private readonly Sensor _memoryClock;
|
||||
private readonly Sensor _memoryLoad;
|
||||
private readonly int _memorySensorIndex;
|
||||
private readonly Sensor _memoryVoltage;
|
||||
private readonly int _nodeSensorIndex;
|
||||
private readonly bool _overdriveApiSupported;
|
||||
private readonly Sensor _powerCore;
|
||||
private readonly Sensor _powerPpt;
|
||||
private readonly Sensor _powerSoC;
|
||||
@@ -43,14 +50,14 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
private readonly Sensor _temperaturePlx;
|
||||
private readonly Sensor _temperatureSoC;
|
||||
private readonly Sensor _temperatureVddc;
|
||||
private readonly Sensor _fullscreenFPS;
|
||||
private readonly string _windowsDeviceName;
|
||||
|
||||
public AmdGpu(string name, int adapterIndex, int busNumber, int deviceNumber, ISettings settings)
|
||||
: base(name, new Identifier("gpu-amd", adapterIndex.ToString(CultureInfo.InvariantCulture)), settings)
|
||||
public AmdGpu(AtiAdlxx.ADLAdapterInfo adapterInfo, ISettings settings)
|
||||
: base(adapterInfo.AdapterName.Trim(), new Identifier("gpu-amd", adapterInfo.AdapterIndex.ToString(CultureInfo.InvariantCulture)), settings)
|
||||
{
|
||||
_adapterIndex = adapterIndex;
|
||||
BusNumber = busNumber;
|
||||
DeviceNumber = deviceNumber;
|
||||
_adapterIndex = adapterInfo.AdapterIndex;
|
||||
BusNumber = adapterInfo.BusNumber;
|
||||
DeviceNumber = adapterInfo.DeviceNumber;
|
||||
|
||||
_temperatureCore = new Sensor("GPU Core", 0, SensorType.Temperature, this, settings);
|
||||
_temperatureMemory = new Sensor("GPU Memory", 1, SensorType.Temperature, this, settings);
|
||||
@@ -81,7 +88,40 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
_powerSoC = new Sensor("GPU SoC", 2, SensorType.Power, this, settings);
|
||||
_powerTotal = new Sensor("GPU Package", 3, SensorType.Power, this, settings);
|
||||
|
||||
_fullscreenFPS = new Sensor("Fullscreen FPS", 0, SensorType.Factor, this, settings);
|
||||
_fullscreenFps = new Sensor("Fullscreen FPS", 0, SensorType.Factor, this, settings);
|
||||
|
||||
if (!Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
string convertedPnpString = adapterInfo.PNPString.Replace("\\", "#");
|
||||
string[] deviceIdentifiers = D3DDisplayDevice.GetDeviceIdentifiers();
|
||||
if (deviceIdentifiers != null)
|
||||
{
|
||||
foreach (string deviceIdentifier in deviceIdentifiers)
|
||||
{
|
||||
if (deviceIdentifier.IndexOf(convertedPnpString, StringComparison.OrdinalIgnoreCase) != -1 &&
|
||||
D3DDisplayDevice.GetDeviceInfoByIdentifier(deviceIdentifier, out D3DDisplayDevice.D3DDeviceInfo deviceInfo))
|
||||
{
|
||||
_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);
|
||||
|
||||
_gpuNodeUsage = new Sensor[deviceInfo.Nodes.Length];
|
||||
_gpuNodeUsagePrevValue = new long[deviceInfo.Nodes.Length];
|
||||
_gpuNodeUsagePrevTick = new DateTime[deviceInfo.Nodes.Length];
|
||||
|
||||
foreach (D3DDisplayDevice.D3DDeviceNodeInfo node in deviceInfo.Nodes)
|
||||
{
|
||||
_gpuNodeUsage[node.Id] = new Sensor(node.Name, _nodeSensorIndex++, SensorType.Load, this, settings);
|
||||
_gpuNodeUsagePrevValue[node.Id] = node.RunningTime;
|
||||
_gpuNodeUsagePrevTick[node.Id] = node.QueryTime;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int supported = 0;
|
||||
int enabled = 0;
|
||||
@@ -91,9 +131,9 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
{
|
||||
if (supported == AtiAdlxx.ADL_TRUE && AtiAdlxx.ADL2_Adapter_FrameMetrics_Start(_context, _adapterIndex, 0) == AtiAdlxx.ADLStatus.ADL_OK)
|
||||
{
|
||||
_framemetricsStarted = true;
|
||||
_fullscreenFPS.Value = -1;
|
||||
ActivateSensor(_fullscreenFPS);
|
||||
_frameMetricsStarted = true;
|
||||
_fullscreenFps.Value = -1;
|
||||
ActivateSensor(_fullscreenFps);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,12 +147,12 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
if (_currentOverdriveApiLevel >= 6)
|
||||
{
|
||||
if (AtiAdlxx.ADL2_Main_Control_Create(AtiAdlxx.Main_Memory_Alloc, adapterIndex, ref _context) == AtiAdlxx.ADLStatus.ADL_OK)
|
||||
if (AtiAdlxx.ADL2_Main_Control_Create(AtiAdlxx.Main_Memory_Alloc, _adapterIndex, ref _context) == AtiAdlxx.ADLStatus.ADL_OK)
|
||||
_context = IntPtr.Zero;
|
||||
}
|
||||
|
||||
AtiAdlxx.ADLFanSpeedInfo fanSpeedInfo = new AtiAdlxx.ADLFanSpeedInfo();
|
||||
if (AtiAdlxx.ADL_Overdrive5_FanSpeedInfo_Get(adapterIndex, 0, ref fanSpeedInfo) != AtiAdlxx.ADLStatus.ADL_OK)
|
||||
AtiAdlxx.ADLFanSpeedInfo fanSpeedInfo = new();
|
||||
if (AtiAdlxx.ADL_Overdrive5_FanSpeedInfo_Get(_adapterIndex, 0, ref fanSpeedInfo) != AtiAdlxx.ADLStatus.ADL_OK)
|
||||
{
|
||||
fanSpeedInfo.MaxPercent = 100;
|
||||
fanSpeedInfo.MinPercent = 0;
|
||||
@@ -139,11 +179,9 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
{
|
||||
if (control.ControlMode == ControlMode.Software)
|
||||
{
|
||||
AtiAdlxx.ADLFanSpeedValue fanSpeedValue = new AtiAdlxx.ADLFanSpeedValue
|
||||
AtiAdlxx.ADLFanSpeedValue fanSpeedValue = new()
|
||||
{
|
||||
SpeedType = AtiAdlxx.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT,
|
||||
Flags = AtiAdlxx.ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED,
|
||||
FanSpeed = (int)control.SoftwareValue
|
||||
SpeedType = AtiAdlxx.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT, Flags = AtiAdlxx.ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED, FanSpeed = (int)control.SoftwareValue
|
||||
};
|
||||
|
||||
AtiAdlxx.ADL_Overdrive5_FanSpeed_Set(_adapterIndex, 0, ref fanSpeedValue);
|
||||
@@ -177,16 +215,35 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
if(_framemetricsStarted)
|
||||
if (_windowsDeviceName != null && D3DDisplayDevice.GetDeviceInfoByIdentifier(_windowsDeviceName, out D3DDisplayDevice.D3DDeviceInfo deviceInfo))
|
||||
{
|
||||
_gpuDedicatedMemoryUsage.Value = 1f * deviceInfo.GpuDedicatedUsed / 1024 / 1024;
|
||||
_gpuSharedMemoryUsage.Value = 1f * deviceInfo.GpuSharedUsed / 1024 / 1024;
|
||||
ActivateSensor(_gpuDedicatedMemoryUsage);
|
||||
ActivateSensor(_gpuSharedMemoryUsage);
|
||||
|
||||
foreach (D3DDisplayDevice.D3DDeviceNodeInfo node in deviceInfo.Nodes)
|
||||
{
|
||||
long runningTimeDiff = node.RunningTime - _gpuNodeUsagePrevValue[node.Id];
|
||||
long timeDiff = node.QueryTime.Ticks - _gpuNodeUsagePrevTick[node.Id].Ticks;
|
||||
|
||||
_gpuNodeUsage[node.Id].Value = 100f * runningTimeDiff / timeDiff;
|
||||
_gpuNodeUsagePrevValue[node.Id] = node.RunningTime;
|
||||
_gpuNodeUsagePrevTick[node.Id] = node.QueryTime;
|
||||
ActivateSensor(_gpuNodeUsage[node.Id]);
|
||||
}
|
||||
}
|
||||
|
||||
if (_frameMetricsStarted)
|
||||
{
|
||||
float framesPerSecond = 0;
|
||||
if (AtiAdlxx.ADL2_Adapter_FrameMetrics_Get(_context, _adapterIndex, 0, ref framesPerSecond) == AtiAdlxx.ADLStatus.ADL_OK)
|
||||
{
|
||||
_fullscreenFPS.Value = framesPerSecond;
|
||||
_fullscreenFps.Value = framesPerSecond;
|
||||
}
|
||||
}
|
||||
|
||||
if (_currentOverdriveApiLevel < 8)
|
||||
if (_overdriveApiSupported)
|
||||
{
|
||||
if (_currentOverdriveApiLevel >= 6)
|
||||
{
|
||||
@@ -217,7 +274,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
}
|
||||
else
|
||||
{
|
||||
AtiAdlxx.ADLPMLogDataOutput logDataOutput = new AtiAdlxx.ADLPMLogDataOutput();
|
||||
AtiAdlxx.ADLPMLogDataOutput logDataOutput = new();
|
||||
if (AtiAdlxx.ADL2_New_QueryPMLogData_Get(_context, _adapterIndex, ref logDataOutput) == AtiAdlxx.ADLStatus.ADL_OK)
|
||||
{
|
||||
GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_EDGE, _temperatureCore);
|
||||
@@ -266,7 +323,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
private void GetOD5CurrentActivity()
|
||||
{
|
||||
AtiAdlxx.ADLPMActivity adlpmActivity = new AtiAdlxx.ADLPMActivity();
|
||||
AtiAdlxx.ADLPMActivity adlpmActivity = new();
|
||||
if (AtiAdlxx.ADL_Overdrive5_CurrentActivity_Get(_adapterIndex, ref adlpmActivity) == AtiAdlxx.ADLStatus.ADL_OK)
|
||||
{
|
||||
if (adlpmActivity.EngineClock > 0)
|
||||
@@ -313,7 +370,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
private void GetOD5FanSpeed(int speedType, Sensor sensor)
|
||||
{
|
||||
AtiAdlxx.ADLFanSpeedValue fanSpeedValue = new AtiAdlxx.ADLFanSpeedValue { SpeedType = speedType };
|
||||
AtiAdlxx.ADLFanSpeedValue fanSpeedValue = new() { SpeedType = speedType };
|
||||
if (AtiAdlxx.ADL_Overdrive5_FanSpeed_Get(_adapterIndex, 0, ref fanSpeedValue) == AtiAdlxx.ADLStatus.ADL_OK)
|
||||
{
|
||||
sensor.Value = fanSpeedValue.FanSpeed;
|
||||
@@ -325,17 +382,17 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
}
|
||||
}
|
||||
|
||||
private void GetOD5Temperature(Sensor _temperatureCore)
|
||||
private void GetOD5Temperature(Sensor temperatureCore)
|
||||
{
|
||||
AtiAdlxx.ADLTemperature temperature = new AtiAdlxx.ADLTemperature();
|
||||
AtiAdlxx.ADLTemperature temperature = new();
|
||||
if (AtiAdlxx.ADL_Overdrive5_Temperature_Get(_adapterIndex, 0, ref temperature) == AtiAdlxx.ADLStatus.ADL_OK)
|
||||
{
|
||||
_temperatureCore.Value = 0.001f * temperature.Temperature;
|
||||
ActivateSensor(_temperatureCore);
|
||||
temperatureCore.Value = 0.001f * temperature.Temperature;
|
||||
ActivateSensor(temperatureCore);
|
||||
}
|
||||
else
|
||||
{
|
||||
_temperatureCore.Value = null;
|
||||
temperatureCore.Value = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,6 +401,8 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="sensor">The sensor.</param>
|
||||
/// <param name="minTemperature">The minimum temperature.</param>
|
||||
/// <param name="scale">The scale.</param>
|
||||
private void GetODNTemperature(AtiAdlxx.ADLODNTemperatureType type, Sensor sensor, double minTemperature = -200, double scale = 1)
|
||||
{
|
||||
// If a sensor isn't available, some cards report 54000 degrees C. 110C is expected for Navi, so 100 more than that should be enough to use as a maximum.
|
||||
@@ -410,7 +469,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
if (_fanControl.ControlMode != ControlMode.Undefined)
|
||||
SetDefaultFanSpeed();
|
||||
|
||||
if (_framemetricsStarted)
|
||||
if (_frameMetricsStarted)
|
||||
AtiAdlxx.ADL2_Adapter_FrameMetrics_Stop(_context, _adapterIndex, 0);
|
||||
|
||||
if (_context != IntPtr.Zero)
|
||||
|
||||
@@ -80,12 +80,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
}
|
||||
|
||||
if (!found)
|
||||
_hardware.Add(new AmdGpu(
|
||||
adapterInfo[i].AdapterName.Trim(),
|
||||
adapterInfo[i].AdapterIndex,
|
||||
adapterInfo[i].BusNumber,
|
||||
adapterInfo[i].DeviceNumber,
|
||||
settings));
|
||||
_hardware.Add(new AmdGpu(adapterInfo[i], settings));
|
||||
}
|
||||
|
||||
_report.AppendLine();
|
||||
|
||||
@@ -8,6 +8,7 @@ using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using LibreHardwareMonitor.Interop;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
{
|
||||
@@ -19,17 +20,25 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
private readonly NvApi.NvDisplayHandle? _displayHandle;
|
||||
private readonly Sensor _fan;
|
||||
private readonly Control _fanControl;
|
||||
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 _memoryUsed;
|
||||
private readonly int _nodeSensorIndex;
|
||||
private readonly NvidiaML.NvmlDevice? _nvmlDevice;
|
||||
private readonly Sensor _pcieThroughputRx;
|
||||
private readonly Sensor _pcieThroughputTx;
|
||||
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)
|
||||
@@ -120,6 +129,101 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
_pcieThroughputRx = new Sensor("GPU PCIe Rx", 0, SensorType.Throughput, this, settings);
|
||||
_pcieThroughputTx = new Sensor("GPU PCIe Tx", 1, SensorType.Throughput, this, settings);
|
||||
|
||||
if (!Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
NvidiaML.NvmlPciInfo? pciInfo = NvidiaML.NvmlDeviceGetPciInfo(_nvmlDevice.Value);
|
||||
|
||||
if (pciInfo is { } pci)
|
||||
{
|
||||
string[] deviceIdentifiers = D3DDisplayDevice.GetDeviceIdentifiers();
|
||||
if (deviceIdentifiers != null)
|
||||
{
|
||||
foreach (string deviceIdentifier in deviceIdentifiers)
|
||||
{
|
||||
if (deviceIdentifier.IndexOf("VEN_" + pci.pciVendorId.ToString("X"), StringComparison.OrdinalIgnoreCase) != -1 &&
|
||||
deviceIdentifier.IndexOf("DEV_" + pci.pciDeviceId.ToString("X"), StringComparison.OrdinalIgnoreCase) != -1 &&
|
||||
deviceIdentifier.IndexOf("SUBSYS_" + pci.pciSubSystemId.ToString("X"), StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
bool isMatch = false;
|
||||
|
||||
try
|
||||
{
|
||||
if (Registry.GetValue(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\nvlddmkm\Enum", adapterIndex.ToString(), null) is string adapterPnpId)
|
||||
{
|
||||
if (deviceIdentifier.IndexOf(adapterPnpId.Replace('\\', '#'), StringComparison.OrdinalIgnoreCase) != -1)
|
||||
isMatch = true;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignored.
|
||||
}
|
||||
|
||||
if (!isMatch)
|
||||
{
|
||||
try
|
||||
{
|
||||
string path = deviceIdentifier;
|
||||
if (path.StartsWith(@"\\?\"))
|
||||
path = path.Substring(4);
|
||||
|
||||
path = path.Replace('#', '\\');
|
||||
int index = path.IndexOf('{');
|
||||
if (index != -1)
|
||||
path = path.Substring(0, index);
|
||||
|
||||
path = @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\" + path;
|
||||
|
||||
if (Registry.GetValue(path, "LocationInformation", null) is string locationInformation)
|
||||
{
|
||||
// For example:
|
||||
// @System32\drivers\pci.sys,#65536;PCI bus %1, device %2, function %3;(38,0,0)
|
||||
|
||||
index = locationInformation.IndexOf('(');
|
||||
if (index != -1)
|
||||
{
|
||||
index++;
|
||||
int secondIndex = locationInformation.IndexOf(',', index);
|
||||
if (secondIndex != -1)
|
||||
{
|
||||
string bus = locationInformation.Substring(index, secondIndex - index);
|
||||
|
||||
if (pci.bus.ToString() == bus)
|
||||
isMatch = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignored.
|
||||
}
|
||||
}
|
||||
|
||||
if (isMatch && D3DDisplayDevice.GetDeviceInfoByIdentifier(deviceIdentifier, out D3DDisplayDevice.D3DDeviceInfo deviceInfo))
|
||||
{
|
||||
_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);
|
||||
|
||||
_gpuNodeUsage = new Sensor[deviceInfo.Nodes.Length];
|
||||
_gpuNodeUsagePrevValue = new long[deviceInfo.Nodes.Length];
|
||||
_gpuNodeUsagePrevTick = new DateTime[deviceInfo.Nodes.Length];
|
||||
|
||||
foreach (D3DDisplayDevice.D3DDeviceNodeInfo node in deviceInfo.Nodes)
|
||||
{
|
||||
_gpuNodeUsage[node.Id] = new Sensor(node.Name, _nodeSensorIndex++, SensorType.Load, this, settings);
|
||||
_gpuNodeUsagePrevValue[node.Id] = node.RunningTime;
|
||||
_gpuNodeUsagePrevTick[node.Id] = node.QueryTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +247,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
private NvApi.NvGPUThermalSettings GetThermalSettings()
|
||||
{
|
||||
NvApi.NvGPUThermalSettings settings = new NvApi.NvGPUThermalSettings
|
||||
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]
|
||||
};
|
||||
@@ -170,7 +274,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
private NvApi.NvGPUCoolerSettings GetCoolerSettings()
|
||||
{
|
||||
NvApi.NvGPUCoolerSettings settings = new NvApi.NvGPUCoolerSettings { Version = NvApi.GPU_COOLER_SETTINGS_VER, Cooler = new NvApi.NvCooler[NvApi.MAX_COOLER_PER_GPU] };
|
||||
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;
|
||||
@@ -181,7 +285,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
private uint[] GetClocks()
|
||||
{
|
||||
NvApi.NvClocks allClocks = new NvApi.NvClocks { Version = NvApi.GPU_CLOCKS_VER, Clock = new uint[NvApi.MAX_CLOCKS_PER_GPU] };
|
||||
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;
|
||||
@@ -192,6 +296,25 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
if (_windowsDeviceName != null && D3DDisplayDevice.GetDeviceInfoByIdentifier(_windowsDeviceName, out D3DDisplayDevice.D3DDeviceInfo deviceInfo))
|
||||
{
|
||||
_gpuDedicatedMemoryUsage.Value = 1f * deviceInfo.GpuDedicatedUsed / 1024 / 1024;
|
||||
_gpuSharedMemoryUsage.Value = 1f * deviceInfo.GpuSharedUsed / 1024 / 1024;
|
||||
ActivateSensor(_gpuDedicatedMemoryUsage);
|
||||
ActivateSensor(_gpuSharedMemoryUsage);
|
||||
|
||||
foreach (D3DDisplayDevice.D3DDeviceNodeInfo node in deviceInfo.Nodes)
|
||||
{
|
||||
long runningTimeDiff = node.RunningTime - _gpuNodeUsagePrevValue[node.Id];
|
||||
long timeDiff = node.QueryTime.Ticks - _gpuNodeUsagePrevTick[node.Id].Ticks;
|
||||
|
||||
_gpuNodeUsage[node.Id].Value = 100f * runningTimeDiff / timeDiff;
|
||||
_gpuNodeUsagePrevValue[node.Id] = node.RunningTime;
|
||||
_gpuNodeUsagePrevTick[node.Id] = node.QueryTime;
|
||||
ActivateSensor(_gpuNodeUsage[node.Id]);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -228,7 +351,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
}
|
||||
}
|
||||
|
||||
NvApi.NvPStates states = new NvApi.NvPStates { Version = NvApi.GPU_PSTATES_VER, PStates = new NvApi.NvPState[NvApi.MAX_PSTATES_PER_GPU] };
|
||||
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++)
|
||||
@@ -242,7 +365,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
}
|
||||
else
|
||||
{
|
||||
NvApi.NvUsages usages = new NvApi.NvUsages { Version = NvApi.GPU_USAGES_VER, Usage = new uint[NvApi.MAX_USAGES_PER_GPU] };
|
||||
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)
|
||||
{
|
||||
_loads[0].Value = usages.Usage[2];
|
||||
@@ -282,7 +405,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
}
|
||||
}
|
||||
|
||||
NvApi.NvMemoryInfo memoryInfo = new NvApi.NvMemoryInfo { Version = NvApi.GPU_MEMORY_INFO_VER, Values = new uint[NvApi.MAX_MEMORY_VALUES_PER_GPU] };
|
||||
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)
|
||||
{
|
||||
uint totalMemory = memoryInfo.Values[0];
|
||||
@@ -326,7 +449,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
public override string GetReport()
|
||||
{
|
||||
StringBuilder r = new StringBuilder();
|
||||
StringBuilder r = new();
|
||||
|
||||
r.AppendLine("Nvidia GPU");
|
||||
r.AppendLine();
|
||||
@@ -335,7 +458,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
if (_displayHandle.HasValue && NvApi.NvAPI_GetDisplayDriverVersion != null)
|
||||
{
|
||||
NvApi.NvDisplayDriverVersion driverVersion = new NvApi.NvDisplayDriverVersion { Version = NvApi.DISPLAY_DRIVER_VERSION_VER };
|
||||
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: ");
|
||||
@@ -369,7 +492,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
if (NvApi.NvAPI_GPU_GetThermalSettings != null)
|
||||
{
|
||||
NvApi.NvGPUThermalSettings settings = new NvApi.NvGPUThermalSettings
|
||||
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]
|
||||
};
|
||||
@@ -399,7 +522,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
if (NvApi.NvAPI_GPU_GetAllClocks != null)
|
||||
{
|
||||
NvApi.NvClocks allClocks = new NvApi.NvClocks { Version = NvApi.GPU_CLOCKS_VER, Clock = new uint[NvApi.MAX_CLOCKS_PER_GPU] };
|
||||
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);
|
||||
|
||||
r.AppendLine("Clocks");
|
||||
@@ -442,7 +565,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
if (NvApi.NvAPI_GPU_GetPStates != null)
|
||||
{
|
||||
NvApi.NvPStates states = new NvApi.NvPStates { Version = NvApi.GPU_PSTATES_VER, PStates = new NvApi.NvPState[NvApi.MAX_PSTATES_PER_GPU] };
|
||||
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");
|
||||
@@ -466,7 +589,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
if (NvApi.NvAPI_GPU_GetUsages != null)
|
||||
{
|
||||
NvApi.NvUsages usages = new NvApi.NvUsages { Version = NvApi.GPU_USAGES_VER, Usage = new uint[NvApi.MAX_USAGES_PER_GPU] };
|
||||
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);
|
||||
|
||||
r.AppendLine("Usages");
|
||||
@@ -490,7 +613,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
if (NvApi.NvAPI_GPU_GetCoolerSettings != null)
|
||||
{
|
||||
NvApi.NvGPUCoolerSettings settings = new NvApi.NvGPUCoolerSettings { Version = NvApi.GPU_COOLER_SETTINGS_VER, Cooler = new NvApi.NvCooler[NvApi.MAX_COOLER_PER_GPU] };
|
||||
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();
|
||||
@@ -523,11 +646,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
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]
|
||||
};
|
||||
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);
|
||||
|
||||
@@ -537,16 +656,30 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
{
|
||||
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);
|
||||
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
|
||||
@@ -554,12 +687,13 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
r.Append(" Status: ");
|
||||
r.AppendLine(status.ToString());
|
||||
}
|
||||
|
||||
r.AppendLine();
|
||||
}
|
||||
|
||||
if (NvApi.NvAPI_GPU_GetMemoryInfo != null && _displayHandle.HasValue)
|
||||
{
|
||||
NvApi.NvMemoryInfo memoryInfo = new NvApi.NvMemoryInfo { Version = NvApi.GPU_MEMORY_INFO_VER, Values = new uint[NvApi.MAX_MEMORY_VALUES_PER_GPU] };
|
||||
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);
|
||||
|
||||
r.AppendLine("Memory Info");
|
||||
@@ -583,7 +717,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
private void SoftwareControlValueChanged(IControl control)
|
||||
{
|
||||
NvApi.NvGPUCoolerLevels coolerLevels = new NvApi.NvGPUCoolerLevels { Version = NvApi.GPU_COOLER_LEVELS_VER, Levels = new NvApi.NvLevel[NvApi.MAX_COOLER_PER_GPU] };
|
||||
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);
|
||||
@@ -608,7 +742,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
|
||||
private void SetDefaultFanSpeed()
|
||||
{
|
||||
NvApi.NvGPUCoolerLevels coolerLevels = new NvApi.NvGPUCoolerLevels { Version = NvApi.GPU_COOLER_LEVELS_VER, Levels = new NvApi.NvLevel[NvApi.MAX_COOLER_PER_GPU] };
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
{
|
||||
internal class NvidiaGroup : IGroup
|
||||
{
|
||||
private readonly List<Hardware> _hardware = new List<Hardware>();
|
||||
private readonly StringBuilder _report = new StringBuilder();
|
||||
private readonly List<Hardware> _hardware = new();
|
||||
private readonly StringBuilder _report = new();
|
||||
|
||||
public NvidiaGroup(ISettings settings)
|
||||
{
|
||||
@@ -54,7 +54,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
||||
int i = 0;
|
||||
while (status == NvApi.NvStatus.OK)
|
||||
{
|
||||
NvApi.NvDisplayHandle displayHandle = new NvApi.NvDisplayHandle();
|
||||
NvApi.NvDisplayHandle displayHandle = new();
|
||||
status = NvApi.NvAPI_EnumNvidiaDisplayHandle(i, ref displayHandle);
|
||||
i++;
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// 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.
|
||||
|
||||
// ReSharper disable IdentifierTypo
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibreHardwareMonitor.Interop
|
||||
{
|
||||
internal static class CfgMgr32
|
||||
{
|
||||
internal const uint CM_GET_DEVICE_INTERFACE_LIST_PRESENT = 0;
|
||||
internal const int CR_SUCCESS = 0;
|
||||
internal static Guid GUID_DISPLAY_DEVICE_ARRIVAL = new("1CA05180-A699-450A-9A0C-DE4FBE3DDD89");
|
||||
|
||||
internal const string DllName = "CfgMgr32.dll";
|
||||
|
||||
[DllImport(DllName, CharSet = CharSet.Unicode)]
|
||||
internal static extern uint CM_Get_Device_Interface_List_Size(out uint size, ref Guid interfaceClassGuid, string deviceID, uint flags);
|
||||
|
||||
[DllImport(DllName, CharSet = CharSet.Unicode)]
|
||||
internal static extern uint CM_Get_Device_Interface_List(ref Guid interfaceClassGuid, string deviceID, char[] buffer, uint bufferLength, uint flags);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// 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.
|
||||
|
||||
// ReSharper disable IdentifierTypo
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibreHardwareMonitor.Interop
|
||||
{
|
||||
internal static class D3dkmdt
|
||||
{
|
||||
internal enum DXGK_ENGINE_TYPE
|
||||
{
|
||||
DXGK_ENGINE_TYPE_OTHER = 0,
|
||||
DXGK_ENGINE_TYPE_3D = 1,
|
||||
DXGK_ENGINE_TYPE_VIDEO_DECODE = 2,
|
||||
DXGK_ENGINE_TYPE_VIDEO_ENCODE = 3,
|
||||
DXGK_ENGINE_TYPE_VIDEO_PROCESSING = 4,
|
||||
DXGK_ENGINE_TYPE_SCENE_ASSEMBLY = 5,
|
||||
DXGK_ENGINE_TYPE_COPY = 6,
|
||||
DXGK_ENGINE_TYPE_OVERLAY = 7,
|
||||
DXGK_ENGINE_TYPE_CRYPTO,
|
||||
DXGK_ENGINE_TYPE_MAX
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct DXGK_NODEMETADATA_FLAGS
|
||||
{
|
||||
public uint Value;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)]
|
||||
internal struct DXGK_NODEMETADATA
|
||||
{
|
||||
public DXGK_ENGINE_TYPE EngineType;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
|
||||
public string FriendlyName;
|
||||
|
||||
public DXGK_NODEMETADATA_FLAGS Flags;
|
||||
public byte GpuMmuSupported;
|
||||
public byte IoMmuSupported;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,563 @@
|
||||
// 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.
|
||||
|
||||
// ReSharper disable IdentifierTypo
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibreHardwareMonitor.Interop
|
||||
{
|
||||
internal static class D3dkmth
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_CLOSEADAPTER
|
||||
{
|
||||
public uint hAdapter;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYADAPTERINFO
|
||||
{
|
||||
public uint hAdapter;
|
||||
public KMTQUERYADAPTERINFOTYPE Type;
|
||||
public IntPtr pPrivateDriverData;
|
||||
public int PrivateDriverDataSize;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_OPENADAPTERFROMDEVICENAME
|
||||
{
|
||||
[MarshalAs(UnmanagedType.LPWStr)]
|
||||
public string pDeviceName;
|
||||
|
||||
public uint hAdapter;
|
||||
public WinNt.LUID AdapterLuid;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_ADAPTERTYPE
|
||||
{
|
||||
public D3DKMT_ADAPTERTYPE_FLAGS Value;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_QUERY_SEGMENT
|
||||
{
|
||||
public uint SegmentId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_QUERY_NODE
|
||||
{
|
||||
public uint NodeId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_QUERY_VIDPNSOURCE
|
||||
{
|
||||
public uint VidPnSourceId;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_REFERENCE_DMA_BUFFER
|
||||
{
|
||||
public uint NbCall;
|
||||
public uint NbAllocationsReferenced;
|
||||
public uint MaxNbAllocationsReferenced;
|
||||
public uint NbNULLReference;
|
||||
public uint NbWriteReference;
|
||||
public uint NbRenamedAllocationsReferenced;
|
||||
public uint NbIterationSearchingRenamedAllocation;
|
||||
public uint NbLockedAllocationReferenced;
|
||||
public uint NbAllocationWithValidPrepatchingInfoReferenced;
|
||||
public uint NbAllocationWithInvalidPrepatchingInfoReferenced;
|
||||
public uint NbDMABufferSuccessfullyPrePatched;
|
||||
public uint NbPrimariesReferencesOverflow;
|
||||
public uint NbAllocationWithNonPreferredResources;
|
||||
public uint NbAllocationInsertedInMigrationTable;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_SEGMENTSIZEINFO
|
||||
{
|
||||
public ulong DedicatedVideoMemorySize;
|
||||
public ulong DedicatedSystemMemorySize;
|
||||
public ulong SharedSystemMemorySize;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_RENAMING
|
||||
{
|
||||
public uint NbAllocationsRenamed;
|
||||
public uint NbAllocationsShrinked;
|
||||
public uint NbRenamedBuffer;
|
||||
public uint MaxRenamingListLength;
|
||||
public uint NbFailuresDueToRenamingLimit;
|
||||
public uint NbFailuresDueToCreateAllocation;
|
||||
public uint NbFailuresDueToOpenAllocation;
|
||||
public uint NbFailuresDueToLowResource;
|
||||
public uint NbFailuresDueToNonRetiredLimit;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_COUNTER
|
||||
{
|
||||
public uint Count;
|
||||
public ulong Bytes;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_PREPRATION
|
||||
{
|
||||
public uint BroadcastStall;
|
||||
public uint NbDMAPrepared;
|
||||
public uint NbDMAPreparedLongPath;
|
||||
public uint ImmediateHighestPreparationPass;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER AllocationsTrimmed;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_PAGING_FAULT
|
||||
{
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER Faults;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER FaultsFirstTimeAccess;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER FaultsReclaimed;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER FaultsMigration;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER FaultsIncorrectResource;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER FaultsLostContent;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER FaultsEvicted;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER AllocationsMEM_RESET;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER AllocationsUnresetSuccess;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER AllocationsUnresetFail;
|
||||
|
||||
public uint AllocationsUnresetSuccessRead;
|
||||
public uint AllocationsUnresetFailRead;
|
||||
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER Evictions;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER EvictionsDueToPreparation;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER EvictionsDueToLock;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER EvictionsDueToClose;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER EvictionsDueToPurge;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER EvictionsDueToSuspendCPUAccess;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_PAGING_TRANSFER
|
||||
{
|
||||
public ulong BytesFilled;
|
||||
public ulong BytesDiscarded;
|
||||
public ulong BytesMappedIntoAperture;
|
||||
public ulong BytesUnmappedFromAperture;
|
||||
public ulong BytesTransferredFromMdlToMemory;
|
||||
public ulong BytesTransferredFromMemoryToMdl;
|
||||
public ulong BytesTransferredFromApertureToMemory;
|
||||
public ulong BytesTransferredFromMemoryToAperture;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_SWIZZLING_RANGE
|
||||
{
|
||||
public uint NbRangesAcquired;
|
||||
public uint NbRangesReleased;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_LOCKS
|
||||
{
|
||||
public uint NbLocks;
|
||||
public uint NbLocksWaitFlag;
|
||||
public uint NbLocksDiscardFlag;
|
||||
public uint NbLocksNoOverwrite;
|
||||
public uint NbLocksNoReadSync;
|
||||
public uint NbLocksLinearization;
|
||||
public uint NbComplexLocks;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_ALLOCATIONS
|
||||
{
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER Created;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER Destroyed;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER Opened;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER Closed;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER MigratedSuccess;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER MigratedFail;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER MigratedAbandoned;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_TERMINATIONS
|
||||
{
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER TerminatedShared;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER TerminatedNonShared;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER DestroyedShared;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER DestroyedNonShared;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_ADAPTER_INFORMATION
|
||||
{
|
||||
public uint NbSegments;
|
||||
public uint NodeCount;
|
||||
public uint VidPnSourceCount;
|
||||
|
||||
public uint VSyncEnabled;
|
||||
public uint TdrDetectedCount;
|
||||
|
||||
public long ZeroLengthDmaBuffers;
|
||||
public ulong RestartedPeriod;
|
||||
|
||||
public D3DKMT_QUERYSTATISTICS_REFERENCE_DMA_BUFFER ReferenceDmaBuffer;
|
||||
public D3DKMT_QUERYSTATISTICS_RENAMING Renaming;
|
||||
public D3DKMT_QUERYSTATISTICS_PREPRATION Preparation;
|
||||
public D3DKMT_QUERYSTATISTICS_PAGING_FAULT PagingFault;
|
||||
public D3DKMT_QUERYSTATISTICS_PAGING_TRANSFER PagingTransfer;
|
||||
public D3DKMT_QUERYSTATISTICS_SWIZZLING_RANGE SwizzlingRange;
|
||||
public D3DKMT_QUERYSTATISTICS_LOCKS Locks;
|
||||
public D3DKMT_QUERYSTATISTICS_ALLOCATIONS Allocations;
|
||||
public D3DKMT_QUERYSTATISTICS_TERMINATIONS Terminations;
|
||||
|
||||
private readonly ulong Reserved;
|
||||
private readonly ulong Reserved1;
|
||||
private readonly ulong Reserved2;
|
||||
private readonly ulong Reserved3;
|
||||
private readonly ulong Reserved4;
|
||||
private readonly ulong Reserved5;
|
||||
private readonly ulong Reserved6;
|
||||
private readonly ulong Reserved7;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_MEMORY
|
||||
{
|
||||
public ulong TotalBytesEvicted;
|
||||
public uint AllocsCommitted;
|
||||
public uint AllocsResident;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct D3DKMT_QUERYSTATISTICS_SEGMENT_INFORMATION
|
||||
{
|
||||
public ulong CommitLimit;
|
||||
public ulong BytesCommitted;
|
||||
public ulong BytesResident;
|
||||
public D3DKMT_QUERYSTATISTICS_MEMORY Memory;
|
||||
public uint Aperture; // boolean
|
||||
public fixed ulong TotalBytesEvictedByPriority[5]; // D3DKMT_QUERYSTATISTICS_SEGMENT_PREFERENCE_MAX
|
||||
public ulong SystemMemoryEndAddress;
|
||||
public D3DKMT_QUERYSTATISTICS_SEGMENT_INFORMATION_POWER_FLAGS PowerFlags;
|
||||
public fixed ulong Reserved[6];
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_SEGMENT_INFORMATION_POWER_FLAGS
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public ulong PreservedDuringStandby;
|
||||
|
||||
[FieldOffset(1)]
|
||||
public ulong PreservedDuringHibernate;
|
||||
|
||||
[FieldOffset(2)]
|
||||
public ulong PartiallyPreservedDuringHibernate;
|
||||
|
||||
[FieldOffset(3)]
|
||||
public ulong Reserved;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_VIDEO_MEMORY
|
||||
{
|
||||
public uint AllocsCommitted;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER AllocsResidentIn0;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER AllocsResidentIn1;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER AllocsResidentIn2;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER AllocsResidentIn3;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER AllocsResidentIn4;
|
||||
public D3DKMT_QUERYSTATISTICS_COUNTER AllocsResidentInNonPreferred;
|
||||
public ulong TotalBytesEvictedDueToPreparation;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_PROCESS_SEGMENT_POLICY
|
||||
{
|
||||
public ulong UseMRU;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct D3DKMT_QUERYSTATISTICS_PROCESS_SEGMENT_INFORMATION
|
||||
{
|
||||
public ulong BytesCommitted;
|
||||
public ulong MaximumWorkingSet;
|
||||
public ulong MinimumWorkingSet;
|
||||
|
||||
public uint NbReferencedAllocationEvictedInPeriod;
|
||||
|
||||
public D3DKMT_QUERYSTATISTICS_VIDEO_MEMORY VideoMemory;
|
||||
public D3DKMT_QUERYSTATISTICS_PROCESS_SEGMENT_POLICY _Policy;
|
||||
|
||||
public fixed ulong Reserved[8];
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_PREEMPTION_INFORMATION
|
||||
{
|
||||
public uint PreemptionCounter;
|
||||
public uint PreemptionCounter1;
|
||||
public uint PreemptionCounter2;
|
||||
public uint PreemptionCounter3;
|
||||
public uint PreemptionCounter4;
|
||||
public uint PreemptionCounter5;
|
||||
public uint PreemptionCounter6;
|
||||
public uint PreemptionCounter7;
|
||||
public uint PreemptionCounter8;
|
||||
public uint PreemptionCounter9;
|
||||
public uint PreemptionCounter10;
|
||||
public uint PreemptionCounter11;
|
||||
public uint PreemptionCounter12;
|
||||
public uint PreemptionCounter13;
|
||||
public uint PreemptionCounter14;
|
||||
public uint PreemptionCounter15;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct D3DKMT_QUERYSTATISTICS_PROCESS_NODE_INFORMATION
|
||||
{
|
||||
public WinNt.LARGE_INTEGER RunningTime; // 100ns
|
||||
public uint ContextSwitch;
|
||||
readonly D3DKMT_QUERYSTATISTICS_PREEMPTION_INFORMATION PreemptionStatistics;
|
||||
readonly D3DKMT_QUERYSTATISTICS_PACKET_INFORMATION PacketStatistics;
|
||||
private fixed ulong Reserved[8];
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct D3DKMT_QUERYSTATISTICS_NODE_INFORMATION
|
||||
{
|
||||
public D3DKMT_QUERYSTATISTICS_PROCESS_NODE_INFORMATION GlobalInformation; // global
|
||||
|
||||
public D3DKMT_QUERYSTATISTICS_PROCESS_NODE_INFORMATION SystemInformation; // system thread
|
||||
|
||||
//public UInt32 NodeId; // Win10
|
||||
public fixed ulong Reserved[8];
|
||||
}
|
||||
|
||||
internal struct D3DKMT_QUERYSTATISTICS_DMA_PACKET_TYPE_INFORMATION
|
||||
{
|
||||
public uint PacketSubmitted;
|
||||
public uint PacketCompleted;
|
||||
public uint PacketPreempted;
|
||||
public uint PacketFaulted;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_QUEUE_PACKET_TYPE_INFORMATION
|
||||
{
|
||||
public uint PacketSubmited;
|
||||
public uint PacketCompleted;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_PACKET_INFORMATION
|
||||
{
|
||||
public D3DKMT_QUERYSTATISTICS_QUEUE_PACKET_TYPE_INFORMATION QueuePacket;
|
||||
public D3DKMT_QUERYSTATISTICS_QUEUE_PACKET_TYPE_INFORMATION QueuePacket1;
|
||||
public D3DKMT_QUERYSTATISTICS_QUEUE_PACKET_TYPE_INFORMATION QueuePacket2;
|
||||
public D3DKMT_QUERYSTATISTICS_QUEUE_PACKET_TYPE_INFORMATION QueuePacket3;
|
||||
public D3DKMT_QUERYSTATISTICS_QUEUE_PACKET_TYPE_INFORMATION QueuePacket4;
|
||||
public D3DKMT_QUERYSTATISTICS_QUEUE_PACKET_TYPE_INFORMATION QueuePacket5;
|
||||
public D3DKMT_QUERYSTATISTICS_QUEUE_PACKET_TYPE_INFORMATION QueuePacket6;
|
||||
public D3DKMT_QUERYSTATISTICS_QUEUE_PACKET_TYPE_INFORMATION QueuePacket7;
|
||||
|
||||
public D3DKMT_QUERYSTATISTICS_DMA_PACKET_TYPE_INFORMATION DmaPacket;
|
||||
public D3DKMT_QUERYSTATISTICS_DMA_PACKET_TYPE_INFORMATION DmaPacket1;
|
||||
public D3DKMT_QUERYSTATISTICS_DMA_PACKET_TYPE_INFORMATION DmaPacket2;
|
||||
public D3DKMT_QUERYSTATISTICS_DMA_PACKET_TYPE_INFORMATION DmaPacket3;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_RESULT
|
||||
{
|
||||
[FieldOffset(8)]
|
||||
public D3DKMT_QUERYSTATISTICS_ADAPTER_INFORMATION AdapterInformation;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public D3DKMT_QUERYSTATISTICS_SEGMENT_INFORMATION SegmentInformation;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public D3DKMT_QUERYSTATISTICS_PROCESS_SEGMENT_INFORMATION ProcessSegmentInformation;
|
||||
|
||||
[FieldOffset(8)]
|
||||
public D3DKMT_QUERYSTATISTICS_NODE_INFORMATION NodeInformation;
|
||||
|
||||
// D3DKMT_QUERYSTATISTICS_PROCESS_INFORMATION ProcessInformation;
|
||||
// D3DKMT_QUERYSTATISTICS_PROCESS_NODE_INFORMATION ProcessNodeInformation;
|
||||
// D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER_INFORMATION PhysAdapterInformation;
|
||||
// D3DKMT_QUERYSTATISTICS_SEGMENT_INFORMATION_V1 SegmentInformationV1; // WIN7
|
||||
// D3DKMT_QUERYSTATISTICS_VIDPNSOURCE_INFORMATION VidPnSourceInformation;
|
||||
// D3DKMT_QUERYSTATISTICS_PROCESS_ADAPTER_INFORMATION ProcessAdapterInformation;
|
||||
// D3DKMT_QUERYSTATISTICS_PROCESS_VIDPNSOURCE_INFORMATION ProcessVidPnSourceInformation;
|
||||
// D3DKMT_QUERYSTATISTICS_PROCESS_SEGMENT_GROUP_INFORMATION ProcessSegmentGroupInformation;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS_QUERY_ELEMENT
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public D3DKMT_QUERYSTATISTICS_QUERY_SEGMENT QuerySegment;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public D3DKMT_QUERYSTATISTICS_QUERY_SEGMENT QueryProcessSegment;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public D3DKMT_QUERYSTATISTICS_QUERY_NODE QueryNode;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public D3DKMT_QUERYSTATISTICS_QUERY_NODE QueryProcessNode;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public D3DKMT_QUERYSTATISTICS_QUERY_VIDPNSOURCE QueryVidPnSource;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public D3DKMT_QUERYSTATISTICS_QUERY_VIDPNSOURCE QueryProcessVidPnSource;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct D3DKMT_QUERYSTATISTICS
|
||||
{
|
||||
public D3DKMT_QUERYSTATISTICS_TYPE Type;
|
||||
public WinNt.LUID AdapterLuid;
|
||||
public uint ProcessHandle;
|
||||
public D3DKMT_QUERYSTATISTICS_RESULT QueryResult;
|
||||
public D3DKMT_QUERYSTATISTICS_QUERY_ELEMENT QueryElement;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
internal struct D3DKMT_NODEMETADATA
|
||||
{
|
||||
public uint NodeOrdinalAndAdapterIndex;
|
||||
public D3dkmdt.DXGK_NODEMETADATA NodeData;
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum D3DKMT_ADAPTERTYPE_FLAGS : uint
|
||||
{
|
||||
RenderSupported = 0,
|
||||
DisplaySupported = 1,
|
||||
SoftwareDevice = 2,
|
||||
PostDevice = 4,
|
||||
HybridDiscrete = 8,
|
||||
HybridIntegrated = 16,
|
||||
IndirectDisplayDevice = 32,
|
||||
Paravirtualized = 64,
|
||||
ACGSupported = 128,
|
||||
SupportSetTimingsFromVidPn = 256,
|
||||
Detachable = 512,
|
||||
ComputeOnly = 1024,
|
||||
Prototype = 2045
|
||||
}
|
||||
|
||||
internal enum D3DKMT_QUERYSTATISTICS_TYPE
|
||||
{
|
||||
D3DKMT_QUERYSTATISTICS_ADAPTER,
|
||||
D3DKMT_QUERYSTATISTICS_PROCESS,
|
||||
D3DKMT_QUERYSTATISTICS_PROCESS_ADAPTER,
|
||||
D3DKMT_QUERYSTATISTICS_SEGMENT,
|
||||
D3DKMT_QUERYSTATISTICS_PROCESS_SEGMENT,
|
||||
D3DKMT_QUERYSTATISTICS_NODE,
|
||||
D3DKMT_QUERYSTATISTICS_PROCESS_NODE,
|
||||
D3DKMT_QUERYSTATISTICS_VIDPNSOURCE,
|
||||
D3DKMT_QUERYSTATISTICS_PROCESS_VIDPNSOURCE,
|
||||
D3DKMT_QUERYSTATISTICS_PROCESS_SEGMENT_GROUP,
|
||||
D3DKMT_QUERYSTATISTICS_PHYSICAL_ADAPTER
|
||||
}
|
||||
|
||||
internal enum D3DKMT_QUERYSTATISTICS_DMA_PACKET_TYPE
|
||||
{
|
||||
D3DKMT_ClientRenderBuffer = 0,
|
||||
D3DKMT_ClientPagingBuffer = 1,
|
||||
D3DKMT_SystemPagingBuffer = 2,
|
||||
D3DKMT_SystemPreemptionBuffer = 3,
|
||||
D3DKMT_DmaPacketTypeMax
|
||||
}
|
||||
|
||||
internal enum KMTQUERYADAPTERINFOTYPE
|
||||
{
|
||||
KMTQAITYPE_UMDRIVERPRIVATE = 0,
|
||||
KMTQAITYPE_UMDRIVERNAME = 1,
|
||||
KMTQAITYPE_UMOPENGLINFO = 2,
|
||||
KMTQAITYPE_GETSEGMENTSIZE = 3,
|
||||
KMTQAITYPE_ADAPTERGUID = 4,
|
||||
KMTQAITYPE_FLIPQUEUEINFO = 5,
|
||||
KMTQAITYPE_ADAPTERADDRESS = 6,
|
||||
KMTQAITYPE_SETWORKINGSETINFO = 7,
|
||||
KMTQAITYPE_ADAPTERREGISTRYINFO = 8,
|
||||
KMTQAITYPE_CURRENTDISPLAYMODE = 9,
|
||||
KMTQAITYPE_MODELIST = 10,
|
||||
KMTQAITYPE_CHECKDRIVERUPDATESTATUS = 11,
|
||||
KMTQAITYPE_VIRTUALADDRESSINFO = 12,
|
||||
KMTQAITYPE_DRIVERVERSION = 13,
|
||||
KMTQAITYPE_ADAPTERTYPE = 15,
|
||||
KMTQAITYPE_OUTPUTDUPLCONTEXTSCOUNT = 16,
|
||||
KMTQAITYPE_WDDM_1_2_CAPS = 17,
|
||||
KMTQAITYPE_UMD_DRIVER_VERSION = 18,
|
||||
KMTQAITYPE_DIRECTFLIP_SUPPORT = 19,
|
||||
KMTQAITYPE_MULTIPLANEOVERLAY_SUPPORT = 20,
|
||||
KMTQAITYPE_DLIST_DRIVER_NAME = 21,
|
||||
KMTQAITYPE_WDDM_1_3_CAPS = 22,
|
||||
KMTQAITYPE_MULTIPLANEOVERLAY_HUD_SUPPORT = 23,
|
||||
KMTQAITYPE_WDDM_2_0_CAPS = 24,
|
||||
KMTQAITYPE_NODEMETADATA = 25,
|
||||
KMTQAITYPE_CPDRIVERNAME = 26,
|
||||
KMTQAITYPE_XBOX = 27,
|
||||
KMTQAITYPE_INDEPENDENTFLIP_SUPPORT = 28,
|
||||
KMTQAITYPE_MIRACASTCOMPANIONDRIVERNAME = 29,
|
||||
KMTQAITYPE_PHYSICALADAPTERCOUNT = 30,
|
||||
KMTQAITYPE_PHYSICALADAPTERDEVICEIDS = 31,
|
||||
KMTQAITYPE_DRIVERCAPS_EXT = 32,
|
||||
KMTQAITYPE_QUERY_MIRACAST_DRIVER_TYPE = 33,
|
||||
KMTQAITYPE_QUERY_GPUMMU_CAPS = 34,
|
||||
KMTQAITYPE_QUERY_MULTIPLANEOVERLAY_DECODE_SUPPORT = 35,
|
||||
KMTQAITYPE_QUERY_HW_PROTECTION_TEARDOWN_COUNT = 36,
|
||||
KMTQAITYPE_QUERY_ISBADDRIVERFORHWPROTECTIONDISABLED = 37,
|
||||
KMTQAITYPE_MULTIPLANEOVERLAY_SECONDARY_SUPPORT = 38,
|
||||
KMTQAITYPE_INDEPENDENTFLIP_SECONDARY_SUPPORT = 39,
|
||||
KMTQAITYPE_PANELFITTER_SUPPORT = 40,
|
||||
KMTQAITYPE_PHYSICALADAPTERPNPKEY = 41,
|
||||
KMTQAITYPE_GETSEGMENTGROUPSIZE = 42,
|
||||
KMTQAITYPE_MPO3DDI_SUPPORT = 43,
|
||||
KMTQAITYPE_HWDRM_SUPPORT = 44,
|
||||
KMTQAITYPE_MPOKERNELCAPS_SUPPORT = 45,
|
||||
KMTQAITYPE_MULTIPLANEOVERLAY_STRETCH_SUPPORT = 46,
|
||||
KMTQAITYPE_GET_DEVICE_VIDPN_OWNERSHIP_INFO = 47,
|
||||
KMTQAITYPE_QUERYREGISTRY = 48,
|
||||
KMTQAITYPE_KMD_DRIVER_VERSION = 49,
|
||||
KMTQAITYPE_BLOCKLIST_KERNEL = 50,
|
||||
KMTQAITYPE_BLOCKLIST_RUNTIME = 51,
|
||||
KMTQAITYPE_ADAPTERGUID_RENDER = 52,
|
||||
KMTQAITYPE_ADAPTERADDRESS_RENDER = 53,
|
||||
KMTQAITYPE_ADAPTERREGISTRYINFO_RENDER = 54,
|
||||
KMTQAITYPE_CHECKDRIVERUPDATESTATUS_RENDER = 55,
|
||||
KMTQAITYPE_DRIVERVERSION_RENDER = 56,
|
||||
KMTQAITYPE_ADAPTERTYPE_RENDER = 57,
|
||||
KMTQAITYPE_WDDM_1_2_CAPS_RENDER = 58,
|
||||
KMTQAITYPE_WDDM_1_3_CAPS_RENDER = 59,
|
||||
KMTQAITYPE_QUERY_ADAPTER_UNIQUE_GUID = 60,
|
||||
KMTQAITYPE_NODEPERFDATA = 61,
|
||||
KMTQAITYPE_ADAPTERPERFDATA = 62,
|
||||
KMTQAITYPE_ADAPTERPERFDATA_CAPS = 63,
|
||||
KMTQUITYPE_GPUVERSION = 64,
|
||||
KMTQAITYPE_DRIVER_DESCRIPTION = 65,
|
||||
KMTQAITYPE_DRIVER_DESCRIPTION_RENDER = 66,
|
||||
KMTQAITYPE_SCANOUT_CAPS = 67,
|
||||
KMTQAITYPE_DISPLAY_UMDRIVERNAME = 71,
|
||||
KMTQAITYPE_PARAVIRTUALIZATION_RENDER = 68,
|
||||
KMTQAITYPE_SERVICENAME = 69,
|
||||
KMTQAITYPE_WDDM_2_7_CAPS = 70,
|
||||
KMTQAITYPE_TRACKEDWORKLOAD_SUPPORT = 72,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// 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.
|
||||
|
||||
// ReSharper disable IdentifierTypo
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibreHardwareMonitor.Interop
|
||||
{
|
||||
internal static class Gdi32
|
||||
{
|
||||
internal const string DllName = "Gdi32.dll";
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true)]
|
||||
internal static extern uint D3DKMTCloseAdapter(ref D3dkmth.D3DKMT_CLOSEADAPTER closeAdapter);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true)]
|
||||
internal static extern uint D3DKMTOpenAdapterFromDeviceName(ref D3dkmth.D3DKMT_OPENADAPTERFROMDEVICENAME openAdapterFromDeviceName);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true)]
|
||||
internal static extern uint D3DKMTQueryAdapterInfo(ref D3dkmth.D3DKMT_QUERYADAPTERINFO queryAdapterInfo);
|
||||
|
||||
[DllImport(DllName, ExactSpelling = true)]
|
||||
internal static extern uint D3DKMTQueryStatistics(ref D3dkmth.D3DKMT_QUERYSTATISTICS queryStatistics);
|
||||
}
|
||||
}
|
||||
@@ -14,291 +14,25 @@ namespace LibreHardwareMonitor.Interop
|
||||
private const string LinuxDllName = "nvidia-ml";
|
||||
private const string WindowsDllName = "nvml.dll";
|
||||
|
||||
private static readonly object SyncRoot = new object();
|
||||
private static readonly object _syncRoot = new();
|
||||
|
||||
private static IntPtr _windowsDll;
|
||||
|
||||
private static WindowsNvmlGetHandleDelegate _windowsNvmlDeviceGetHandleByIndex;
|
||||
private static WindowsNvmlGetPowerUsageDelegate _windowsNvmlDeviceGetPowerUsage;
|
||||
private static WindowsNvmlDeviceGetPcieThroughputDelegate _windowsNvmlDeviceGetPcieThroughputDelegate;
|
||||
private static WindowsNvmlGetHandleByPciBusIdDelegate _windowsNvmlDeviceGetHandleByPciBusId;
|
||||
private static WindowsNvmlDeviceGetPcieThroughputDelegate _windowsNvmlDeviceGetPcieThroughputDelegate;
|
||||
private static WindowsNvmlGetPowerUsageDelegate _windowsNvmlDeviceGetPowerUsage;
|
||||
private static WindowsNvmlDeviceGetPciInfo _windowsNvmlDeviceGetPciInfo;
|
||||
private static WindowsNvmlDelegate _windowsNvmlInit;
|
||||
private static WindowsNvmlDelegate _windowsNvmlShutdown;
|
||||
|
||||
private static IntPtr WindowsDll;
|
||||
|
||||
internal static bool IsAvailable { get; private set; }
|
||||
|
||||
internal static bool Initialize()
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
if (IsAvailable)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
try
|
||||
{
|
||||
IsAvailable = nvmlInit() == NvmlReturn.Success;
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{ }
|
||||
catch (EntryPointNotFoundException)
|
||||
{
|
||||
try
|
||||
{
|
||||
IsAvailable = nvmlInitLegacy() == NvmlReturn.Success;
|
||||
}
|
||||
catch (EntryPointNotFoundException)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
else if (IsNvmlCompatibleWindowsVersion())
|
||||
{
|
||||
// Attempt to load the Nvidia Management Library from the
|
||||
// windows standard search order for applications. This will
|
||||
// help installations that either have the library in
|
||||
// %windir%/system32 or provide their own library
|
||||
WindowsDll = Kernel32.LoadLibrary(WindowsDllName);
|
||||
|
||||
// If there is no dll in the path, then attempt to load it
|
||||
// from program files
|
||||
if (WindowsDll == IntPtr.Zero)
|
||||
{
|
||||
string programFilesDirectory = Environment.ExpandEnvironmentVariables("%ProgramW6432%");
|
||||
string dllPath = Path.Combine(programFilesDirectory, @"NVIDIA Corporation\NVSMI", WindowsDllName);
|
||||
|
||||
WindowsDll = Kernel32.LoadLibrary(dllPath);
|
||||
}
|
||||
|
||||
IsAvailable = (WindowsDll != IntPtr.Zero)
|
||||
&& InitialiseDelegates()
|
||||
&& (_windowsNvmlInit() == NvmlReturn.Success);
|
||||
}
|
||||
|
||||
return IsAvailable;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsNvmlCompatibleWindowsVersion()
|
||||
{
|
||||
return Software.OperatingSystem.Is64Bit && ((Environment.OSVersion.Version.Major > 6) || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 1));
|
||||
}
|
||||
|
||||
private static bool InitialiseDelegates()
|
||||
{
|
||||
IntPtr nvmlInit = Kernel32.GetProcAddress(WindowsDll, "nvmlInit_v2");
|
||||
|
||||
if (nvmlInit != IntPtr.Zero)
|
||||
{
|
||||
_windowsNvmlInit = (WindowsNvmlDelegate)Marshal.GetDelegateForFunctionPointer(nvmlInit, typeof(WindowsNvmlDelegate));
|
||||
}
|
||||
else
|
||||
{
|
||||
nvmlInit = Kernel32.GetProcAddress(WindowsDll, "nvmlInit");
|
||||
if (nvmlInit != IntPtr.Zero)
|
||||
_windowsNvmlInit = (WindowsNvmlDelegate)Marshal.GetDelegateForFunctionPointer(nvmlInit, typeof(WindowsNvmlDelegate));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
IntPtr nvmlShutdown = Kernel32.GetProcAddress(WindowsDll, "nvmlShutdown");
|
||||
if (nvmlShutdown != IntPtr.Zero)
|
||||
_windowsNvmlShutdown = (WindowsNvmlDelegate)Marshal.GetDelegateForFunctionPointer(nvmlShutdown, typeof(WindowsNvmlDelegate));
|
||||
else
|
||||
return false;
|
||||
|
||||
|
||||
IntPtr nvmlGetHandle = Kernel32.GetProcAddress(WindowsDll, "nvmlDeviceGetHandleByIndex_v2");
|
||||
if (nvmlGetHandle != IntPtr.Zero)
|
||||
{
|
||||
_windowsNvmlDeviceGetHandleByIndex = (WindowsNvmlGetHandleDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetHandle, typeof(WindowsNvmlGetHandleDelegate));
|
||||
}
|
||||
else
|
||||
{
|
||||
nvmlGetHandle = Kernel32.GetProcAddress(WindowsDll, "nvmlDeviceGetHandleByIndex");
|
||||
if (nvmlGetHandle != IntPtr.Zero)
|
||||
_windowsNvmlDeviceGetHandleByIndex = (WindowsNvmlGetHandleDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetHandle, typeof(WindowsNvmlGetHandleDelegate));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
IntPtr nvmlGetPowerUsage = Kernel32.GetProcAddress(WindowsDll, "nvmlDeviceGetPowerUsage");
|
||||
if (nvmlGetPowerUsage != IntPtr.Zero)
|
||||
_windowsNvmlDeviceGetPowerUsage = (WindowsNvmlGetPowerUsageDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetPowerUsage, typeof(WindowsNvmlGetPowerUsageDelegate));
|
||||
else
|
||||
return false;
|
||||
|
||||
IntPtr nvmlGetPcieThroughput = Kernel32.GetProcAddress(WindowsDll, "nvmlDeviceGetPcieThroughput");
|
||||
if (nvmlGetPcieThroughput != IntPtr.Zero)
|
||||
_windowsNvmlDeviceGetPcieThroughputDelegate = (WindowsNvmlDeviceGetPcieThroughputDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetPcieThroughput, typeof(WindowsNvmlDeviceGetPcieThroughputDelegate));
|
||||
else
|
||||
return false;
|
||||
|
||||
IntPtr nvmlGetHandlePciBus = Kernel32.GetProcAddress(WindowsDll, "nvmlDeviceGetHandleByPciBusId_v2");
|
||||
if (nvmlGetHandlePciBus != IntPtr.Zero)
|
||||
_windowsNvmlDeviceGetHandleByPciBusId = (WindowsNvmlGetHandleByPciBusIdDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetHandlePciBus, typeof(WindowsNvmlGetHandleByPciBusIdDelegate));
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static void Close()
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
if (IsAvailable)
|
||||
{
|
||||
if (Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
nvmlShutdown();
|
||||
}
|
||||
else if (WindowsDll != IntPtr.Zero)
|
||||
{
|
||||
_windowsNvmlShutdown();
|
||||
Kernel32.FreeLibrary(WindowsDll);
|
||||
}
|
||||
|
||||
IsAvailable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static NvmlDevice? NvmlDeviceGetHandleByIndex(int index)
|
||||
{
|
||||
if (IsAvailable)
|
||||
{
|
||||
NvmlDevice nvmlDevice;
|
||||
if (Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (nvmlDeviceGetHandleByIndex(index, out nvmlDevice) == NvmlReturn.Success)
|
||||
return nvmlDevice;
|
||||
}
|
||||
catch (EntryPointNotFoundException)
|
||||
{
|
||||
if (nvmlDeviceGetHandleByIndexLegacy(index, out nvmlDevice) == NvmlReturn.Success)
|
||||
return nvmlDevice;
|
||||
}
|
||||
}
|
||||
else if (_windowsNvmlDeviceGetHandleByIndex(index, out nvmlDevice) == NvmlReturn.Success)
|
||||
{
|
||||
return nvmlDevice;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
internal static NvmlDevice? NvmlDeviceGetHandleByPciBusId(string pciBusId)
|
||||
{
|
||||
if (IsAvailable)
|
||||
{
|
||||
NvmlDevice nvmlDevice;
|
||||
if (Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
if (nvmlDeviceGetHandleByPciBusId(pciBusId, out nvmlDevice) == NvmlReturn.Success)
|
||||
return nvmlDevice;
|
||||
}
|
||||
else if (_windowsNvmlDeviceGetHandleByPciBusId(pciBusId, out nvmlDevice) == NvmlReturn.Success)
|
||||
{
|
||||
return nvmlDevice;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static int? NvmlDeviceGetPowerUsage(NvmlDevice nvmlDevice)
|
||||
{
|
||||
if (IsAvailable)
|
||||
{
|
||||
int powerUsage;
|
||||
if (Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
if (nvmlDeviceGetPowerUsage(nvmlDevice, out powerUsage) == NvmlReturn.Success)
|
||||
return powerUsage;
|
||||
}
|
||||
else if (_windowsNvmlDeviceGetPowerUsage(nvmlDevice, out powerUsage) == NvmlReturn.Success)
|
||||
{
|
||||
return powerUsage;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static uint? NvmlDeviceGetPcieThroughput(NvmlDevice nvmlDevice, NvmlPcieUtilCounter counter)
|
||||
{
|
||||
if (IsAvailable)
|
||||
{
|
||||
uint pcieThroughput;
|
||||
if (Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
if (nvmlDeviceGetPcieThroughput(nvmlDevice, counter, out pcieThroughput) == NvmlReturn.Success)
|
||||
return pcieThroughput;
|
||||
}
|
||||
else if (_windowsNvmlDeviceGetPcieThroughputDelegate(nvmlDevice, counter, out pcieThroughput) == NvmlReturn.Success)
|
||||
{
|
||||
return pcieThroughput;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlInit_v2", ExactSpelling = true)]
|
||||
private static extern NvmlReturn nvmlInit();
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlInit", ExactSpelling = true)]
|
||||
private static extern NvmlReturn nvmlInitLegacy();
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlShutdown", ExactSpelling = true)]
|
||||
private static extern NvmlReturn nvmlShutdown();
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetHandleByIndex_v2", ExactSpelling = true)]
|
||||
private static extern NvmlReturn nvmlDeviceGetHandleByIndex(int index, out NvmlDevice device);
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetHandleByPciBusId_v2", ExactSpelling = true)]
|
||||
private static extern NvmlReturn nvmlDeviceGetHandleByPciBusId([MarshalAs(UnmanagedType.LPStr)] string pciBusId, out NvmlDevice device);
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetHandleByIndex", ExactSpelling = true)]
|
||||
private static extern NvmlReturn nvmlDeviceGetHandleByIndexLegacy(int index, out NvmlDevice device);
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetPowerUsage", ExactSpelling = true)]
|
||||
private static extern NvmlReturn nvmlDeviceGetPowerUsage(NvmlDevice device, out int power);
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetPcieThroughput", ExactSpelling = true)]
|
||||
private static extern NvmlReturn nvmlDeviceGetPcieThroughput(NvmlDevice device, NvmlPcieUtilCounter counter, out uint value);
|
||||
|
||||
private delegate NvmlReturn WindowsNvmlDelegate();
|
||||
|
||||
private delegate NvmlReturn WindowsNvmlGetHandleDelegate(int index, out NvmlDevice device);
|
||||
|
||||
private delegate NvmlReturn WindowsNvmlGetHandleByPciBusIdDelegate([MarshalAs(UnmanagedType.LPStr)] string pciBusId, out NvmlDevice device);
|
||||
|
||||
private delegate NvmlReturn WindowsNvmlGetPowerUsageDelegate(NvmlDevice device, out int power);
|
||||
|
||||
private delegate NvmlReturn WindowsNvmlDeviceGetPcieThroughputDelegate(NvmlDevice device, NvmlPcieUtilCounter counter, out uint value);
|
||||
|
||||
internal enum NvmlPcieUtilCounter
|
||||
public enum NvmlPcieUtilCounter
|
||||
{
|
||||
TxBytes = 0,
|
||||
RxBytes = 1
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct NvmlDevice
|
||||
{
|
||||
public IntPtr Handle;
|
||||
}
|
||||
|
||||
internal enum NvmlReturn
|
||||
public enum NvmlReturn
|
||||
{
|
||||
/// <summary>
|
||||
/// The operation was successful
|
||||
@@ -396,9 +130,317 @@ namespace LibreHardwareMonitor.Interop
|
||||
InUse = 19,
|
||||
|
||||
/// <summary>
|
||||
/// An internal driver error occurred
|
||||
/// An public driver error occurred
|
||||
/// </summary>
|
||||
Unknown = 999
|
||||
}
|
||||
|
||||
public static bool IsAvailable { get; private set; }
|
||||
|
||||
public static bool Initialize()
|
||||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
if (IsAvailable)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
try
|
||||
{
|
||||
IsAvailable = nvmlInit() == NvmlReturn.Success;
|
||||
}
|
||||
catch (DllNotFoundException)
|
||||
{ }
|
||||
catch (EntryPointNotFoundException)
|
||||
{
|
||||
try
|
||||
{
|
||||
IsAvailable = nvmlInitLegacy() == NvmlReturn.Success;
|
||||
}
|
||||
catch (EntryPointNotFoundException)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
else if (IsNvmlCompatibleWindowsVersion())
|
||||
{
|
||||
// Attempt to load the Nvidia Management Library from the
|
||||
// windows standard search order for applications. This will
|
||||
// help installations that either have the library in
|
||||
// %windir%/system32 or provide their own library
|
||||
_windowsDll = Kernel32.LoadLibrary(WindowsDllName);
|
||||
|
||||
// If there is no dll in the path, then attempt to load it
|
||||
// from program files
|
||||
if (_windowsDll == IntPtr.Zero)
|
||||
{
|
||||
string programFilesDirectory = Environment.ExpandEnvironmentVariables("%ProgramW6432%");
|
||||
string dllPath = Path.Combine(programFilesDirectory, @"NVIDIA Corporation\NVSMI", WindowsDllName);
|
||||
|
||||
_windowsDll = Kernel32.LoadLibrary(dllPath);
|
||||
}
|
||||
|
||||
IsAvailable = (_windowsDll != IntPtr.Zero) && InitialiseDelegates() && (_windowsNvmlInit() == NvmlReturn.Success);
|
||||
}
|
||||
|
||||
return IsAvailable;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsNvmlCompatibleWindowsVersion()
|
||||
{
|
||||
return Software.OperatingSystem.Is64Bit && ((Environment.OSVersion.Version.Major > 6) || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 1));
|
||||
}
|
||||
|
||||
private static bool InitialiseDelegates()
|
||||
{
|
||||
IntPtr nvmlInit = Kernel32.GetProcAddress(_windowsDll, "nvmlInit_v2");
|
||||
|
||||
if (nvmlInit != IntPtr.Zero)
|
||||
{
|
||||
_windowsNvmlInit = (WindowsNvmlDelegate)Marshal.GetDelegateForFunctionPointer(nvmlInit, typeof(WindowsNvmlDelegate));
|
||||
}
|
||||
else
|
||||
{
|
||||
nvmlInit = Kernel32.GetProcAddress(_windowsDll, "nvmlInit");
|
||||
if (nvmlInit != IntPtr.Zero)
|
||||
_windowsNvmlInit = (WindowsNvmlDelegate)Marshal.GetDelegateForFunctionPointer(nvmlInit, typeof(WindowsNvmlDelegate));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
IntPtr nvmlShutdown = Kernel32.GetProcAddress(_windowsDll, "nvmlShutdown");
|
||||
if (nvmlShutdown != IntPtr.Zero)
|
||||
_windowsNvmlShutdown = (WindowsNvmlDelegate)Marshal.GetDelegateForFunctionPointer(nvmlShutdown, typeof(WindowsNvmlDelegate));
|
||||
else
|
||||
return false;
|
||||
|
||||
|
||||
IntPtr nvmlGetHandle = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetHandleByIndex_v2");
|
||||
if (nvmlGetHandle != IntPtr.Zero)
|
||||
_windowsNvmlDeviceGetHandleByIndex = (WindowsNvmlGetHandleDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetHandle, typeof(WindowsNvmlGetHandleDelegate));
|
||||
else
|
||||
{
|
||||
nvmlGetHandle = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetHandleByIndex");
|
||||
if (nvmlGetHandle != IntPtr.Zero)
|
||||
_windowsNvmlDeviceGetHandleByIndex = (WindowsNvmlGetHandleDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetHandle, typeof(WindowsNvmlGetHandleDelegate));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
IntPtr nvmlGetPowerUsage = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetPowerUsage");
|
||||
if (nvmlGetPowerUsage != IntPtr.Zero)
|
||||
_windowsNvmlDeviceGetPowerUsage = (WindowsNvmlGetPowerUsageDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetPowerUsage, typeof(WindowsNvmlGetPowerUsageDelegate));
|
||||
else
|
||||
return false;
|
||||
|
||||
|
||||
IntPtr nvmlGetPcieThroughput = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetPcieThroughput");
|
||||
if (nvmlGetPcieThroughput != IntPtr.Zero)
|
||||
_windowsNvmlDeviceGetPcieThroughputDelegate = (WindowsNvmlDeviceGetPcieThroughputDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetPcieThroughput, typeof(WindowsNvmlDeviceGetPcieThroughputDelegate));
|
||||
else
|
||||
return false;
|
||||
|
||||
|
||||
IntPtr nvmlGetHandlePciBus = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetHandleByPciBusId_v2");
|
||||
if (nvmlGetHandlePciBus != IntPtr.Zero)
|
||||
_windowsNvmlDeviceGetHandleByPciBusId = (WindowsNvmlGetHandleByPciBusIdDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetHandlePciBus, typeof(WindowsNvmlGetHandleByPciBusIdDelegate));
|
||||
else
|
||||
return false;
|
||||
|
||||
IntPtr nvmlDeviceGetPciInfo = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetPciInfo_v2");
|
||||
if (nvmlDeviceGetPciInfo != IntPtr.Zero)
|
||||
_windowsNvmlDeviceGetPciInfo = (WindowsNvmlDeviceGetPciInfo)Marshal.GetDelegateForFunctionPointer(nvmlDeviceGetPciInfo, typeof(WindowsNvmlDeviceGetPciInfo));
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Close()
|
||||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
if (IsAvailable)
|
||||
{
|
||||
if (Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
nvmlShutdown();
|
||||
}
|
||||
else if (_windowsDll != IntPtr.Zero)
|
||||
{
|
||||
_windowsNvmlShutdown();
|
||||
Kernel32.FreeLibrary(_windowsDll);
|
||||
}
|
||||
|
||||
IsAvailable = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static NvmlDevice? NvmlDeviceGetHandleByIndex(int index)
|
||||
{
|
||||
if (IsAvailable)
|
||||
{
|
||||
NvmlDevice nvmlDevice;
|
||||
if (Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (nvmlDeviceGetHandleByIndex(index, out nvmlDevice) == NvmlReturn.Success)
|
||||
return nvmlDevice;
|
||||
}
|
||||
catch (EntryPointNotFoundException)
|
||||
{
|
||||
if (nvmlDeviceGetHandleByIndexLegacy(index, out nvmlDevice) == NvmlReturn.Success)
|
||||
return nvmlDevice;
|
||||
}
|
||||
}
|
||||
else if (_windowsNvmlDeviceGetHandleByIndex(index, out nvmlDevice) == NvmlReturn.Success)
|
||||
return nvmlDevice;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static NvmlDevice? NvmlDeviceGetHandleByPciBusId(string pciBusId)
|
||||
{
|
||||
if (IsAvailable)
|
||||
{
|
||||
NvmlDevice nvmlDevice;
|
||||
if (Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
if (nvmlDeviceGetHandleByPciBusId(pciBusId, out nvmlDevice) == NvmlReturn.Success)
|
||||
return nvmlDevice;
|
||||
}
|
||||
else if (_windowsNvmlDeviceGetHandleByPciBusId(pciBusId, out nvmlDevice) == NvmlReturn.Success)
|
||||
return nvmlDevice;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int? NvmlDeviceGetPowerUsage(NvmlDevice nvmlDevice)
|
||||
{
|
||||
if (IsAvailable)
|
||||
{
|
||||
int powerUsage;
|
||||
if (Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
if (nvmlDeviceGetPowerUsage(nvmlDevice, out powerUsage) == NvmlReturn.Success)
|
||||
return powerUsage;
|
||||
}
|
||||
else if (_windowsNvmlDeviceGetPowerUsage(nvmlDevice, out powerUsage) == NvmlReturn.Success)
|
||||
return powerUsage;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static uint? NvmlDeviceGetPcieThroughput(NvmlDevice nvmlDevice, NvmlPcieUtilCounter counter)
|
||||
{
|
||||
if (IsAvailable)
|
||||
{
|
||||
uint pcieThroughput;
|
||||
if (Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
if (nvmlDeviceGetPcieThroughput(nvmlDevice, counter, out pcieThroughput) == NvmlReturn.Success)
|
||||
return pcieThroughput;
|
||||
}
|
||||
else if (_windowsNvmlDeviceGetPcieThroughputDelegate(nvmlDevice, counter, out pcieThroughput) == NvmlReturn.Success)
|
||||
return pcieThroughput;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static NvmlPciInfo? NvmlDeviceGetPciInfo(NvmlDevice nvmlDevice)
|
||||
{
|
||||
if (IsAvailable)
|
||||
{
|
||||
var pci = new NvmlPciInfo();
|
||||
|
||||
if (Software.OperatingSystem.IsUnix)
|
||||
{
|
||||
if (nvmlDeviceGetPciInfo(nvmlDevice, ref pci) == NvmlReturn.Success)
|
||||
return pci;
|
||||
}
|
||||
else if (_windowsNvmlDeviceGetPciInfo(nvmlDevice, ref pci) == NvmlReturn.Success)
|
||||
return pci;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlInit_v2", ExactSpelling = true)]
|
||||
private static extern NvmlReturn nvmlInit();
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlInit", ExactSpelling = true)]
|
||||
private static extern NvmlReturn nvmlInitLegacy();
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlShutdown", ExactSpelling = true)]
|
||||
private static extern NvmlReturn nvmlShutdown();
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetHandleByIndex_v2", ExactSpelling = true)]
|
||||
private static extern NvmlReturn nvmlDeviceGetHandleByIndex(int index, out NvmlDevice device);
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetHandleByPciBusId_v2", ExactSpelling = true)]
|
||||
private static extern NvmlReturn nvmlDeviceGetHandleByPciBusId([MarshalAs(UnmanagedType.LPStr)] string pciBusId, out NvmlDevice device);
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetHandleByIndex", ExactSpelling = true)]
|
||||
private static extern NvmlReturn nvmlDeviceGetHandleByIndexLegacy(int index, out NvmlDevice device);
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetPowerUsage", ExactSpelling = true)]
|
||||
private static extern NvmlReturn nvmlDeviceGetPowerUsage(NvmlDevice device, out int power);
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetPcieThroughput", ExactSpelling = true)]
|
||||
private static extern NvmlReturn nvmlDeviceGetPcieThroughput(NvmlDevice device, NvmlPcieUtilCounter counter, out uint value);
|
||||
|
||||
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetPciInfo_v2")]
|
||||
private static extern NvmlReturn nvmlDeviceGetPciInfo(NvmlDevice device, ref NvmlPciInfo pci);
|
||||
|
||||
private delegate NvmlReturn WindowsNvmlDelegate();
|
||||
|
||||
private delegate NvmlReturn WindowsNvmlGetHandleDelegate(int index, out NvmlDevice device);
|
||||
|
||||
private delegate NvmlReturn WindowsNvmlGetHandleByPciBusIdDelegate([MarshalAs(UnmanagedType.LPStr)] string pciBusId, out NvmlDevice device);
|
||||
|
||||
private delegate NvmlReturn WindowsNvmlGetPowerUsageDelegate(NvmlDevice device, out int power);
|
||||
|
||||
private delegate NvmlReturn WindowsNvmlDeviceGetPcieThroughputDelegate(NvmlDevice device, NvmlPcieUtilCounter counter, out uint value);
|
||||
|
||||
private delegate NvmlReturn WindowsNvmlDeviceGetPciInfo(NvmlDevice device, ref NvmlPciInfo pci);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct NvmlDevice
|
||||
{
|
||||
public IntPtr Handle;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct NvmlPciInfo
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
|
||||
public string busId;
|
||||
|
||||
public uint domain;
|
||||
|
||||
public uint bus;
|
||||
|
||||
public uint device;
|
||||
|
||||
public ushort pciVendorId;
|
||||
|
||||
public ushort pciDeviceId;
|
||||
|
||||
public uint pciSubSystemId;
|
||||
|
||||
public uint reserved0;
|
||||
public uint reserved1;
|
||||
public uint reserved2;
|
||||
public uint reserved3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// 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.
|
||||
|
||||
// ReSharper disable IdentifierTypo
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibreHardwareMonitor.Interop
|
||||
{
|
||||
internal static class WinNt
|
||||
{
|
||||
internal const int STATUS_SUCCESS = 0;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct LUID
|
||||
{
|
||||
public readonly uint LowPart;
|
||||
public readonly int HighPart;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Size = 8)]
|
||||
internal struct LARGE_INTEGER
|
||||
{
|
||||
[FieldOffset(0)]
|
||||
public long QuadPart;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public uint LowPart;
|
||||
|
||||
[FieldOffset(4)]
|
||||
public int HighPart;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user