Add Intel integrated GPU (#671)

Thanks to @bjarniivarsson.
This commit is contained in:
Bjarni Ivarsson
2022-02-26 10:14:09 +01:00
committed by GitHub
parent c94cb69ed0
commit 627f0a56ce
9 changed files with 276 additions and 11 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

@@ -35,6 +35,9 @@ namespace LibreHardwareMonitor.UI
case HardwareType.GpuAmd:
image = Utilities.EmbeddedResources.GetImage("amd.png");
break;
case HardwareType.GpuIntel:
image = Utilities.EmbeddedResources.GetImage("intel.png");
break;
case HardwareType.Storage:
image = Utilities.EmbeddedResources.GetImage("hdd.png");
break;
@@ -629,6 +629,8 @@ namespace LibreHardwareMonitor.Utilities
return "nvidia.png";
case HardwareType.GpuAmd:
return "ati.png";
case HardwareType.GpuIntel:
return "intel.png";
case HardwareType.Storage:
return "hdd.png";
case HardwareType.Motherboard:
+18 -3
View File
@@ -8,12 +8,14 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using LibreHardwareMonitor.Hardware.Battery;
using LibreHardwareMonitor.Hardware.Controller.AeroCool;
using LibreHardwareMonitor.Hardware.Controller.AquaComputer;
using LibreHardwareMonitor.Hardware.Controller.Heatmaster;
using LibreHardwareMonitor.Hardware.Controller.Nzxt;
using LibreHardwareMonitor.Hardware.Controller.TBalancer;
using LibreHardwareMonitor.Hardware.CPU;
using LibreHardwareMonitor.Hardware.Gpu;
using LibreHardwareMonitor.Hardware.Memory;
using LibreHardwareMonitor.Hardware.Motherboard;
@@ -145,9 +147,9 @@ namespace LibreHardwareMonitor.Hardware
if (_open && value != _cpuEnabled)
{
if (value)
Add(new CPU.CpuGroup(_settings));
Add(new CpuGroup(_settings));
else
RemoveType<CPU.CpuGroup>();
RemoveType<CpuGroup>();
}
_cpuEnabled = value;
@@ -166,11 +168,13 @@ namespace LibreHardwareMonitor.Hardware
{
Add(new AmdGpuGroup(_settings));
Add(new NvidiaGroup(_settings));
Add(new IntelGpuGroup(GetIntelCpus(), _settings));
}
else
{
RemoveType<AmdGpuGroup>();
RemoveType<NvidiaGroup>();
RemoveType<IntelGpuGroup>();
}
}
@@ -497,7 +501,7 @@ namespace LibreHardwareMonitor.Hardware
Add(new MotherboardGroup(_smbios, _settings));
if (_cpuEnabled)
Add(new CPU.CpuGroup(_settings));
Add(new CpuGroup(_settings));
if (_memoryEnabled)
Add(new MemoryGroup(_settings));
@@ -506,6 +510,7 @@ namespace LibreHardwareMonitor.Hardware
{
Add(new AmdGpuGroup(_settings));
Add(new NvidiaGroup(_settings));
Add(new IntelGpuGroup(GetIntelCpus(), _settings));
}
if (_controllerEnabled)
@@ -653,6 +658,16 @@ namespace LibreHardwareMonitor.Hardware
}
}
private List<IntelCpu> GetIntelCpus()
{
// Create a temporary cpu group if one has not been added.
lock (_lock)
{
IGroup cpuGroup = _groups.Find(x => x is CpuGroup) ?? new CpuGroup(_settings);
return cpuGroup.Hardware.Select(x => x as IntelCpu).ToList();
}
}
/// <summary>
/// <see cref="Computer" /> specific additional settings passed to its <see cref="IHardware" />.
/// </summary>
@@ -30,6 +30,8 @@ namespace LibreHardwareMonitor.Hardware.CPU
private readonly Sensor[] _powerSensors;
private readonly double _timeStampCounterMultiplier;
public float EnergyUnitsMultiplier => _energyUnitMultiplier;
public IntelCpu(int processorIndex, CpuId[][] cpuId, ISettings settings) : base(processorIndex, cpuId, settings)
{
// set tjMax
@@ -401,6 +403,9 @@ namespace LibreHardwareMonitor.Hardware.CPU
if (!Ring0.ReadMsr(_energyStatusMsrs[i], out eax, out uint _))
continue;
// Don't show the "GPU Graphics" sensor on windows, it will show up under the GPU instead.
if (i == 2 && !Software.OperatingSystem.IsUnix)
continue;
_lastEnergyTime[i] = DateTime.UtcNow;
_lastEnergyConsumed[i] = eax;
@@ -66,6 +66,7 @@ namespace LibreHardwareMonitor.Hardware
if (!adapterType.Value.HasFlag(D3dkmth.D3DKMT_ADAPTERTYPE_FLAGS.SoftwareDevice))
return false;
deviceInfo.Integrated = !adapterType.Value.HasFlag(D3dkmth.D3DKMT_ADAPTERTYPE_FLAGS.HybridIntegrated);
GetQueryStatisticsAdapterInformation(out status, adapter, out D3dkmth.D3DKMT_QUERYSTATISTICS_ADAPTER_INFORMATION adapterInformation);
if (status != WinNt.STATUS_SUCCESS)
@@ -93,13 +94,20 @@ namespace LibreHardwareMonitor.Hardware
deviceInfo.Nodes[nodeId] = new D3DDeviceNodeInfo
{
Id = nodeId,
Name = GetNodeEngineTypeString(nodeMetaData),
RunningTime = nodeInformation.GlobalInformation.RunningTime.QuadPart,
Id = nodeId,
Name = GetNodeEngineTypeString(nodeMetaData),
RunningTime = nodeInformation.GlobalInformation.RunningTime.QuadPart,
QueryTime = queryTime
};
}
GetSegmentSize(out status, adapter, out D3dkmth.D3DKMT_SEGMENTSIZEINFO segmentSizeInfo);
if (status != WinNt.STATUS_SUCCESS)
return false;
deviceInfo.GpuSharedLimit = segmentSizeInfo.SharedSystemMemorySize;
deviceInfo.GpuDedicatedLimit = segmentSizeInfo.DedicatedSystemMemorySize;
for (uint segmentId = 0; segmentId < segmentCount; segmentId++)
{
GetQueryStatisticsSegment(out status, adapter, segmentId, out D3dkmth.D3DKMT_QUERYSTATISTICS_SEGMENT_INFORMATION segmentInformation);
@@ -107,7 +115,6 @@ namespace LibreHardwareMonitor.Hardware
return false;
ulong commitLimit = segmentInformation.CommitLimit;
ulong bytesResident = segmentInformation.BytesResident;
ulong bytesCommitted = segmentInformation.BytesCommitted;
@@ -115,13 +122,11 @@ namespace LibreHardwareMonitor.Hardware
if (aperture == 1)
{
deviceInfo.GpuSharedLimit += commitLimit;
deviceInfo.GpuSharedUsed += bytesResident;
deviceInfo.GpuSharedMax += bytesCommitted;
}
else
{
deviceInfo.GpuDedicatedLimit += commitLimit;
deviceInfo.GpuDedicatedUsed += bytesResident;
deviceInfo.GpuDedicatedMax += bytesCommitted;
}
@@ -135,7 +140,7 @@ namespace LibreHardwareMonitor.Hardware
{
return nodeMetaData.NodeData.EngineType switch
{
D3dkmdt.DXGK_ENGINE_TYPE.DXGK_ENGINE_TYPE_OTHER => "D3D " + nodeMetaData.NodeData.FriendlyName,
D3dkmdt.DXGK_ENGINE_TYPE.DXGK_ENGINE_TYPE_OTHER => "D3D " + (!string.IsNullOrWhiteSpace(nodeMetaData.NodeData.FriendlyName) ? nodeMetaData.NodeData.FriendlyName : "Other"),
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",
@@ -148,6 +153,29 @@ namespace LibreHardwareMonitor.Hardware
};
}
private static void GetSegmentSize
(
out uint status,
D3dkmth.D3DKMT_OPENADAPTERFROMDEVICENAME adapter,
out D3dkmth.D3DKMT_SEGMENTSIZEINFO sizeInformation)
{
IntPtr segmentSizePtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(D3dkmth.D3DKMT_SEGMENTSIZEINFO)));
sizeInformation = new D3dkmth.D3DKMT_SEGMENTSIZEINFO();
Marshal.StructureToPtr(sizeInformation, segmentSizePtr, true);
var queryAdapterInfo = new D3dkmth.D3DKMT_QUERYADAPTERINFO
{
hAdapter = adapter.hAdapter,
Type = D3dkmth.KMTQUERYADAPTERINFOTYPE.KMTQAITYPE_GETSEGMENTSIZE,
pPrivateDriverData = segmentSizePtr,
PrivateDriverDataSize = Marshal.SizeOf(typeof(D3dkmth.D3DKMT_SEGMENTSIZEINFO))
};
status = Gdi32.D3DKMTQueryAdapterInfo(ref queryAdapterInfo);
sizeInformation = Marshal.PtrToStructure<D3dkmth.D3DKMT_SEGMENTSIZEINFO>(segmentSizePtr);
Marshal.FreeHGlobal(segmentSizePtr);
}
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)));
@@ -261,6 +289,7 @@ namespace LibreHardwareMonitor.Hardware
public ulong GpuDedicatedMax;
public D3DDeviceNodeInfo[] Nodes;
}
public bool Integrated;
}
}
}
@@ -0,0 +1,90 @@
// 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.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using LibreHardwareMonitor.Hardware.CPU;
namespace LibreHardwareMonitor.Hardware.Gpu
{
internal class IntelGpuGroup : IGroup
{
private readonly List<Hardware> _hardware = new();
private readonly StringBuilder _report = new();
public IntelGpuGroup(List<IntelCpu> intelCpus, ISettings settings)
{
if (!Software.OperatingSystem.IsUnix && intelCpus?.Count > 0)
{
_report.AppendLine("Intel GPU (D3D)");
_report.AppendLine();
string[] ids = D3DDisplayDevice.GetDeviceIdentifiers();
_report.Append("Number of adapters: ");
_report.AppendLine(ids.Length.ToString(CultureInfo.InvariantCulture));
_report.AppendLine();
for (int i = 0; i < ids.Length; i++)
{
string deviceId = ids[i];
bool isIntel = deviceId.IndexOf("VEN_8086", StringComparison.Ordinal) != -1;
_report.Append("AdapterIndex: ");
_report.AppendLine(i.ToString(CultureInfo.InvariantCulture));
_report.Append("DeviceId: ");
_report.AppendLine(deviceId);
_report.Append("IsIntel: ");
_report.AppendLine(isIntel.ToString(CultureInfo.InvariantCulture));
if (isIntel)
{
if (D3DDisplayDevice.GetDeviceInfoByIdentifier(deviceId, out D3DDisplayDevice.D3DDeviceInfo deviceInfo))
{
_report.Append("GpuSharedLimit: ");
_report.AppendLine(deviceInfo.GpuSharedLimit.ToString(CultureInfo.InvariantCulture));
_report.Append("GpuSharedUsed: ");
_report.AppendLine(deviceInfo.GpuSharedUsed.ToString(CultureInfo.InvariantCulture));
_report.Append("GpuSharedMax: ");
_report.AppendLine(deviceInfo.GpuSharedMax.ToString(CultureInfo.InvariantCulture));
_report.Append("GpuDedicatedLimit: ");
_report.AppendLine(deviceInfo.GpuDedicatedLimit.ToString(CultureInfo.InvariantCulture));
_report.Append("GpuDedicatedUsed: ");
_report.AppendLine(deviceInfo.GpuDedicatedUsed.ToString(CultureInfo.InvariantCulture));
_report.Append("GpuDedicatedMax: ");
_report.AppendLine(deviceInfo.GpuDedicatedMax.ToString(CultureInfo.InvariantCulture));
_report.Append("Integrated: ");
_report.AppendLine(deviceInfo.Integrated.ToString(CultureInfo.InvariantCulture));
if (deviceInfo.Integrated)
{
// It may seem strange to only use the first cpu here, but in-case we have a multi cpu system with integrated graphics (does that exist?),
// we would pick up the multiple device identifiers above and would add one instance for each CPU.
_hardware.Add(new IntelIntegratedGpu(intelCpus[0], deviceId, deviceInfo, settings));
}
}
}
_report.AppendLine();
}
}
}
public IReadOnlyList<IHardware> Hardware => _hardware;
public string GetReport()
{
return _report.ToString();
}
public void Close()
{
foreach (Hardware gpu in _hardware)
gpu.Close();
}
}
}
@@ -0,0 +1,120 @@
using Microsoft.Win32;
using System;
using System.Globalization;
using System.Linq;
namespace LibreHardwareMonitor.Hardware.Gpu
{
internal class IntelIntegratedGpu : Hardware
{
private readonly string _deviceId;
private readonly Sensor _dedicatedMemoryUsage;
private readonly D3DDisplayDevice.D3DDeviceInfo _deviceInfo;
private readonly float _energyUnitMultiplier;
private readonly CPU.IntelCpu _intelCpu;
private uint _lastEnergyConsumed;
private DateTime _lastEnergyTime;
private const uint MSR_RAPL_POWER_UNIT = 0x606;
private const uint MSR_PP1_ENERGY_STATUS = 0x641;
private readonly Sensor[] _nodeUsage;
private readonly DateTime[] _nodeUsagePrevTick;
private readonly long[] _nodeUsagePrevValue;
private readonly Sensor _powerSensor;
private readonly Sensor _sharedMemoryUsage;
public override HardwareType HardwareType => HardwareType.GpuIntel;
public IntelIntegratedGpu(CPU.IntelCpu intelCpu, string deviceId, D3DDisplayDevice.D3DDeviceInfo deviceInfo, ISettings settings)
: base(GetName(deviceId),
new Identifier("gpu-intel-integrated", deviceId.ToString(CultureInfo.InvariantCulture)),
settings)
{
_intelCpu = intelCpu;
_deviceId = deviceId;
_deviceInfo = deviceInfo;
var memorySensorIndex = 0;
if (_deviceInfo.GpuDedicatedLimit > 0)
{
_dedicatedMemoryUsage = new Sensor("D3D Dedicated Memory Used", memorySensorIndex++, SensorType.SmallData, this, settings);
}
_sharedMemoryUsage = new Sensor("D3D Shared Memory Used", memorySensorIndex++, SensorType.SmallData, this, settings);
if (Ring0.ReadMsr(MSR_RAPL_POWER_UNIT, out var eax, out var _))
{
_energyUnitMultiplier = _intelCpu.EnergyUnitsMultiplier;
if (_energyUnitMultiplier != 0)
{
_lastEnergyTime = DateTime.UtcNow;
_lastEnergyConsumed = eax;
_powerSensor = new Sensor("GPU Power", 0, SensorType.Power, this, settings);
ActivateSensor(_powerSensor);
}
}
_nodeUsage = new Sensor[deviceInfo.Nodes.Length];
_nodeUsagePrevValue = new long[deviceInfo.Nodes.Length];
_nodeUsagePrevTick = new DateTime[deviceInfo.Nodes.Length];
var nodeSensorIndex = 0;
foreach(var node in deviceInfo.Nodes.OrderBy(x => x.Name))
{
_nodeUsage[node.Id] = new Sensor(node.Name, nodeSensorIndex++, SensorType.Load, this, settings);
_nodeUsagePrevValue[node.Id] = node.RunningTime;
_nodeUsagePrevTick[node.Id] = node.QueryTime;
}
}
public override void Update()
{
if (D3DDisplayDevice.GetDeviceInfoByIdentifier(_deviceId, out D3DDisplayDevice.D3DDeviceInfo deviceInfo))
{
if (_dedicatedMemoryUsage != null)
{
_dedicatedMemoryUsage.Value = 1f * deviceInfo.GpuDedicatedUsed / 1024 / 1024;
ActivateSensor(_dedicatedMemoryUsage);
}
_sharedMemoryUsage.Value = 1f * deviceInfo.GpuSharedUsed / 1024 / 1024;
ActivateSensor(_sharedMemoryUsage);
if (_powerSensor != null && Ring0.ReadMsr(MSR_PP1_ENERGY_STATUS, out var eax, out var _))
{
var time = DateTime.UtcNow;
uint energyConsumed = eax;
float deltaTime = (float)(time - _lastEnergyTime).TotalSeconds;
if (deltaTime >= 0.01)
{
_powerSensor.Value = _energyUnitMultiplier * unchecked(energyConsumed - _lastEnergyConsumed) / deltaTime;
_lastEnergyTime = time;
_lastEnergyConsumed = energyConsumed;
}
}
foreach (var node in deviceInfo.Nodes)
{
long runningTimeDiff = node.RunningTime - _nodeUsagePrevValue[node.Id];
long timeDiff = node.QueryTime.Ticks - _nodeUsagePrevTick[node.Id].Ticks;
_nodeUsage[node.Id].Value = 100f * runningTimeDiff / timeDiff;
_nodeUsagePrevValue[node.Id] = node.RunningTime;
_nodeUsagePrevTick[node.Id] = node.QueryTime;
ActivateSensor(_nodeUsage[node.Id]);
}
}
}
private static string GetName(string deviceId)
{
var path = @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\" + D3DDisplayDevice.GetActualDeviceIdentifier(deviceId);
if (Registry.GetValue(path, "DeviceDesc", null) is string deviceDesc)
{
return deviceDesc.Split(';').Last();
}
return "Intel Integrated Graphics";
}
}
}
@@ -17,6 +17,7 @@ namespace LibreHardwareMonitor.Hardware
Memory,
GpuNvidia,
GpuAmd,
GpuIntel,
Storage,
Network,
Cooler,