From d1cff075719694ef4d3f75061b044cb7143035a4 Mon Sep 17 00:00:00 2001 From: Phyxion <> Date: Fri, 31 Jan 2020 15:21:37 +0100 Subject: [PATCH] Fixes #196 Switch to bus id instead of adapter index. --- .../Hardware/Gpu/NvidiaGpu.cs | 8 ++++- .../Hardware/Gpu/NvidiaGroup.cs | 18 +++++----- LibreHardwareMonitorLib/Interop/NvApi.cs | 5 +++ LibreHardwareMonitorLib/Interop/NvidiaML.cs | 33 ++++++++++++++++++- 4 files changed, 52 insertions(+), 12 deletions(-) diff --git a/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGpu.cs b/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGpu.cs index 7ce54ea..2e86859 100644 --- a/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGpu.cs +++ b/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGpu.cs @@ -35,6 +35,8 @@ namespace LibreHardwareMonitor.Hardware.Gpu _handle = handle; _displayHandle = displayHandle; + bool hasPciBusId = NvApi.NvAPI_GPU_GetBusId(handle, out uint busId) == NvApi.NvStatus.OK; + NvApi.NvGPUThermalSettings thermalSettings = GetThermalSettings(); _temperatures = new Sensor[thermalSettings.Count]; for (int i = 0; i < _temperatures.Length; i++) @@ -105,7 +107,11 @@ namespace LibreHardwareMonitor.Hardware.Gpu if (NvidiaML.IsAvailable) { - _nvmlDevice = NvidiaML.NvmlDeviceGetHandleByIndex(adapterIndex); + if (hasPciBusId) + _nvmlDevice = NvidiaML.NvmlDeviceGetHandleByPciBusId($" 0000:{busId:X2}:00.0") ?? NvidiaML.NvmlDeviceGetHandleByIndex(_adapterIndex); + else + _nvmlDevice = NvidiaML.NvmlDeviceGetHandleByIndex(_adapterIndex); + if (_nvmlDevice.HasValue) { _powerUsage = new Sensor("GPU Package", 0, SensorType.Power, this, settings); diff --git a/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGroup.cs b/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGroup.cs index 7183db1..27aadfe 100644 --- a/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGroup.cs +++ b/LibreHardwareMonitorLib/Hardware/Gpu/NvidiaGroup.cs @@ -31,7 +31,6 @@ namespace LibreHardwareMonitor.Hardware.Gpu } NvApi.NvPhysicalGpuHandle[] handles = new NvApi.NvPhysicalGpuHandle[NvApi.MAX_PHYSICAL_GPUS]; - int count; if (NvApi.NvAPI_EnumPhysicalGPUs == null) { _report.AppendLine("Error: NvAPI_EnumPhysicalGPUs not available"); @@ -39,27 +38,26 @@ namespace LibreHardwareMonitor.Hardware.Gpu return; } + NvApi.NvStatus status = NvApi.NvAPI_EnumPhysicalGPUs(handles, out int count); + if (status != NvApi.NvStatus.OK) { - NvApi.NvStatus status = NvApi.NvAPI_EnumPhysicalGPUs(handles, out count); - if (status != NvApi.NvStatus.OK) - { - _report.AppendLine("Status: " + status); - _report.AppendLine(); - return; - } + _report.AppendLine("Status: " + status); + _report.AppendLine(); + return; } IDictionary displayHandles = new Dictionary(); if (NvApi.NvAPI_EnumNvidiaDisplayHandle != null && NvApi.NvAPI_GetPhysicalGPUsFromDisplay != null) { - NvApi.NvStatus status = NvApi.NvStatus.OK; + status = NvApi.NvStatus.OK; int i = 0; while (status == NvApi.NvStatus.OK) { NvApi.NvDisplayHandle displayHandle = new NvApi.NvDisplayHandle(); status = NvApi.NvAPI_EnumNvidiaDisplayHandle(i, ref displayHandle); i++; - + NvApi.NvDisplayHandle a; + if (status == NvApi.NvStatus.OK) { NvApi.NvPhysicalGpuHandle[] handlesFromDisplay = new NvApi.NvPhysicalGpuHandle[NvApi.MAX_PHYSICAL_GPUS]; diff --git a/LibreHardwareMonitorLib/Interop/NvApi.cs b/LibreHardwareMonitorLib/Interop/NvApi.cs index d96f1f9..d0062e1 100644 --- a/LibreHardwareMonitorLib/Interop/NvApi.cs +++ b/LibreHardwareMonitorLib/Interop/NvApi.cs @@ -41,6 +41,7 @@ namespace LibreHardwareMonitor.Interop public static readonly NvAPI_GPU_GetPCIIdentifiersDelegate NvAPI_GPU_GetPCIIdentifiers; public static readonly NvAPI_GPU_GetPStatesDelegate NvAPI_GPU_GetPStates; public static readonly NvAPI_GPU_GetTachReadingDelegate NvAPI_GPU_GetTachReading; + public static readonly NvAPI_GPU_GetBusIdDelegate NvAPI_GPU_GetBusId; public static readonly NvAPI_GPU_GetThermalSettingsDelegate NvAPI_GPU_GetThermalSettings; public static readonly NvAPI_GPU_GetUsagesDelegate NvAPI_GPU_GetUsages; @@ -91,6 +92,9 @@ namespace LibreHardwareMonitor.Interop [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate NvStatus NvAPI_GPU_SetCoolerLevelsDelegate(NvPhysicalGpuHandle gpuHandle, int coolerIndex, ref NvGPUCoolerLevels NvGPUCoolerLevels); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate NvStatus NvAPI_GPU_GetBusIdDelegate(NvPhysicalGpuHandle gpuHandle, out uint busId); + static NvApi() { NvAPI_InitializeDelegate nvApiInitialize; @@ -129,6 +133,7 @@ namespace LibreHardwareMonitor.Interop GetDelegate(0xF951A4D1, out NvAPI_GetDisplayDriverVersion); GetDelegate(0x01053FA5, out _nvAPI_GetInterfaceVersionString); GetDelegate(0x2DDFB66E, out NvAPI_GPU_GetPCIIdentifiers); + GetDelegate(0x1BE0B8E5, out NvAPI_GPU_GetBusId); IsAvailable = true; } diff --git a/LibreHardwareMonitorLib/Interop/NvidiaML.cs b/LibreHardwareMonitorLib/Interop/NvidiaML.cs index ea70501..5bd4c53 100644 --- a/LibreHardwareMonitorLib/Interop/NvidiaML.cs +++ b/LibreHardwareMonitorLib/Interop/NvidiaML.cs @@ -16,6 +16,7 @@ namespace LibreHardwareMonitor.Interop private static WindowsNvmlGetHandleDelegate _windowsNvmlDeviceGetHandleByIndex; private static WindowsNvmlGetPowerUsageDelegate _windowsNvmlDeviceGetPowerUsage; + private static WindowsNvmlGetHandleByPciBusIdDelegate _windowsNvmlDeviceGetHandleByPciBusId; private static WindowsNvmlDelegate _windowsNvmlInit; private static WindowsNvmlDelegate _windowsNvmlShutdown; @@ -118,6 +119,11 @@ namespace LibreHardwareMonitor.Interop 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; } @@ -165,6 +171,26 @@ namespace LibreHardwareMonitor.Interop return null; } + + internal static NvmlDevice? NvmlDeviceGetHandleByPciBusId(string pciBusId) + { + if (IsAvailable) + { + NvmlDevice nvmlDevice; + if (Software.OperatingSystem.IsLinux) + { + 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) @@ -197,6 +223,9 @@ namespace LibreHardwareMonitor.Interop [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); @@ -207,8 +236,10 @@ namespace LibreHardwareMonitor.Interop private delegate NvmlReturn WindowsNvmlGetHandleDelegate(int index, out NvmlDevice device); - private delegate NvmlReturn WindowsNvmlGetPowerUsageDelegate(NvmlDevice device, out int power); + private delegate NvmlReturn WindowsNvmlGetHandleByPciBusIdDelegate([MarshalAs(UnmanagedType.LPStr)] string pciBusId, out NvmlDevice device); + private delegate NvmlReturn WindowsNvmlGetPowerUsageDelegate(NvmlDevice device, out int power); + [StructLayout(LayoutKind.Sequential)] internal struct NvmlDevice {