From 035a878e2015870b660f1d3e28ceaa95a05b0349 Mon Sep 17 00:00:00 2001 From: jasonlyoin <15674058+jaslioin@users.noreply.github.com> Date: Thu, 16 Apr 2026 22:17:04 +1000 Subject: [PATCH] NVIDIA GPU: reserve load index 3 for GPU Memory, remap other loads (#2310) * NVIDIA GPU: reserve load index 3 for GPU Memory, remap other loads * NVIDIA GPU: simplify load sensor indexing * NVIDIA GPU: create GPU Memory load after utilization loads Place the GPU Memory Load sensor before power topology and D3D node loads so it appears with other GPU metrics in the UI. Load indices advance in the same order as before for uniqueness. * NVIDIA GPU: use local nextLoadIndex in constructor Replace the instance field with a ctor-local counter for Load sensor indices. --- .../Hardware/Gpu/NvidiaGpu.cs | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGpu.cs b/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGpu.cs index d281a09..9cb56c0 100644 --- a/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGpu.cs +++ b/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGpu.cs @@ -246,6 +246,8 @@ internal sealed class NvidiaGpu : GenericGpu } } + int nextLoadIndex = 0; + // Load usages. NvApi.NvDynamicPStatesInfo pStatesInfo = GetDynamicPstatesInfoEx(out status); if (status == NvApi.NvStatus.OK) @@ -260,7 +262,7 @@ internal sealed class NvidiaGpu : GenericGpu string name = GetUtilizationDomainName(utilizationDomain); if (name != null) - loads.Add(new Sensor(name, index, SensorType.Load, this, settings)); + loads.Add(new Sensor(name, nextLoadIndex++, SensorType.Load, this, settings)); } } @@ -287,7 +289,7 @@ internal sealed class NvidiaGpu : GenericGpu string name = GetUtilizationDomainName(utilizationDomain); if (name != null) - loads.Add(new Sensor(name, index, SensorType.Load, this, settings)); + loads.Add(new Sensor(name, nextLoadIndex++, SensorType.Load, this, settings)); } } @@ -301,6 +303,9 @@ internal sealed class NvidiaGpu : GenericGpu } } + // GPU Memory load: created after NVAPI utilization loads so it appears with other GPU metrics (before power/D3D loads). + _memoryLoad = new Sensor("GPU Memory", nextLoadIndex++, SensorType.Load, this, settings); + // Power. NvApi.NvPowerTopology powerTopology = GetPowerTopology(out NvApi.NvStatus powerStatus); if (powerStatus == NvApi.NvStatus.OK && powerTopology.Count > 0) @@ -318,7 +323,7 @@ internal sealed class NvidiaGpu : GenericGpu if (name != null) { - _powers[i] = new Sensor(name, i + (_loads?.Length ?? 0), SensorType.Load, this, settings); + _powers[i] = new Sensor(name, nextLoadIndex++, SensorType.Load, this, settings); ActivateSensor(_powers[i]); } } @@ -356,6 +361,7 @@ internal sealed class NvidiaGpu : GenericGpu string[] deviceIds = D3DDisplayDevice.GetDeviceIdentifiers(); if (deviceIds != null) { + int d3dLoadStartIndex = nextLoadIndex; foreach (string deviceId in deviceIds) { if (deviceId.IndexOf("VEN_" + pci.pciVendorId.ToString("X"), StringComparison.OrdinalIgnoreCase) != -1 && @@ -417,9 +423,8 @@ internal sealed class NvidiaGpu : GenericGpu if (isMatch && D3DDisplayDevice.GetDeviceInfoByIdentifier(deviceId, out D3DDisplayDevice.D3DDeviceInfo deviceInfo)) { - int sensorCount = (_loads?.Length ?? 0) + (_powers?.Length ?? 0); - int loadSensorIndex = sensorCount > 0 ? sensorCount + 1 : 0; int smallDataSensorIndex = 3; // There are three normal GPU memory sensors. + int nextD3dLoadIndex = d3dLoadStartIndex; _d3dDeviceId = deviceId; @@ -432,10 +437,12 @@ internal sealed class NvidiaGpu : GenericGpu foreach (D3DDisplayDevice.D3DDeviceNodeInfo node in deviceInfo.Nodes.OrderBy(x => x.Name)) { - _gpuNodeUsage[node.Id] = new Sensor(node.Name, loadSensorIndex++, SensorType.Load, this, settings); + _gpuNodeUsage[node.Id] = new Sensor(node.Name, nextD3dLoadIndex++, SensorType.Load, this, settings); _gpuNodeUsagePrevValue[node.Id] = node.RunningTime; _gpuNodeUsagePrevTick[node.Id] = node.QueryTime; } + + nextLoadIndex = nextD3dLoadIndex; } } } @@ -448,7 +455,6 @@ internal sealed class NvidiaGpu : GenericGpu _memoryFree = new Sensor("GPU Memory Free", 0, SensorType.SmallData, this, settings); _memoryUsed = new Sensor("GPU Memory Used", 1, SensorType.SmallData, this, settings); _memoryTotal = new Sensor("GPU Memory Total", 2, SensorType.SmallData, this, settings); - _memoryLoad = new Sensor("GPU Memory", 3, SensorType.Load, this, settings); // Pin power sensors for NVIDIA RTX Astral series from ASUS if (NvApi.NvAPI_I2CReadEx != null && NvApi.NvAPI_GPU_GetPCIIdentifiers != null)