@@ -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 int _adapterIndex;
|
||||||
|
|
||||||
private readonly IntPtr _context = IntPtr.Zero;
|
private readonly IntPtr _context = IntPtr.Zero;
|
||||||
private readonly bool _framemetricsStarted = false;
|
|
||||||
|
|
||||||
private readonly Sensor _controlSensor;
|
private readonly Sensor _controlSensor;
|
||||||
private readonly Sensor _coreClock;
|
private readonly Sensor _coreClock;
|
||||||
private readonly Sensor _coreLoad;
|
private readonly Sensor _coreLoad;
|
||||||
private readonly Sensor _coreVoltage;
|
private readonly Sensor _coreVoltage;
|
||||||
private readonly bool _overdriveApiSupported;
|
|
||||||
private readonly int _currentOverdriveApiLevel;
|
private readonly int _currentOverdriveApiLevel;
|
||||||
private readonly Sensor _fan;
|
private readonly Sensor _fan;
|
||||||
private readonly Control _fanControl;
|
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 _memoryClock;
|
||||||
private readonly Sensor _memoryLoad;
|
private readonly Sensor _memoryLoad;
|
||||||
|
private readonly int _memorySensorIndex;
|
||||||
private readonly Sensor _memoryVoltage;
|
private readonly Sensor _memoryVoltage;
|
||||||
|
private readonly int _nodeSensorIndex;
|
||||||
|
private readonly bool _overdriveApiSupported;
|
||||||
private readonly Sensor _powerCore;
|
private readonly Sensor _powerCore;
|
||||||
private readonly Sensor _powerPpt;
|
private readonly Sensor _powerPpt;
|
||||||
private readonly Sensor _powerSoC;
|
private readonly Sensor _powerSoC;
|
||||||
@@ -43,14 +50,14 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
private readonly Sensor _temperaturePlx;
|
private readonly Sensor _temperaturePlx;
|
||||||
private readonly Sensor _temperatureSoC;
|
private readonly Sensor _temperatureSoC;
|
||||||
private readonly Sensor _temperatureVddc;
|
private readonly Sensor _temperatureVddc;
|
||||||
private readonly Sensor _fullscreenFPS;
|
private readonly string _windowsDeviceName;
|
||||||
|
|
||||||
public AmdGpu(string name, int adapterIndex, int busNumber, int deviceNumber, ISettings settings)
|
public AmdGpu(AtiAdlxx.ADLAdapterInfo adapterInfo, ISettings settings)
|
||||||
: base(name, new Identifier("gpu-amd", adapterIndex.ToString(CultureInfo.InvariantCulture)), settings)
|
: base(adapterInfo.AdapterName.Trim(), new Identifier("gpu-amd", adapterInfo.AdapterIndex.ToString(CultureInfo.InvariantCulture)), settings)
|
||||||
{
|
{
|
||||||
_adapterIndex = adapterIndex;
|
_adapterIndex = adapterInfo.AdapterIndex;
|
||||||
BusNumber = busNumber;
|
BusNumber = adapterInfo.BusNumber;
|
||||||
DeviceNumber = deviceNumber;
|
DeviceNumber = adapterInfo.DeviceNumber;
|
||||||
|
|
||||||
_temperatureCore = new Sensor("GPU Core", 0, SensorType.Temperature, this, settings);
|
_temperatureCore = new Sensor("GPU Core", 0, SensorType.Temperature, this, settings);
|
||||||
_temperatureMemory = new Sensor("GPU Memory", 1, 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);
|
_powerSoC = new Sensor("GPU SoC", 2, SensorType.Power, this, settings);
|
||||||
_powerTotal = new Sensor("GPU Package", 3, 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 supported = 0;
|
||||||
int enabled = 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)
|
if (supported == AtiAdlxx.ADL_TRUE && AtiAdlxx.ADL2_Adapter_FrameMetrics_Start(_context, _adapterIndex, 0) == AtiAdlxx.ADLStatus.ADL_OK)
|
||||||
{
|
{
|
||||||
_framemetricsStarted = true;
|
_frameMetricsStarted = true;
|
||||||
_fullscreenFPS.Value = -1;
|
_fullscreenFps.Value = -1;
|
||||||
ActivateSensor(_fullscreenFPS);
|
ActivateSensor(_fullscreenFps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,12 +147,12 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
|
|
||||||
if (_currentOverdriveApiLevel >= 6)
|
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;
|
_context = IntPtr.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
AtiAdlxx.ADLFanSpeedInfo fanSpeedInfo = new AtiAdlxx.ADLFanSpeedInfo();
|
AtiAdlxx.ADLFanSpeedInfo fanSpeedInfo = new();
|
||||||
if (AtiAdlxx.ADL_Overdrive5_FanSpeedInfo_Get(adapterIndex, 0, ref fanSpeedInfo) != AtiAdlxx.ADLStatus.ADL_OK)
|
if (AtiAdlxx.ADL_Overdrive5_FanSpeedInfo_Get(_adapterIndex, 0, ref fanSpeedInfo) != AtiAdlxx.ADLStatus.ADL_OK)
|
||||||
{
|
{
|
||||||
fanSpeedInfo.MaxPercent = 100;
|
fanSpeedInfo.MaxPercent = 100;
|
||||||
fanSpeedInfo.MinPercent = 0;
|
fanSpeedInfo.MinPercent = 0;
|
||||||
@@ -139,11 +179,9 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
{
|
{
|
||||||
if (control.ControlMode == ControlMode.Software)
|
if (control.ControlMode == ControlMode.Software)
|
||||||
{
|
{
|
||||||
AtiAdlxx.ADLFanSpeedValue fanSpeedValue = new AtiAdlxx.ADLFanSpeedValue
|
AtiAdlxx.ADLFanSpeedValue fanSpeedValue = new()
|
||||||
{
|
{
|
||||||
SpeedType = AtiAdlxx.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT,
|
SpeedType = AtiAdlxx.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT, Flags = AtiAdlxx.ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED, FanSpeed = (int)control.SoftwareValue
|
||||||
Flags = AtiAdlxx.ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED,
|
|
||||||
FanSpeed = (int)control.SoftwareValue
|
|
||||||
};
|
};
|
||||||
|
|
||||||
AtiAdlxx.ADL_Overdrive5_FanSpeed_Set(_adapterIndex, 0, ref fanSpeedValue);
|
AtiAdlxx.ADL_Overdrive5_FanSpeed_Set(_adapterIndex, 0, ref fanSpeedValue);
|
||||||
@@ -177,16 +215,35 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
|
|
||||||
public override void Update()
|
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;
|
float framesPerSecond = 0;
|
||||||
if (AtiAdlxx.ADL2_Adapter_FrameMetrics_Get(_context, _adapterIndex, 0, ref framesPerSecond) == AtiAdlxx.ADLStatus.ADL_OK)
|
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)
|
if (_currentOverdriveApiLevel >= 6)
|
||||||
{
|
{
|
||||||
@@ -217,7 +274,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
}
|
}
|
||||||
else
|
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)
|
if (AtiAdlxx.ADL2_New_QueryPMLogData_Get(_context, _adapterIndex, ref logDataOutput) == AtiAdlxx.ADLStatus.ADL_OK)
|
||||||
{
|
{
|
||||||
GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_EDGE, _temperatureCore);
|
GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_EDGE, _temperatureCore);
|
||||||
@@ -266,7 +323,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
|
|
||||||
private void GetOD5CurrentActivity()
|
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 (AtiAdlxx.ADL_Overdrive5_CurrentActivity_Get(_adapterIndex, ref adlpmActivity) == AtiAdlxx.ADLStatus.ADL_OK)
|
||||||
{
|
{
|
||||||
if (adlpmActivity.EngineClock > 0)
|
if (adlpmActivity.EngineClock > 0)
|
||||||
@@ -313,7 +370,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
|
|
||||||
private void GetOD5FanSpeed(int speedType, Sensor sensor)
|
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)
|
if (AtiAdlxx.ADL_Overdrive5_FanSpeed_Get(_adapterIndex, 0, ref fanSpeedValue) == AtiAdlxx.ADLStatus.ADL_OK)
|
||||||
{
|
{
|
||||||
sensor.Value = fanSpeedValue.FanSpeed;
|
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)
|
if (AtiAdlxx.ADL_Overdrive5_Temperature_Get(_adapterIndex, 0, ref temperature) == AtiAdlxx.ADLStatus.ADL_OK)
|
||||||
{
|
{
|
||||||
_temperatureCore.Value = 0.001f * temperature.Temperature;
|
temperatureCore.Value = 0.001f * temperature.Temperature;
|
||||||
ActivateSensor(_temperatureCore);
|
ActivateSensor(temperatureCore);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_temperatureCore.Value = null;
|
temperatureCore.Value = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,6 +401,8 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="type">The type.</param>
|
/// <param name="type">The type.</param>
|
||||||
/// <param name="sensor">The sensor.</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)
|
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.
|
// 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)
|
if (_fanControl.ControlMode != ControlMode.Undefined)
|
||||||
SetDefaultFanSpeed();
|
SetDefaultFanSpeed();
|
||||||
|
|
||||||
if (_framemetricsStarted)
|
if (_frameMetricsStarted)
|
||||||
AtiAdlxx.ADL2_Adapter_FrameMetrics_Stop(_context, _adapterIndex, 0);
|
AtiAdlxx.ADL2_Adapter_FrameMetrics_Stop(_context, _adapterIndex, 0);
|
||||||
|
|
||||||
if (_context != IntPtr.Zero)
|
if (_context != IntPtr.Zero)
|
||||||
|
|||||||
@@ -80,12 +80,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
_hardware.Add(new AmdGpu(
|
_hardware.Add(new AmdGpu(adapterInfo[i], settings));
|
||||||
adapterInfo[i].AdapterName.Trim(),
|
|
||||||
adapterInfo[i].AdapterIndex,
|
|
||||||
adapterInfo[i].BusNumber,
|
|
||||||
adapterInfo[i].DeviceNumber,
|
|
||||||
settings));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_report.AppendLine();
|
_report.AppendLine();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using System;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using LibreHardwareMonitor.Interop;
|
using LibreHardwareMonitor.Interop;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
namespace LibreHardwareMonitor.Hardware.Gpu
|
namespace LibreHardwareMonitor.Hardware.Gpu
|
||||||
{
|
{
|
||||||
@@ -19,17 +20,25 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
private readonly NvApi.NvDisplayHandle? _displayHandle;
|
private readonly NvApi.NvDisplayHandle? _displayHandle;
|
||||||
private readonly Sensor _fan;
|
private readonly Sensor _fan;
|
||||||
private readonly Control _fanControl;
|
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 NvApi.NvPhysicalGpuHandle _handle;
|
||||||
private readonly Sensor[] _loads;
|
private readonly Sensor[] _loads;
|
||||||
private readonly Sensor _memoryAvail;
|
private readonly Sensor _memoryAvail;
|
||||||
private readonly Sensor _memoryFree;
|
private readonly Sensor _memoryFree;
|
||||||
private readonly Sensor _memoryLoad;
|
private readonly Sensor _memoryLoad;
|
||||||
|
private readonly int _memorySensorIndex;
|
||||||
private readonly Sensor _memoryUsed;
|
private readonly Sensor _memoryUsed;
|
||||||
|
private readonly int _nodeSensorIndex;
|
||||||
private readonly NvidiaML.NvmlDevice? _nvmlDevice;
|
private readonly NvidiaML.NvmlDevice? _nvmlDevice;
|
||||||
private readonly Sensor _pcieThroughputRx;
|
private readonly Sensor _pcieThroughputRx;
|
||||||
private readonly Sensor _pcieThroughputTx;
|
private readonly Sensor _pcieThroughputTx;
|
||||||
private readonly Sensor _powerUsage;
|
private readonly Sensor _powerUsage;
|
||||||
private readonly Sensor[] _temperatures;
|
private readonly Sensor[] _temperatures;
|
||||||
|
private readonly string _windowsDeviceName;
|
||||||
|
|
||||||
public NvidiaGpu(int adapterIndex, NvApi.NvPhysicalGpuHandle handle, NvApi.NvDisplayHandle? displayHandle, ISettings settings)
|
public NvidiaGpu(int adapterIndex, NvApi.NvPhysicalGpuHandle handle, NvApi.NvDisplayHandle? displayHandle, ISettings settings)
|
||||||
: base(GetName(handle), new Identifier("gpu-nvidia", adapterIndex.ToString(CultureInfo.InvariantCulture)), 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);
|
_pcieThroughputRx = new Sensor("GPU PCIe Rx", 0, SensorType.Throughput, this, settings);
|
||||||
_pcieThroughputTx = new Sensor("GPU PCIe Tx", 1, 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()
|
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]
|
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()
|
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))
|
if (!(NvApi.NvAPI_GPU_GetCoolerSettings != null && NvApi.NvAPI_GPU_GetCoolerSettings(_handle, 0, ref settings) == NvApi.NvStatus.OK))
|
||||||
{
|
{
|
||||||
settings.Count = 0;
|
settings.Count = 0;
|
||||||
@@ -181,7 +285,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
|
|
||||||
private uint[] GetClocks()
|
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)
|
if (NvApi.NvAPI_GPU_GetAllClocks != null && NvApi.NvAPI_GPU_GetAllClocks(_handle, ref allClocks) == NvApi.NvStatus.OK)
|
||||||
{
|
{
|
||||||
return allClocks.Clock;
|
return allClocks.Clock;
|
||||||
@@ -192,6 +296,25 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
|
|
||||||
public override void Update()
|
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();
|
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.
|
// 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)
|
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)
|
if (NvApi.NvAPI_GPU_GetPStates != null && NvApi.NvAPI_GPU_GetPStates(_handle, ref states) == NvApi.NvStatus.OK)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < _loads.Length; i++)
|
for (int i = 0; i < _loads.Length; i++)
|
||||||
@@ -242,7 +365,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
}
|
}
|
||||||
else
|
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)
|
if (NvApi.NvAPI_GPU_GetUsages != null && NvApi.NvAPI_GPU_GetUsages(_handle, ref usages) == NvApi.NvStatus.OK)
|
||||||
{
|
{
|
||||||
_loads[0].Value = usages.Usage[2];
|
_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)
|
if (NvApi.NvAPI_GPU_GetMemoryInfo != null && _displayHandle.HasValue && NvApi.NvAPI_GPU_GetMemoryInfo(_displayHandle.Value, ref memoryInfo) == NvApi.NvStatus.OK)
|
||||||
{
|
{
|
||||||
uint totalMemory = memoryInfo.Values[0];
|
uint totalMemory = memoryInfo.Values[0];
|
||||||
@@ -326,7 +449,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
|
|
||||||
public override string GetReport()
|
public override string GetReport()
|
||||||
{
|
{
|
||||||
StringBuilder r = new StringBuilder();
|
StringBuilder r = new();
|
||||||
|
|
||||||
r.AppendLine("Nvidia GPU");
|
r.AppendLine("Nvidia GPU");
|
||||||
r.AppendLine();
|
r.AppendLine();
|
||||||
@@ -335,7 +458,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
|
|
||||||
if (_displayHandle.HasValue && NvApi.NvAPI_GetDisplayDriverVersion != null)
|
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)
|
if (NvApi.NvAPI_GetDisplayDriverVersion(_displayHandle.Value, ref driverVersion) == NvApi.NvStatus.OK)
|
||||||
{
|
{
|
||||||
r.Append("Driver Version: ");
|
r.Append("Driver Version: ");
|
||||||
@@ -369,7 +492,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
|
|
||||||
if (NvApi.NvAPI_GPU_GetThermalSettings != null)
|
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]
|
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)
|
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);
|
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetAllClocks(_handle, ref allClocks);
|
||||||
|
|
||||||
r.AppendLine("Clocks");
|
r.AppendLine("Clocks");
|
||||||
@@ -442,7 +565,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
|
|
||||||
if (NvApi.NvAPI_GPU_GetPStates != null)
|
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);
|
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetPStates(_handle, ref states);
|
||||||
|
|
||||||
r.AppendLine("P-States");
|
r.AppendLine("P-States");
|
||||||
@@ -466,7 +589,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
|
|
||||||
if (NvApi.NvAPI_GPU_GetUsages != null)
|
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);
|
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetUsages(_handle, ref usages);
|
||||||
|
|
||||||
r.AppendLine("Usages");
|
r.AppendLine("Usages");
|
||||||
@@ -490,7 +613,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
|
|
||||||
if (NvApi.NvAPI_GPU_GetCoolerSettings != null)
|
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);
|
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetCoolerSettings(_handle, 0, ref settings);
|
||||||
r.AppendLine("Cooler Settings");
|
r.AppendLine("Cooler Settings");
|
||||||
r.AppendLine();
|
r.AppendLine();
|
||||||
@@ -523,11 +646,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
|
|
||||||
if (NvApi.NvAPI_GPU_ClientFanCoolersGetStatus != null)
|
if (NvApi.NvAPI_GPU_ClientFanCoolersGetStatus != null)
|
||||||
{
|
{
|
||||||
var coolers = new NvApi.NvFanCoolersStatus
|
var coolers = new NvApi.NvFanCoolersStatus { Version = NvApi.GPU_FAN_COOLERS_STATUS_VER, Items = new NvApi.NvFanCoolersStatusItem[NvApi.MAX_FAN_COOLERS_STATUS_ITEMS] };
|
||||||
{
|
|
||||||
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);
|
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++)
|
for (int i = 0; i < coolers.Count; i++)
|
||||||
{
|
{
|
||||||
r.AppendFormat(" Items[{0}].Type: {1}{2}", i,
|
r.AppendFormat(" Items[{0}].Type: {1}{2}",
|
||||||
coolers.Items[i].Type, Environment.NewLine);
|
i,
|
||||||
r.AppendFormat(" Items[{0}].CurrentRpm: {1}{2}", i,
|
coolers.Items[i].Type,
|
||||||
coolers.Items[i].CurrentRpm, Environment.NewLine);
|
Environment.NewLine);
|
||||||
r.AppendFormat(" Items[{0}].CurrentMinLevel: {1}{2}", i,
|
|
||||||
coolers.Items[i].CurrentMinLevel, Environment.NewLine);
|
r.AppendFormat(" Items[{0}].CurrentRpm: {1}{2}",
|
||||||
r.AppendFormat(" Items[{0}].CurrentMaxLevel: {1}{2}", i,
|
i,
|
||||||
coolers.Items[i].CurrentMaxLevel, Environment.NewLine);
|
coolers.Items[i].CurrentRpm,
|
||||||
r.AppendFormat(" Items[{0}].CurrentLevel: {1}{2}", i,
|
Environment.NewLine);
|
||||||
coolers.Items[i].CurrentLevel, 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
|
else
|
||||||
@@ -554,12 +687,13 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
r.Append(" Status: ");
|
r.Append(" Status: ");
|
||||||
r.AppendLine(status.ToString());
|
r.AppendLine(status.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
r.AppendLine();
|
r.AppendLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NvApi.NvAPI_GPU_GetMemoryInfo != null && _displayHandle.HasValue)
|
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);
|
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetMemoryInfo(_displayHandle.Value, ref memoryInfo);
|
||||||
|
|
||||||
r.AppendLine("Memory Info");
|
r.AppendLine("Memory Info");
|
||||||
@@ -583,7 +717,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
|
|
||||||
private void SoftwareControlValueChanged(IControl control)
|
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].Level = (int)control.SoftwareValue;
|
||||||
coolerLevels.Levels[0].Policy = 1;
|
coolerLevels.Levels[0].Policy = 1;
|
||||||
NvApi.NvAPI_GPU_SetCoolerLevels(_handle, 0, ref coolerLevels);
|
NvApi.NvAPI_GPU_SetCoolerLevels(_handle, 0, ref coolerLevels);
|
||||||
@@ -608,7 +742,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
|
|
||||||
private void SetDefaultFanSpeed()
|
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;
|
coolerLevels.Levels[0].Policy = 0x20;
|
||||||
NvApi.NvAPI_GPU_SetCoolerLevels(_handle, 0, ref coolerLevels);
|
NvApi.NvAPI_GPU_SetCoolerLevels(_handle, 0, ref coolerLevels);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
{
|
{
|
||||||
internal class NvidiaGroup : IGroup
|
internal class NvidiaGroup : IGroup
|
||||||
{
|
{
|
||||||
private readonly List<Hardware> _hardware = new List<Hardware>();
|
private readonly List<Hardware> _hardware = new();
|
||||||
private readonly StringBuilder _report = new StringBuilder();
|
private readonly StringBuilder _report = new();
|
||||||
|
|
||||||
public NvidiaGroup(ISettings settings)
|
public NvidiaGroup(ISettings settings)
|
||||||
{
|
{
|
||||||
@@ -54,7 +54,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
while (status == NvApi.NvStatus.OK)
|
while (status == NvApi.NvStatus.OK)
|
||||||
{
|
{
|
||||||
NvApi.NvDisplayHandle displayHandle = new NvApi.NvDisplayHandle();
|
NvApi.NvDisplayHandle displayHandle = new();
|
||||||
status = NvApi.NvAPI_EnumNvidiaDisplayHandle(i, ref displayHandle);
|
status = NvApi.NvAPI_EnumNvidiaDisplayHandle(i, ref displayHandle);
|
||||||
i++;
|
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 LinuxDllName = "nvidia-ml";
|
||||||
private const string WindowsDllName = "nvml.dll";
|
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 WindowsNvmlGetHandleDelegate _windowsNvmlDeviceGetHandleByIndex;
|
||||||
private static WindowsNvmlGetPowerUsageDelegate _windowsNvmlDeviceGetPowerUsage;
|
|
||||||
private static WindowsNvmlDeviceGetPcieThroughputDelegate _windowsNvmlDeviceGetPcieThroughputDelegate;
|
|
||||||
private static WindowsNvmlGetHandleByPciBusIdDelegate _windowsNvmlDeviceGetHandleByPciBusId;
|
private static WindowsNvmlGetHandleByPciBusIdDelegate _windowsNvmlDeviceGetHandleByPciBusId;
|
||||||
|
private static WindowsNvmlDeviceGetPcieThroughputDelegate _windowsNvmlDeviceGetPcieThroughputDelegate;
|
||||||
|
private static WindowsNvmlGetPowerUsageDelegate _windowsNvmlDeviceGetPowerUsage;
|
||||||
|
private static WindowsNvmlDeviceGetPciInfo _windowsNvmlDeviceGetPciInfo;
|
||||||
private static WindowsNvmlDelegate _windowsNvmlInit;
|
private static WindowsNvmlDelegate _windowsNvmlInit;
|
||||||
private static WindowsNvmlDelegate _windowsNvmlShutdown;
|
private static WindowsNvmlDelegate _windowsNvmlShutdown;
|
||||||
|
|
||||||
private static IntPtr WindowsDll;
|
public enum NvmlPcieUtilCounter
|
||||||
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
TxBytes = 0,
|
TxBytes = 0,
|
||||||
RxBytes = 1
|
RxBytes = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
public enum NvmlReturn
|
||||||
internal struct NvmlDevice
|
|
||||||
{
|
|
||||||
public IntPtr Handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum NvmlReturn
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The operation was successful
|
/// The operation was successful
|
||||||
@@ -396,9 +130,317 @@ namespace LibreHardwareMonitor.Interop
|
|||||||
InUse = 19,
|
InUse = 19,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An internal driver error occurred
|
/// An public driver error occurred
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Unknown = 999
|
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