Add D3D GPU Sensors (#426)

Thanks to @kolos.
This commit is contained in:
kolos
2021-06-01 13:30:52 +02:00
committed by GitHub
parent 37e917a4f8
commit 5dc6cb95c8
11 changed files with 1520 additions and 347 deletions
@@ -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;
}
}
}
+91 -32
View File
@@ -16,19 +16,26 @@ namespace LibreHardwareMonitor.Hardware.Gpu
private readonly int _adapterIndex;
private readonly IntPtr _context = IntPtr.Zero;
private readonly bool _framemetricsStarted = false;
private readonly Sensor _controlSensor;
private readonly Sensor _coreClock;
private readonly Sensor _coreLoad;
private readonly Sensor _coreVoltage;
private readonly bool _overdriveApiSupported;
private readonly int _currentOverdriveApiLevel;
private readonly Sensor _fan;
private readonly Control _fanControl;
private readonly bool _frameMetricsStarted;
private readonly Sensor _fullscreenFps;
private readonly Sensor _gpuDedicatedMemoryUsage;
private readonly Sensor[] _gpuNodeUsage;
private readonly DateTime[] _gpuNodeUsagePrevTick;
private readonly long[] _gpuNodeUsagePrevValue;
private readonly Sensor _gpuSharedMemoryUsage;
private readonly Sensor _memoryClock;
private readonly Sensor _memoryLoad;
private readonly int _memorySensorIndex;
private readonly Sensor _memoryVoltage;
private readonly int _nodeSensorIndex;
private readonly bool _overdriveApiSupported;
private readonly Sensor _powerCore;
private readonly Sensor _powerPpt;
private readonly Sensor _powerSoC;
@@ -43,14 +50,14 @@ namespace LibreHardwareMonitor.Hardware.Gpu
private readonly Sensor _temperaturePlx;
private readonly Sensor _temperatureSoC;
private readonly Sensor _temperatureVddc;
private readonly Sensor _fullscreenFPS;
private readonly string _windowsDeviceName;
public AmdGpu(string name, int adapterIndex, int busNumber, int deviceNumber, ISettings settings)
: base(name, new Identifier("gpu-amd", adapterIndex.ToString(CultureInfo.InvariantCulture)), settings)
public AmdGpu(AtiAdlxx.ADLAdapterInfo adapterInfo, ISettings settings)
: base(adapterInfo.AdapterName.Trim(), new Identifier("gpu-amd", adapterInfo.AdapterIndex.ToString(CultureInfo.InvariantCulture)), settings)
{
_adapterIndex = adapterIndex;
BusNumber = busNumber;
DeviceNumber = deviceNumber;
_adapterIndex = adapterInfo.AdapterIndex;
BusNumber = adapterInfo.BusNumber;
DeviceNumber = adapterInfo.DeviceNumber;
_temperatureCore = new Sensor("GPU Core", 0, SensorType.Temperature, this, settings);
_temperatureMemory = new Sensor("GPU Memory", 1, SensorType.Temperature, this, settings);
@@ -81,7 +88,40 @@ namespace LibreHardwareMonitor.Hardware.Gpu
_powerSoC = new Sensor("GPU SoC", 2, SensorType.Power, this, settings);
_powerTotal = new Sensor("GPU Package", 3, SensorType.Power, this, settings);
_fullscreenFPS = new Sensor("Fullscreen FPS", 0, SensorType.Factor, this, settings);
_fullscreenFps = new Sensor("Fullscreen FPS", 0, SensorType.Factor, this, settings);
if (!Software.OperatingSystem.IsUnix)
{
string convertedPnpString = adapterInfo.PNPString.Replace("\\", "#");
string[] deviceIdentifiers = D3DDisplayDevice.GetDeviceIdentifiers();
if (deviceIdentifiers != null)
{
foreach (string deviceIdentifier in deviceIdentifiers)
{
if (deviceIdentifier.IndexOf(convertedPnpString, StringComparison.OrdinalIgnoreCase) != -1 &&
D3DDisplayDevice.GetDeviceInfoByIdentifier(deviceIdentifier, out D3DDisplayDevice.D3DDeviceInfo deviceInfo))
{
_windowsDeviceName = deviceIdentifier;
_gpuDedicatedMemoryUsage = new Sensor("D3D Dedicated Memory Used", _memorySensorIndex++, SensorType.SmallData, this, settings);
_gpuSharedMemoryUsage = new Sensor("D3D Shared Memory Used", _memorySensorIndex++, SensorType.SmallData, this, settings);
_gpuNodeUsage = new Sensor[deviceInfo.Nodes.Length];
_gpuNodeUsagePrevValue = new long[deviceInfo.Nodes.Length];
_gpuNodeUsagePrevTick = new DateTime[deviceInfo.Nodes.Length];
foreach (D3DDisplayDevice.D3DDeviceNodeInfo node in deviceInfo.Nodes)
{
_gpuNodeUsage[node.Id] = new Sensor(node.Name, _nodeSensorIndex++, SensorType.Load, this, settings);
_gpuNodeUsagePrevValue[node.Id] = node.RunningTime;
_gpuNodeUsagePrevTick[node.Id] = node.QueryTime;
}
break;
}
}
}
}
int supported = 0;
int enabled = 0;
@@ -91,9 +131,9 @@ namespace LibreHardwareMonitor.Hardware.Gpu
{
if (supported == AtiAdlxx.ADL_TRUE && AtiAdlxx.ADL2_Adapter_FrameMetrics_Start(_context, _adapterIndex, 0) == AtiAdlxx.ADLStatus.ADL_OK)
{
_framemetricsStarted = true;
_fullscreenFPS.Value = -1;
ActivateSensor(_fullscreenFPS);
_frameMetricsStarted = true;
_fullscreenFps.Value = -1;
ActivateSensor(_fullscreenFps);
}
}
@@ -107,12 +147,12 @@ namespace LibreHardwareMonitor.Hardware.Gpu
if (_currentOverdriveApiLevel >= 6)
{
if (AtiAdlxx.ADL2_Main_Control_Create(AtiAdlxx.Main_Memory_Alloc, adapterIndex, ref _context) == AtiAdlxx.ADLStatus.ADL_OK)
if (AtiAdlxx.ADL2_Main_Control_Create(AtiAdlxx.Main_Memory_Alloc, _adapterIndex, ref _context) == AtiAdlxx.ADLStatus.ADL_OK)
_context = IntPtr.Zero;
}
AtiAdlxx.ADLFanSpeedInfo fanSpeedInfo = new AtiAdlxx.ADLFanSpeedInfo();
if (AtiAdlxx.ADL_Overdrive5_FanSpeedInfo_Get(adapterIndex, 0, ref fanSpeedInfo) != AtiAdlxx.ADLStatus.ADL_OK)
AtiAdlxx.ADLFanSpeedInfo fanSpeedInfo = new();
if (AtiAdlxx.ADL_Overdrive5_FanSpeedInfo_Get(_adapterIndex, 0, ref fanSpeedInfo) != AtiAdlxx.ADLStatus.ADL_OK)
{
fanSpeedInfo.MaxPercent = 100;
fanSpeedInfo.MinPercent = 0;
@@ -139,11 +179,9 @@ namespace LibreHardwareMonitor.Hardware.Gpu
{
if (control.ControlMode == ControlMode.Software)
{
AtiAdlxx.ADLFanSpeedValue fanSpeedValue = new AtiAdlxx.ADLFanSpeedValue
AtiAdlxx.ADLFanSpeedValue fanSpeedValue = new()
{
SpeedType = AtiAdlxx.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT,
Flags = AtiAdlxx.ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED,
FanSpeed = (int)control.SoftwareValue
SpeedType = AtiAdlxx.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT, Flags = AtiAdlxx.ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED, FanSpeed = (int)control.SoftwareValue
};
AtiAdlxx.ADL_Overdrive5_FanSpeed_Set(_adapterIndex, 0, ref fanSpeedValue);
@@ -177,16 +215,35 @@ namespace LibreHardwareMonitor.Hardware.Gpu
public override void Update()
{
if(_framemetricsStarted)
if (_windowsDeviceName != null && D3DDisplayDevice.GetDeviceInfoByIdentifier(_windowsDeviceName, out D3DDisplayDevice.D3DDeviceInfo deviceInfo))
{
_gpuDedicatedMemoryUsage.Value = 1f * deviceInfo.GpuDedicatedUsed / 1024 / 1024;
_gpuSharedMemoryUsage.Value = 1f * deviceInfo.GpuSharedUsed / 1024 / 1024;
ActivateSensor(_gpuDedicatedMemoryUsage);
ActivateSensor(_gpuSharedMemoryUsage);
foreach (D3DDisplayDevice.D3DDeviceNodeInfo node in deviceInfo.Nodes)
{
long runningTimeDiff = node.RunningTime - _gpuNodeUsagePrevValue[node.Id];
long timeDiff = node.QueryTime.Ticks - _gpuNodeUsagePrevTick[node.Id].Ticks;
_gpuNodeUsage[node.Id].Value = 100f * runningTimeDiff / timeDiff;
_gpuNodeUsagePrevValue[node.Id] = node.RunningTime;
_gpuNodeUsagePrevTick[node.Id] = node.QueryTime;
ActivateSensor(_gpuNodeUsage[node.Id]);
}
}
if (_frameMetricsStarted)
{
float framesPerSecond = 0;
if (AtiAdlxx.ADL2_Adapter_FrameMetrics_Get(_context, _adapterIndex, 0, ref framesPerSecond) == AtiAdlxx.ADLStatus.ADL_OK)
{
_fullscreenFPS.Value = framesPerSecond;
_fullscreenFps.Value = framesPerSecond;
}
}
if (_currentOverdriveApiLevel < 8)
if (_overdriveApiSupported)
{
if (_currentOverdriveApiLevel >= 6)
{
@@ -217,7 +274,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
}
else
{
AtiAdlxx.ADLPMLogDataOutput logDataOutput = new AtiAdlxx.ADLPMLogDataOutput();
AtiAdlxx.ADLPMLogDataOutput logDataOutput = new();
if (AtiAdlxx.ADL2_New_QueryPMLogData_Get(_context, _adapterIndex, ref logDataOutput) == AtiAdlxx.ADLStatus.ADL_OK)
{
GetPMLog(logDataOutput, AtiAdlxx.ADLSensorType.PMLOG_TEMPERATURE_EDGE, _temperatureCore);
@@ -266,7 +323,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
private void GetOD5CurrentActivity()
{
AtiAdlxx.ADLPMActivity adlpmActivity = new AtiAdlxx.ADLPMActivity();
AtiAdlxx.ADLPMActivity adlpmActivity = new();
if (AtiAdlxx.ADL_Overdrive5_CurrentActivity_Get(_adapterIndex, ref adlpmActivity) == AtiAdlxx.ADLStatus.ADL_OK)
{
if (adlpmActivity.EngineClock > 0)
@@ -313,7 +370,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
private void GetOD5FanSpeed(int speedType, Sensor sensor)
{
AtiAdlxx.ADLFanSpeedValue fanSpeedValue = new AtiAdlxx.ADLFanSpeedValue { SpeedType = speedType };
AtiAdlxx.ADLFanSpeedValue fanSpeedValue = new() { SpeedType = speedType };
if (AtiAdlxx.ADL_Overdrive5_FanSpeed_Get(_adapterIndex, 0, ref fanSpeedValue) == AtiAdlxx.ADLStatus.ADL_OK)
{
sensor.Value = fanSpeedValue.FanSpeed;
@@ -325,17 +382,17 @@ namespace LibreHardwareMonitor.Hardware.Gpu
}
}
private void GetOD5Temperature(Sensor _temperatureCore)
private void GetOD5Temperature(Sensor temperatureCore)
{
AtiAdlxx.ADLTemperature temperature = new AtiAdlxx.ADLTemperature();
AtiAdlxx.ADLTemperature temperature = new();
if (AtiAdlxx.ADL_Overdrive5_Temperature_Get(_adapterIndex, 0, ref temperature) == AtiAdlxx.ADLStatus.ADL_OK)
{
_temperatureCore.Value = 0.001f * temperature.Temperature;
ActivateSensor(_temperatureCore);
temperatureCore.Value = 0.001f * temperature.Temperature;
ActivateSensor(temperatureCore);
}
else
{
_temperatureCore.Value = null;
temperatureCore.Value = null;
}
}
@@ -344,6 +401,8 @@ namespace LibreHardwareMonitor.Hardware.Gpu
/// </summary>
/// <param name="type">The type.</param>
/// <param name="sensor">The sensor.</param>
/// <param name="minTemperature">The minimum temperature.</param>
/// <param name="scale">The scale.</param>
private void GetODNTemperature(AtiAdlxx.ADLODNTemperatureType type, Sensor sensor, double minTemperature = -200, double scale = 1)
{
// If a sensor isn't available, some cards report 54000 degrees C. 110C is expected for Navi, so 100 more than that should be enough to use as a maximum.
@@ -410,7 +469,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
if (_fanControl.ControlMode != ControlMode.Undefined)
SetDefaultFanSpeed();
if (_framemetricsStarted)
if (_frameMetricsStarted)
AtiAdlxx.ADL2_Adapter_FrameMetrics_Stop(_context, _adapterIndex, 0);
if (_context != IntPtr.Zero)
@@ -80,12 +80,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
}
if (!found)
_hardware.Add(new AmdGpu(
adapterInfo[i].AdapterName.Trim(),
adapterInfo[i].AdapterIndex,
adapterInfo[i].BusNumber,
adapterInfo[i].DeviceNumber,
settings));
_hardware.Add(new AmdGpu(adapterInfo[i], settings));
}
_report.AppendLine();
+165 -31
View File
@@ -8,6 +8,7 @@ using System;
using System.Globalization;
using System.Text;
using LibreHardwareMonitor.Interop;
using Microsoft.Win32;
namespace LibreHardwareMonitor.Hardware.Gpu
{
@@ -19,17 +20,25 @@ namespace LibreHardwareMonitor.Hardware.Gpu
private readonly NvApi.NvDisplayHandle? _displayHandle;
private readonly Sensor _fan;
private readonly Control _fanControl;
private readonly Sensor _gpuDedicatedMemoryUsage;
private readonly Sensor[] _gpuNodeUsage;
private readonly DateTime[] _gpuNodeUsagePrevTick;
private readonly long[] _gpuNodeUsagePrevValue;
private readonly Sensor _gpuSharedMemoryUsage;
private readonly NvApi.NvPhysicalGpuHandle _handle;
private readonly Sensor[] _loads;
private readonly Sensor _memoryAvail;
private readonly Sensor _memoryFree;
private readonly Sensor _memoryLoad;
private readonly int _memorySensorIndex;
private readonly Sensor _memoryUsed;
private readonly int _nodeSensorIndex;
private readonly NvidiaML.NvmlDevice? _nvmlDevice;
private readonly Sensor _pcieThroughputRx;
private readonly Sensor _pcieThroughputTx;
private readonly Sensor _powerUsage;
private readonly Sensor[] _temperatures;
private readonly string _windowsDeviceName;
public NvidiaGpu(int adapterIndex, NvApi.NvPhysicalGpuHandle handle, NvApi.NvDisplayHandle? displayHandle, ISettings settings)
: base(GetName(handle), new Identifier("gpu-nvidia", adapterIndex.ToString(CultureInfo.InvariantCulture)), settings)
@@ -120,6 +129,101 @@ namespace LibreHardwareMonitor.Hardware.Gpu
_pcieThroughputRx = new Sensor("GPU PCIe Rx", 0, SensorType.Throughput, this, settings);
_pcieThroughputTx = new Sensor("GPU PCIe Tx", 1, SensorType.Throughput, this, settings);
if (!Software.OperatingSystem.IsUnix)
{
NvidiaML.NvmlPciInfo? pciInfo = NvidiaML.NvmlDeviceGetPciInfo(_nvmlDevice.Value);
if (pciInfo is { } pci)
{
string[] deviceIdentifiers = D3DDisplayDevice.GetDeviceIdentifiers();
if (deviceIdentifiers != null)
{
foreach (string deviceIdentifier in deviceIdentifiers)
{
if (deviceIdentifier.IndexOf("VEN_" + pci.pciVendorId.ToString("X"), StringComparison.OrdinalIgnoreCase) != -1 &&
deviceIdentifier.IndexOf("DEV_" + pci.pciDeviceId.ToString("X"), StringComparison.OrdinalIgnoreCase) != -1 &&
deviceIdentifier.IndexOf("SUBSYS_" + pci.pciSubSystemId.ToString("X"), StringComparison.OrdinalIgnoreCase) != -1)
{
bool isMatch = false;
try
{
if (Registry.GetValue(@"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\nvlddmkm\Enum", adapterIndex.ToString(), null) is string adapterPnpId)
{
if (deviceIdentifier.IndexOf(adapterPnpId.Replace('\\', '#'), StringComparison.OrdinalIgnoreCase) != -1)
isMatch = true;
}
}
catch
{
// Ignored.
}
if (!isMatch)
{
try
{
string path = deviceIdentifier;
if (path.StartsWith(@"\\?\"))
path = path.Substring(4);
path = path.Replace('#', '\\');
int index = path.IndexOf('{');
if (index != -1)
path = path.Substring(0, index);
path = @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\" + path;
if (Registry.GetValue(path, "LocationInformation", null) is string locationInformation)
{
// For example:
// @System32\drivers\pci.sys,#65536;PCI bus %1, device %2, function %3;(38,0,0)
index = locationInformation.IndexOf('(');
if (index != -1)
{
index++;
int secondIndex = locationInformation.IndexOf(',', index);
if (secondIndex != -1)
{
string bus = locationInformation.Substring(index, secondIndex - index);
if (pci.bus.ToString() == bus)
isMatch = true;
}
}
}
}
catch
{
// Ignored.
}
}
if (isMatch && D3DDisplayDevice.GetDeviceInfoByIdentifier(deviceIdentifier, out D3DDisplayDevice.D3DDeviceInfo deviceInfo))
{
_windowsDeviceName = deviceIdentifier;
_gpuDedicatedMemoryUsage = new Sensor("D3D Dedicated Memory Used", _memorySensorIndex++, SensorType.SmallData, this, settings);
_gpuSharedMemoryUsage = new Sensor("D3D Shared Memory Used", _memorySensorIndex++, SensorType.SmallData, this, settings);
_gpuNodeUsage = new Sensor[deviceInfo.Nodes.Length];
_gpuNodeUsagePrevValue = new long[deviceInfo.Nodes.Length];
_gpuNodeUsagePrevTick = new DateTime[deviceInfo.Nodes.Length];
foreach (D3DDisplayDevice.D3DDeviceNodeInfo node in deviceInfo.Nodes)
{
_gpuNodeUsage[node.Id] = new Sensor(node.Name, _nodeSensorIndex++, SensorType.Load, this, settings);
_gpuNodeUsagePrevValue[node.Id] = node.RunningTime;
_gpuNodeUsagePrevTick[node.Id] = node.QueryTime;
}
}
}
}
}
}
}
}
}
@@ -143,7 +247,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
private NvApi.NvGPUThermalSettings GetThermalSettings()
{
NvApi.NvGPUThermalSettings settings = new NvApi.NvGPUThermalSettings
NvApi.NvGPUThermalSettings settings = new()
{
Version = NvApi.GPU_THERMAL_SETTINGS_VER, Count = NvApi.MAX_THERMAL_SENSORS_PER_GPU, Sensor = new NvApi.NvSensor[NvApi.MAX_THERMAL_SENSORS_PER_GPU]
};
@@ -170,7 +274,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
private NvApi.NvGPUCoolerSettings GetCoolerSettings()
{
NvApi.NvGPUCoolerSettings settings = new NvApi.NvGPUCoolerSettings { Version = NvApi.GPU_COOLER_SETTINGS_VER, Cooler = new NvApi.NvCooler[NvApi.MAX_COOLER_PER_GPU] };
NvApi.NvGPUCoolerSettings settings = new() { Version = NvApi.GPU_COOLER_SETTINGS_VER, Cooler = new NvApi.NvCooler[NvApi.MAX_COOLER_PER_GPU] };
if (!(NvApi.NvAPI_GPU_GetCoolerSettings != null && NvApi.NvAPI_GPU_GetCoolerSettings(_handle, 0, ref settings) == NvApi.NvStatus.OK))
{
settings.Count = 0;
@@ -181,7 +285,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
private uint[] GetClocks()
{
NvApi.NvClocks allClocks = new NvApi.NvClocks { Version = NvApi.GPU_CLOCKS_VER, Clock = new uint[NvApi.MAX_CLOCKS_PER_GPU] };
NvApi.NvClocks allClocks = new() { Version = NvApi.GPU_CLOCKS_VER, Clock = new uint[NvApi.MAX_CLOCKS_PER_GPU] };
if (NvApi.NvAPI_GPU_GetAllClocks != null && NvApi.NvAPI_GPU_GetAllClocks(_handle, ref allClocks) == NvApi.NvStatus.OK)
{
return allClocks.Clock;
@@ -192,6 +296,25 @@ namespace LibreHardwareMonitor.Hardware.Gpu
public override void Update()
{
if (_windowsDeviceName != null && D3DDisplayDevice.GetDeviceInfoByIdentifier(_windowsDeviceName, out D3DDisplayDevice.D3DDeviceInfo deviceInfo))
{
_gpuDedicatedMemoryUsage.Value = 1f * deviceInfo.GpuDedicatedUsed / 1024 / 1024;
_gpuSharedMemoryUsage.Value = 1f * deviceInfo.GpuSharedUsed / 1024 / 1024;
ActivateSensor(_gpuDedicatedMemoryUsage);
ActivateSensor(_gpuSharedMemoryUsage);
foreach (D3DDisplayDevice.D3DDeviceNodeInfo node in deviceInfo.Nodes)
{
long runningTimeDiff = node.RunningTime - _gpuNodeUsagePrevValue[node.Id];
long timeDiff = node.QueryTime.Ticks - _gpuNodeUsagePrevTick[node.Id].Ticks;
_gpuNodeUsage[node.Id].Value = 100f * runningTimeDiff / timeDiff;
_gpuNodeUsagePrevValue[node.Id] = node.RunningTime;
_gpuNodeUsagePrevTick[node.Id] = node.QueryTime;
ActivateSensor(_gpuNodeUsage[node.Id]);
}
}
NvApi.NvGPUThermalSettings settings = GetThermalSettings();
// settings.Count is 0 when no valid data available, this happens when you try to read out this value with a high polling interval.
if (settings.Count > 0)
@@ -228,7 +351,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
}
}
NvApi.NvPStates states = new NvApi.NvPStates { Version = NvApi.GPU_PSTATES_VER, PStates = new NvApi.NvPState[NvApi.MAX_PSTATES_PER_GPU] };
NvApi.NvPStates states = new() { Version = NvApi.GPU_PSTATES_VER, PStates = new NvApi.NvPState[NvApi.MAX_PSTATES_PER_GPU] };
if (NvApi.NvAPI_GPU_GetPStates != null && NvApi.NvAPI_GPU_GetPStates(_handle, ref states) == NvApi.NvStatus.OK)
{
for (int i = 0; i < _loads.Length; i++)
@@ -242,7 +365,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
}
else
{
NvApi.NvUsages usages = new NvApi.NvUsages { Version = NvApi.GPU_USAGES_VER, Usage = new uint[NvApi.MAX_USAGES_PER_GPU] };
NvApi.NvUsages usages = new() { Version = NvApi.GPU_USAGES_VER, Usage = new uint[NvApi.MAX_USAGES_PER_GPU] };
if (NvApi.NvAPI_GPU_GetUsages != null && NvApi.NvAPI_GPU_GetUsages(_handle, ref usages) == NvApi.NvStatus.OK)
{
_loads[0].Value = usages.Usage[2];
@@ -282,7 +405,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
}
}
NvApi.NvMemoryInfo memoryInfo = new NvApi.NvMemoryInfo { Version = NvApi.GPU_MEMORY_INFO_VER, Values = new uint[NvApi.MAX_MEMORY_VALUES_PER_GPU] };
NvApi.NvMemoryInfo memoryInfo = new() { Version = NvApi.GPU_MEMORY_INFO_VER, Values = new uint[NvApi.MAX_MEMORY_VALUES_PER_GPU] };
if (NvApi.NvAPI_GPU_GetMemoryInfo != null && _displayHandle.HasValue && NvApi.NvAPI_GPU_GetMemoryInfo(_displayHandle.Value, ref memoryInfo) == NvApi.NvStatus.OK)
{
uint totalMemory = memoryInfo.Values[0];
@@ -326,7 +449,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
public override string GetReport()
{
StringBuilder r = new StringBuilder();
StringBuilder r = new();
r.AppendLine("Nvidia GPU");
r.AppendLine();
@@ -335,7 +458,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
if (_displayHandle.HasValue && NvApi.NvAPI_GetDisplayDriverVersion != null)
{
NvApi.NvDisplayDriverVersion driverVersion = new NvApi.NvDisplayDriverVersion { Version = NvApi.DISPLAY_DRIVER_VERSION_VER };
NvApi.NvDisplayDriverVersion driverVersion = new() { Version = NvApi.DISPLAY_DRIVER_VERSION_VER };
if (NvApi.NvAPI_GetDisplayDriverVersion(_displayHandle.Value, ref driverVersion) == NvApi.NvStatus.OK)
{
r.Append("Driver Version: ");
@@ -369,7 +492,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
if (NvApi.NvAPI_GPU_GetThermalSettings != null)
{
NvApi.NvGPUThermalSettings settings = new NvApi.NvGPUThermalSettings
NvApi.NvGPUThermalSettings settings = new()
{
Version = NvApi.GPU_THERMAL_SETTINGS_VER, Count = NvApi.MAX_THERMAL_SENSORS_PER_GPU, Sensor = new NvApi.NvSensor[NvApi.MAX_THERMAL_SENSORS_PER_GPU]
};
@@ -399,7 +522,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
if (NvApi.NvAPI_GPU_GetAllClocks != null)
{
NvApi.NvClocks allClocks = new NvApi.NvClocks { Version = NvApi.GPU_CLOCKS_VER, Clock = new uint[NvApi.MAX_CLOCKS_PER_GPU] };
NvApi.NvClocks allClocks = new() { Version = NvApi.GPU_CLOCKS_VER, Clock = new uint[NvApi.MAX_CLOCKS_PER_GPU] };
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetAllClocks(_handle, ref allClocks);
r.AppendLine("Clocks");
@@ -442,7 +565,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
if (NvApi.NvAPI_GPU_GetPStates != null)
{
NvApi.NvPStates states = new NvApi.NvPStates { Version = NvApi.GPU_PSTATES_VER, PStates = new NvApi.NvPState[NvApi.MAX_PSTATES_PER_GPU] };
NvApi.NvPStates states = new() { Version = NvApi.GPU_PSTATES_VER, PStates = new NvApi.NvPState[NvApi.MAX_PSTATES_PER_GPU] };
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetPStates(_handle, ref states);
r.AppendLine("P-States");
@@ -466,7 +589,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
if (NvApi.NvAPI_GPU_GetUsages != null)
{
NvApi.NvUsages usages = new NvApi.NvUsages { Version = NvApi.GPU_USAGES_VER, Usage = new uint[NvApi.MAX_USAGES_PER_GPU] };
NvApi.NvUsages usages = new() { Version = NvApi.GPU_USAGES_VER, Usage = new uint[NvApi.MAX_USAGES_PER_GPU] };
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetUsages(_handle, ref usages);
r.AppendLine("Usages");
@@ -490,7 +613,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
if (NvApi.NvAPI_GPU_GetCoolerSettings != null)
{
NvApi.NvGPUCoolerSettings settings = new NvApi.NvGPUCoolerSettings { Version = NvApi.GPU_COOLER_SETTINGS_VER, Cooler = new NvApi.NvCooler[NvApi.MAX_COOLER_PER_GPU] };
NvApi.NvGPUCoolerSettings settings = new() { Version = NvApi.GPU_COOLER_SETTINGS_VER, Cooler = new NvApi.NvCooler[NvApi.MAX_COOLER_PER_GPU] };
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetCoolerSettings(_handle, 0, ref settings);
r.AppendLine("Cooler Settings");
r.AppendLine();
@@ -523,11 +646,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
if (NvApi.NvAPI_GPU_ClientFanCoolersGetStatus != null)
{
var coolers = new NvApi.NvFanCoolersStatus
{
Version = NvApi.GPU_FAN_COOLERS_STATUS_VER,
Items = new NvApi.NvFanCoolersStatusItem[NvApi.MAX_FAN_COOLERS_STATUS_ITEMS]
};
var coolers = new NvApi.NvFanCoolersStatus { Version = NvApi.GPU_FAN_COOLERS_STATUS_VER, Items = new NvApi.NvFanCoolersStatusItem[NvApi.MAX_FAN_COOLERS_STATUS_ITEMS] };
NvApi.NvStatus status = NvApi.NvAPI_GPU_ClientFanCoolersGetStatus(_handle, ref coolers);
@@ -537,16 +656,30 @@ namespace LibreHardwareMonitor.Hardware.Gpu
{
for (int i = 0; i < coolers.Count; i++)
{
r.AppendFormat(" Items[{0}].Type: {1}{2}", i,
coolers.Items[i].Type, Environment.NewLine);
r.AppendFormat(" Items[{0}].CurrentRpm: {1}{2}", i,
coolers.Items[i].CurrentRpm, Environment.NewLine);
r.AppendFormat(" Items[{0}].CurrentMinLevel: {1}{2}", i,
coolers.Items[i].CurrentMinLevel, Environment.NewLine);
r.AppendFormat(" Items[{0}].CurrentMaxLevel: {1}{2}", i,
coolers.Items[i].CurrentMaxLevel, Environment.NewLine);
r.AppendFormat(" Items[{0}].CurrentLevel: {1}{2}", i,
coolers.Items[i].CurrentLevel, Environment.NewLine);
r.AppendFormat(" Items[{0}].Type: {1}{2}",
i,
coolers.Items[i].Type,
Environment.NewLine);
r.AppendFormat(" Items[{0}].CurrentRpm: {1}{2}",
i,
coolers.Items[i].CurrentRpm,
Environment.NewLine);
r.AppendFormat(" Items[{0}].CurrentMinLevel: {1}{2}",
i,
coolers.Items[i].CurrentMinLevel,
Environment.NewLine);
r.AppendFormat(" Items[{0}].CurrentMaxLevel: {1}{2}",
i,
coolers.Items[i].CurrentMaxLevel,
Environment.NewLine);
r.AppendFormat(" Items[{0}].CurrentLevel: {1}{2}",
i,
coolers.Items[i].CurrentLevel,
Environment.NewLine);
}
}
else
@@ -554,12 +687,13 @@ namespace LibreHardwareMonitor.Hardware.Gpu
r.Append(" Status: ");
r.AppendLine(status.ToString());
}
r.AppendLine();
}
if (NvApi.NvAPI_GPU_GetMemoryInfo != null && _displayHandle.HasValue)
{
NvApi.NvMemoryInfo memoryInfo = new NvApi.NvMemoryInfo { Version = NvApi.GPU_MEMORY_INFO_VER, Values = new uint[NvApi.MAX_MEMORY_VALUES_PER_GPU] };
NvApi.NvMemoryInfo memoryInfo = new() { Version = NvApi.GPU_MEMORY_INFO_VER, Values = new uint[NvApi.MAX_MEMORY_VALUES_PER_GPU] };
NvApi.NvStatus status = NvApi.NvAPI_GPU_GetMemoryInfo(_displayHandle.Value, ref memoryInfo);
r.AppendLine("Memory Info");
@@ -583,7 +717,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
private void SoftwareControlValueChanged(IControl control)
{
NvApi.NvGPUCoolerLevels coolerLevels = new NvApi.NvGPUCoolerLevels { Version = NvApi.GPU_COOLER_LEVELS_VER, Levels = new NvApi.NvLevel[NvApi.MAX_COOLER_PER_GPU] };
NvApi.NvGPUCoolerLevels coolerLevels = new() { Version = NvApi.GPU_COOLER_LEVELS_VER, Levels = new NvApi.NvLevel[NvApi.MAX_COOLER_PER_GPU] };
coolerLevels.Levels[0].Level = (int)control.SoftwareValue;
coolerLevels.Levels[0].Policy = 1;
NvApi.NvAPI_GPU_SetCoolerLevels(_handle, 0, ref coolerLevels);
@@ -608,7 +742,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
private void SetDefaultFanSpeed()
{
NvApi.NvGPUCoolerLevels coolerLevels = new NvApi.NvGPUCoolerLevels { Version = NvApi.GPU_COOLER_LEVELS_VER, Levels = new NvApi.NvLevel[NvApi.MAX_COOLER_PER_GPU] };
NvApi.NvGPUCoolerLevels coolerLevels = new() { Version = NvApi.GPU_COOLER_LEVELS_VER, Levels = new NvApi.NvLevel[NvApi.MAX_COOLER_PER_GPU] };
coolerLevels.Levels[0].Policy = 0x20;
NvApi.NvAPI_GPU_SetCoolerLevels(_handle, 0, ref coolerLevels);
}
@@ -13,8 +13,8 @@ namespace LibreHardwareMonitor.Hardware.Gpu
{
internal class NvidiaGroup : IGroup
{
private readonly List<Hardware> _hardware = new List<Hardware>();
private readonly StringBuilder _report = new StringBuilder();
private readonly List<Hardware> _hardware = new();
private readonly StringBuilder _report = new();
public NvidiaGroup(ISettings settings)
{
@@ -54,7 +54,7 @@ namespace LibreHardwareMonitor.Hardware.Gpu
int i = 0;
while (status == NvApi.NvStatus.OK)
{
NvApi.NvDisplayHandle displayHandle = new NvApi.NvDisplayHandle();
NvApi.NvDisplayHandle displayHandle = new();
status = NvApi.NvAPI_EnumNvidiaDisplayHandle(i, ref displayHandle);
i++;
@@ -0,0 +1,28 @@
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Copyright (C) LibreHardwareMonitor and Contributors.
// All Rights Reserved.
// ReSharper disable IdentifierTypo
// ReSharper disable InconsistentNaming
using System;
using System.Runtime.InteropServices;
namespace LibreHardwareMonitor.Interop
{
internal static class CfgMgr32
{
internal const uint CM_GET_DEVICE_INTERFACE_LIST_PRESENT = 0;
internal const int CR_SUCCESS = 0;
internal static Guid GUID_DISPLAY_DEVICE_ARRIVAL = new("1CA05180-A699-450A-9A0C-DE4FBE3DDD89");
internal const string DllName = "CfgMgr32.dll";
[DllImport(DllName, CharSet = CharSet.Unicode)]
internal static extern uint CM_Get_Device_Interface_List_Size(out uint size, ref Guid interfaceClassGuid, string deviceID, uint flags);
[DllImport(DllName, CharSet = CharSet.Unicode)]
internal static extern uint CM_Get_Device_Interface_List(ref Guid interfaceClassGuid, string deviceID, char[] buffer, uint bufferLength, uint flags);
}
}
@@ -0,0 +1,48 @@
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Copyright (C) LibreHardwareMonitor and Contributors.
// All Rights Reserved.
// ReSharper disable IdentifierTypo
// ReSharper disable InconsistentNaming
using System.Runtime.InteropServices;
namespace LibreHardwareMonitor.Interop
{
internal static class D3dkmdt
{
internal enum DXGK_ENGINE_TYPE
{
DXGK_ENGINE_TYPE_OTHER = 0,
DXGK_ENGINE_TYPE_3D = 1,
DXGK_ENGINE_TYPE_VIDEO_DECODE = 2,
DXGK_ENGINE_TYPE_VIDEO_ENCODE = 3,
DXGK_ENGINE_TYPE_VIDEO_PROCESSING = 4,
DXGK_ENGINE_TYPE_SCENE_ASSEMBLY = 5,
DXGK_ENGINE_TYPE_COPY = 6,
DXGK_ENGINE_TYPE_OVERLAY = 7,
DXGK_ENGINE_TYPE_CRYPTO,
DXGK_ENGINE_TYPE_MAX
}
[StructLayout(LayoutKind.Sequential)]
internal struct DXGK_NODEMETADATA_FLAGS
{
public uint Value;
}
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)]
internal struct DXGK_NODEMETADATA
{
public DXGK_ENGINE_TYPE EngineType;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string FriendlyName;
public DXGK_NODEMETADATA_FLAGS Flags;
public byte GpuMmuSupported;
public byte IoMmuSupported;
}
}
}
+563
View File
@@ -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,
}
}
}
+29
View File
@@ -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);
}
}
+317 -275
View File
@@ -14,291 +14,25 @@ namespace LibreHardwareMonitor.Interop
private const string LinuxDllName = "nvidia-ml";
private const string WindowsDllName = "nvml.dll";
private static readonly object SyncRoot = new object();
private static readonly object _syncRoot = new();
private static IntPtr _windowsDll;
private static WindowsNvmlGetHandleDelegate _windowsNvmlDeviceGetHandleByIndex;
private static WindowsNvmlGetPowerUsageDelegate _windowsNvmlDeviceGetPowerUsage;
private static WindowsNvmlDeviceGetPcieThroughputDelegate _windowsNvmlDeviceGetPcieThroughputDelegate;
private static WindowsNvmlGetHandleByPciBusIdDelegate _windowsNvmlDeviceGetHandleByPciBusId;
private static WindowsNvmlDeviceGetPcieThroughputDelegate _windowsNvmlDeviceGetPcieThroughputDelegate;
private static WindowsNvmlGetPowerUsageDelegate _windowsNvmlDeviceGetPowerUsage;
private static WindowsNvmlDeviceGetPciInfo _windowsNvmlDeviceGetPciInfo;
private static WindowsNvmlDelegate _windowsNvmlInit;
private static WindowsNvmlDelegate _windowsNvmlShutdown;
private static IntPtr WindowsDll;
internal static bool IsAvailable { get; private set; }
internal static bool Initialize()
{
lock (SyncRoot)
{
if (IsAvailable)
{
return true;
}
if (Software.OperatingSystem.IsUnix)
{
try
{
IsAvailable = nvmlInit() == NvmlReturn.Success;
}
catch (DllNotFoundException)
{ }
catch (EntryPointNotFoundException)
{
try
{
IsAvailable = nvmlInitLegacy() == NvmlReturn.Success;
}
catch (EntryPointNotFoundException)
{ }
}
}
else if (IsNvmlCompatibleWindowsVersion())
{
// Attempt to load the Nvidia Management Library from the
// windows standard search order for applications. This will
// help installations that either have the library in
// %windir%/system32 or provide their own library
WindowsDll = Kernel32.LoadLibrary(WindowsDllName);
// If there is no dll in the path, then attempt to load it
// from program files
if (WindowsDll == IntPtr.Zero)
{
string programFilesDirectory = Environment.ExpandEnvironmentVariables("%ProgramW6432%");
string dllPath = Path.Combine(programFilesDirectory, @"NVIDIA Corporation\NVSMI", WindowsDllName);
WindowsDll = Kernel32.LoadLibrary(dllPath);
}
IsAvailable = (WindowsDll != IntPtr.Zero)
&& InitialiseDelegates()
&& (_windowsNvmlInit() == NvmlReturn.Success);
}
return IsAvailable;
}
}
private static bool IsNvmlCompatibleWindowsVersion()
{
return Software.OperatingSystem.Is64Bit && ((Environment.OSVersion.Version.Major > 6) || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 1));
}
private static bool InitialiseDelegates()
{
IntPtr nvmlInit = Kernel32.GetProcAddress(WindowsDll, "nvmlInit_v2");
if (nvmlInit != IntPtr.Zero)
{
_windowsNvmlInit = (WindowsNvmlDelegate)Marshal.GetDelegateForFunctionPointer(nvmlInit, typeof(WindowsNvmlDelegate));
}
else
{
nvmlInit = Kernel32.GetProcAddress(WindowsDll, "nvmlInit");
if (nvmlInit != IntPtr.Zero)
_windowsNvmlInit = (WindowsNvmlDelegate)Marshal.GetDelegateForFunctionPointer(nvmlInit, typeof(WindowsNvmlDelegate));
else
return false;
}
IntPtr nvmlShutdown = Kernel32.GetProcAddress(WindowsDll, "nvmlShutdown");
if (nvmlShutdown != IntPtr.Zero)
_windowsNvmlShutdown = (WindowsNvmlDelegate)Marshal.GetDelegateForFunctionPointer(nvmlShutdown, typeof(WindowsNvmlDelegate));
else
return false;
IntPtr nvmlGetHandle = Kernel32.GetProcAddress(WindowsDll, "nvmlDeviceGetHandleByIndex_v2");
if (nvmlGetHandle != IntPtr.Zero)
{
_windowsNvmlDeviceGetHandleByIndex = (WindowsNvmlGetHandleDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetHandle, typeof(WindowsNvmlGetHandleDelegate));
}
else
{
nvmlGetHandle = Kernel32.GetProcAddress(WindowsDll, "nvmlDeviceGetHandleByIndex");
if (nvmlGetHandle != IntPtr.Zero)
_windowsNvmlDeviceGetHandleByIndex = (WindowsNvmlGetHandleDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetHandle, typeof(WindowsNvmlGetHandleDelegate));
else
return false;
}
IntPtr nvmlGetPowerUsage = Kernel32.GetProcAddress(WindowsDll, "nvmlDeviceGetPowerUsage");
if (nvmlGetPowerUsage != IntPtr.Zero)
_windowsNvmlDeviceGetPowerUsage = (WindowsNvmlGetPowerUsageDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetPowerUsage, typeof(WindowsNvmlGetPowerUsageDelegate));
else
return false;
IntPtr nvmlGetPcieThroughput = Kernel32.GetProcAddress(WindowsDll, "nvmlDeviceGetPcieThroughput");
if (nvmlGetPcieThroughput != IntPtr.Zero)
_windowsNvmlDeviceGetPcieThroughputDelegate = (WindowsNvmlDeviceGetPcieThroughputDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetPcieThroughput, typeof(WindowsNvmlDeviceGetPcieThroughputDelegate));
else
return false;
IntPtr nvmlGetHandlePciBus = Kernel32.GetProcAddress(WindowsDll, "nvmlDeviceGetHandleByPciBusId_v2");
if (nvmlGetHandlePciBus != IntPtr.Zero)
_windowsNvmlDeviceGetHandleByPciBusId = (WindowsNvmlGetHandleByPciBusIdDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetHandlePciBus, typeof(WindowsNvmlGetHandleByPciBusIdDelegate));
else
return false;
return true;
}
internal static void Close()
{
lock (SyncRoot)
{
if (IsAvailable)
{
if (Software.OperatingSystem.IsUnix)
{
nvmlShutdown();
}
else if (WindowsDll != IntPtr.Zero)
{
_windowsNvmlShutdown();
Kernel32.FreeLibrary(WindowsDll);
}
IsAvailable = false;
}
}
}
internal static NvmlDevice? NvmlDeviceGetHandleByIndex(int index)
{
if (IsAvailable)
{
NvmlDevice nvmlDevice;
if (Software.OperatingSystem.IsUnix)
{
try
{
if (nvmlDeviceGetHandleByIndex(index, out nvmlDevice) == NvmlReturn.Success)
return nvmlDevice;
}
catch (EntryPointNotFoundException)
{
if (nvmlDeviceGetHandleByIndexLegacy(index, out nvmlDevice) == NvmlReturn.Success)
return nvmlDevice;
}
}
else if (_windowsNvmlDeviceGetHandleByIndex(index, out nvmlDevice) == NvmlReturn.Success)
{
return nvmlDevice;
}
}
return null;
}
internal static NvmlDevice? NvmlDeviceGetHandleByPciBusId(string pciBusId)
{
if (IsAvailable)
{
NvmlDevice nvmlDevice;
if (Software.OperatingSystem.IsUnix)
{
if (nvmlDeviceGetHandleByPciBusId(pciBusId, out nvmlDevice) == NvmlReturn.Success)
return nvmlDevice;
}
else if (_windowsNvmlDeviceGetHandleByPciBusId(pciBusId, out nvmlDevice) == NvmlReturn.Success)
{
return nvmlDevice;
}
}
return null;
}
internal static int? NvmlDeviceGetPowerUsage(NvmlDevice nvmlDevice)
{
if (IsAvailable)
{
int powerUsage;
if (Software.OperatingSystem.IsUnix)
{
if (nvmlDeviceGetPowerUsage(nvmlDevice, out powerUsage) == NvmlReturn.Success)
return powerUsage;
}
else if (_windowsNvmlDeviceGetPowerUsage(nvmlDevice, out powerUsage) == NvmlReturn.Success)
{
return powerUsage;
}
}
return null;
}
internal static uint? NvmlDeviceGetPcieThroughput(NvmlDevice nvmlDevice, NvmlPcieUtilCounter counter)
{
if (IsAvailable)
{
uint pcieThroughput;
if (Software.OperatingSystem.IsUnix)
{
if (nvmlDeviceGetPcieThroughput(nvmlDevice, counter, out pcieThroughput) == NvmlReturn.Success)
return pcieThroughput;
}
else if (_windowsNvmlDeviceGetPcieThroughputDelegate(nvmlDevice, counter, out pcieThroughput) == NvmlReturn.Success)
{
return pcieThroughput;
}
}
return null;
}
[DllImport(LinuxDllName, EntryPoint = "nvmlInit_v2", ExactSpelling = true)]
private static extern NvmlReturn nvmlInit();
[DllImport(LinuxDllName, EntryPoint = "nvmlInit", ExactSpelling = true)]
private static extern NvmlReturn nvmlInitLegacy();
[DllImport(LinuxDllName, EntryPoint = "nvmlShutdown", ExactSpelling = true)]
private static extern NvmlReturn nvmlShutdown();
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetHandleByIndex_v2", ExactSpelling = true)]
private static extern NvmlReturn nvmlDeviceGetHandleByIndex(int index, out NvmlDevice device);
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetHandleByPciBusId_v2", ExactSpelling = true)]
private static extern NvmlReturn nvmlDeviceGetHandleByPciBusId([MarshalAs(UnmanagedType.LPStr)] string pciBusId, out NvmlDevice device);
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetHandleByIndex", ExactSpelling = true)]
private static extern NvmlReturn nvmlDeviceGetHandleByIndexLegacy(int index, out NvmlDevice device);
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetPowerUsage", ExactSpelling = true)]
private static extern NvmlReturn nvmlDeviceGetPowerUsage(NvmlDevice device, out int power);
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetPcieThroughput", ExactSpelling = true)]
private static extern NvmlReturn nvmlDeviceGetPcieThroughput(NvmlDevice device, NvmlPcieUtilCounter counter, out uint value);
private delegate NvmlReturn WindowsNvmlDelegate();
private delegate NvmlReturn WindowsNvmlGetHandleDelegate(int index, out NvmlDevice device);
private delegate NvmlReturn WindowsNvmlGetHandleByPciBusIdDelegate([MarshalAs(UnmanagedType.LPStr)] string pciBusId, out NvmlDevice device);
private delegate NvmlReturn WindowsNvmlGetPowerUsageDelegate(NvmlDevice device, out int power);
private delegate NvmlReturn WindowsNvmlDeviceGetPcieThroughputDelegate(NvmlDevice device, NvmlPcieUtilCounter counter, out uint value);
internal enum NvmlPcieUtilCounter
public enum NvmlPcieUtilCounter
{
TxBytes = 0,
RxBytes = 1
}
[StructLayout(LayoutKind.Sequential)]
internal struct NvmlDevice
{
public IntPtr Handle;
}
internal enum NvmlReturn
public enum NvmlReturn
{
/// <summary>
/// The operation was successful
@@ -396,9 +130,317 @@ namespace LibreHardwareMonitor.Interop
InUse = 19,
/// <summary>
/// An internal driver error occurred
/// An public driver error occurred
/// </summary>
Unknown = 999
}
public static bool IsAvailable { get; private set; }
public static bool Initialize()
{
lock (_syncRoot)
{
if (IsAvailable)
{
return true;
}
if (Software.OperatingSystem.IsUnix)
{
try
{
IsAvailable = nvmlInit() == NvmlReturn.Success;
}
catch (DllNotFoundException)
{ }
catch (EntryPointNotFoundException)
{
try
{
IsAvailable = nvmlInitLegacy() == NvmlReturn.Success;
}
catch (EntryPointNotFoundException)
{ }
}
}
else if (IsNvmlCompatibleWindowsVersion())
{
// Attempt to load the Nvidia Management Library from the
// windows standard search order for applications. This will
// help installations that either have the library in
// %windir%/system32 or provide their own library
_windowsDll = Kernel32.LoadLibrary(WindowsDllName);
// If there is no dll in the path, then attempt to load it
// from program files
if (_windowsDll == IntPtr.Zero)
{
string programFilesDirectory = Environment.ExpandEnvironmentVariables("%ProgramW6432%");
string dllPath = Path.Combine(programFilesDirectory, @"NVIDIA Corporation\NVSMI", WindowsDllName);
_windowsDll = Kernel32.LoadLibrary(dllPath);
}
IsAvailable = (_windowsDll != IntPtr.Zero) && InitialiseDelegates() && (_windowsNvmlInit() == NvmlReturn.Success);
}
return IsAvailable;
}
}
private static bool IsNvmlCompatibleWindowsVersion()
{
return Software.OperatingSystem.Is64Bit && ((Environment.OSVersion.Version.Major > 6) || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 1));
}
private static bool InitialiseDelegates()
{
IntPtr nvmlInit = Kernel32.GetProcAddress(_windowsDll, "nvmlInit_v2");
if (nvmlInit != IntPtr.Zero)
{
_windowsNvmlInit = (WindowsNvmlDelegate)Marshal.GetDelegateForFunctionPointer(nvmlInit, typeof(WindowsNvmlDelegate));
}
else
{
nvmlInit = Kernel32.GetProcAddress(_windowsDll, "nvmlInit");
if (nvmlInit != IntPtr.Zero)
_windowsNvmlInit = (WindowsNvmlDelegate)Marshal.GetDelegateForFunctionPointer(nvmlInit, typeof(WindowsNvmlDelegate));
else
return false;
}
IntPtr nvmlShutdown = Kernel32.GetProcAddress(_windowsDll, "nvmlShutdown");
if (nvmlShutdown != IntPtr.Zero)
_windowsNvmlShutdown = (WindowsNvmlDelegate)Marshal.GetDelegateForFunctionPointer(nvmlShutdown, typeof(WindowsNvmlDelegate));
else
return false;
IntPtr nvmlGetHandle = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetHandleByIndex_v2");
if (nvmlGetHandle != IntPtr.Zero)
_windowsNvmlDeviceGetHandleByIndex = (WindowsNvmlGetHandleDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetHandle, typeof(WindowsNvmlGetHandleDelegate));
else
{
nvmlGetHandle = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetHandleByIndex");
if (nvmlGetHandle != IntPtr.Zero)
_windowsNvmlDeviceGetHandleByIndex = (WindowsNvmlGetHandleDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetHandle, typeof(WindowsNvmlGetHandleDelegate));
else
return false;
}
IntPtr nvmlGetPowerUsage = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetPowerUsage");
if (nvmlGetPowerUsage != IntPtr.Zero)
_windowsNvmlDeviceGetPowerUsage = (WindowsNvmlGetPowerUsageDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetPowerUsage, typeof(WindowsNvmlGetPowerUsageDelegate));
else
return false;
IntPtr nvmlGetPcieThroughput = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetPcieThroughput");
if (nvmlGetPcieThroughput != IntPtr.Zero)
_windowsNvmlDeviceGetPcieThroughputDelegate = (WindowsNvmlDeviceGetPcieThroughputDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetPcieThroughput, typeof(WindowsNvmlDeviceGetPcieThroughputDelegate));
else
return false;
IntPtr nvmlGetHandlePciBus = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetHandleByPciBusId_v2");
if (nvmlGetHandlePciBus != IntPtr.Zero)
_windowsNvmlDeviceGetHandleByPciBusId = (WindowsNvmlGetHandleByPciBusIdDelegate)Marshal.GetDelegateForFunctionPointer(nvmlGetHandlePciBus, typeof(WindowsNvmlGetHandleByPciBusIdDelegate));
else
return false;
IntPtr nvmlDeviceGetPciInfo = Kernel32.GetProcAddress(_windowsDll, "nvmlDeviceGetPciInfo_v2");
if (nvmlDeviceGetPciInfo != IntPtr.Zero)
_windowsNvmlDeviceGetPciInfo = (WindowsNvmlDeviceGetPciInfo)Marshal.GetDelegateForFunctionPointer(nvmlDeviceGetPciInfo, typeof(WindowsNvmlDeviceGetPciInfo));
else
return false;
return true;
}
public static void Close()
{
lock (_syncRoot)
{
if (IsAvailable)
{
if (Software.OperatingSystem.IsUnix)
{
nvmlShutdown();
}
else if (_windowsDll != IntPtr.Zero)
{
_windowsNvmlShutdown();
Kernel32.FreeLibrary(_windowsDll);
}
IsAvailable = false;
}
}
}
public static NvmlDevice? NvmlDeviceGetHandleByIndex(int index)
{
if (IsAvailable)
{
NvmlDevice nvmlDevice;
if (Software.OperatingSystem.IsUnix)
{
try
{
if (nvmlDeviceGetHandleByIndex(index, out nvmlDevice) == NvmlReturn.Success)
return nvmlDevice;
}
catch (EntryPointNotFoundException)
{
if (nvmlDeviceGetHandleByIndexLegacy(index, out nvmlDevice) == NvmlReturn.Success)
return nvmlDevice;
}
}
else if (_windowsNvmlDeviceGetHandleByIndex(index, out nvmlDevice) == NvmlReturn.Success)
return nvmlDevice;
}
return null;
}
public static NvmlDevice? NvmlDeviceGetHandleByPciBusId(string pciBusId)
{
if (IsAvailable)
{
NvmlDevice nvmlDevice;
if (Software.OperatingSystem.IsUnix)
{
if (nvmlDeviceGetHandleByPciBusId(pciBusId, out nvmlDevice) == NvmlReturn.Success)
return nvmlDevice;
}
else if (_windowsNvmlDeviceGetHandleByPciBusId(pciBusId, out nvmlDevice) == NvmlReturn.Success)
return nvmlDevice;
}
return null;
}
public static int? NvmlDeviceGetPowerUsage(NvmlDevice nvmlDevice)
{
if (IsAvailable)
{
int powerUsage;
if (Software.OperatingSystem.IsUnix)
{
if (nvmlDeviceGetPowerUsage(nvmlDevice, out powerUsage) == NvmlReturn.Success)
return powerUsage;
}
else if (_windowsNvmlDeviceGetPowerUsage(nvmlDevice, out powerUsage) == NvmlReturn.Success)
return powerUsage;
}
return null;
}
public static uint? NvmlDeviceGetPcieThroughput(NvmlDevice nvmlDevice, NvmlPcieUtilCounter counter)
{
if (IsAvailable)
{
uint pcieThroughput;
if (Software.OperatingSystem.IsUnix)
{
if (nvmlDeviceGetPcieThroughput(nvmlDevice, counter, out pcieThroughput) == NvmlReturn.Success)
return pcieThroughput;
}
else if (_windowsNvmlDeviceGetPcieThroughputDelegate(nvmlDevice, counter, out pcieThroughput) == NvmlReturn.Success)
return pcieThroughput;
}
return null;
}
public static NvmlPciInfo? NvmlDeviceGetPciInfo(NvmlDevice nvmlDevice)
{
if (IsAvailable)
{
var pci = new NvmlPciInfo();
if (Software.OperatingSystem.IsUnix)
{
if (nvmlDeviceGetPciInfo(nvmlDevice, ref pci) == NvmlReturn.Success)
return pci;
}
else if (_windowsNvmlDeviceGetPciInfo(nvmlDevice, ref pci) == NvmlReturn.Success)
return pci;
}
return null;
}
[DllImport(LinuxDllName, EntryPoint = "nvmlInit_v2", ExactSpelling = true)]
private static extern NvmlReturn nvmlInit();
[DllImport(LinuxDllName, EntryPoint = "nvmlInit", ExactSpelling = true)]
private static extern NvmlReturn nvmlInitLegacy();
[DllImport(LinuxDllName, EntryPoint = "nvmlShutdown", ExactSpelling = true)]
private static extern NvmlReturn nvmlShutdown();
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetHandleByIndex_v2", ExactSpelling = true)]
private static extern NvmlReturn nvmlDeviceGetHandleByIndex(int index, out NvmlDevice device);
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetHandleByPciBusId_v2", ExactSpelling = true)]
private static extern NvmlReturn nvmlDeviceGetHandleByPciBusId([MarshalAs(UnmanagedType.LPStr)] string pciBusId, out NvmlDevice device);
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetHandleByIndex", ExactSpelling = true)]
private static extern NvmlReturn nvmlDeviceGetHandleByIndexLegacy(int index, out NvmlDevice device);
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetPowerUsage", ExactSpelling = true)]
private static extern NvmlReturn nvmlDeviceGetPowerUsage(NvmlDevice device, out int power);
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetPcieThroughput", ExactSpelling = true)]
private static extern NvmlReturn nvmlDeviceGetPcieThroughput(NvmlDevice device, NvmlPcieUtilCounter counter, out uint value);
[DllImport(LinuxDllName, EntryPoint = "nvmlDeviceGetPciInfo_v2")]
private static extern NvmlReturn nvmlDeviceGetPciInfo(NvmlDevice device, ref NvmlPciInfo pci);
private delegate NvmlReturn WindowsNvmlDelegate();
private delegate NvmlReturn WindowsNvmlGetHandleDelegate(int index, out NvmlDevice device);
private delegate NvmlReturn WindowsNvmlGetHandleByPciBusIdDelegate([MarshalAs(UnmanagedType.LPStr)] string pciBusId, out NvmlDevice device);
private delegate NvmlReturn WindowsNvmlGetPowerUsageDelegate(NvmlDevice device, out int power);
private delegate NvmlReturn WindowsNvmlDeviceGetPcieThroughputDelegate(NvmlDevice device, NvmlPcieUtilCounter counter, out uint value);
private delegate NvmlReturn WindowsNvmlDeviceGetPciInfo(NvmlDevice device, ref NvmlPciInfo pci);
[StructLayout(LayoutKind.Sequential)]
public struct NvmlDevice
{
public IntPtr Handle;
}
[StructLayout(LayoutKind.Sequential)]
public struct NvmlPciInfo
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string busId;
public uint domain;
public uint bus;
public uint device;
public ushort pciVendorId;
public ushort pciDeviceId;
public uint pciSubSystemId;
public uint reserved0;
public uint reserved1;
public uint reserved2;
public uint reserved3;
}
}
}
+37
View File
@@ -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;
}
}
}