Improved the support for Nvidia GPUs.
authormoel.mich
Sun, 27 Jun 2010 10:24:27 +0000
changeset 14004a5155c9c1a
parent 139 9611b4d9d898
child 141 a78cc5c55216
Improved the support for Nvidia GPUs.
Hardware/Nvidia/NVAPI.cs
Hardware/Nvidia/NvidiaGPU.cs
Hardware/Nvidia/NvidiaGroup.cs
     1.1 --- a/Hardware/Nvidia/NVAPI.cs	Sat Jun 12 12:15:00 2010 +0000
     1.2 +++ b/Hardware/Nvidia/NVAPI.cs	Sun Jun 27 10:24:27 2010 +0000
     1.3 @@ -125,16 +125,16 @@
     1.4    [StructLayout(LayoutKind.Sequential, Pack = 8)]
     1.5    public struct NvSensor {
     1.6      public NvThermalController Controller;
     1.7 -    public int DefaultMinTemp;
     1.8 -    public int DefaultMaxTemp;
     1.9 -    public int CurrentTemp;
    1.10 +    public uint DefaultMinTemp;
    1.11 +    public uint DefaultMaxTemp;
    1.12 +    public uint CurrentTemp;
    1.13      public NvThermalTarget Target;     
    1.14    }
    1.15  
    1.16    [StructLayout(LayoutKind.Sequential, Pack = 8)]
    1.17    public struct NvGPUThermalSettings {
    1.18 -    public int Version;
    1.19 -    public int Count;
    1.20 +    public uint Version;
    1.21 +    public uint Count;
    1.22      [MarshalAs(UnmanagedType.ByValArray, 
    1.23        SizeConst = NVAPI.MAX_THERMAL_SENSORS_PER_GPU)]
    1.24      public NvSensor[] Sensor;
    1.25 @@ -150,15 +150,104 @@
    1.26      private IntPtr ptr;
    1.27    }
    1.28  
    1.29 +  [StructLayout(LayoutKind.Sequential, Pack = 8)]
    1.30 +  public struct NvClocks {
    1.31 +    public uint Version;
    1.32 +    [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_CLOCKS_PER_GPU)]
    1.33 +    public uint[] Clock;
    1.34 +  }
    1.35 +
    1.36 +  [StructLayout(LayoutKind.Sequential, Pack = 8)]
    1.37 +  public struct NvPState {
    1.38 +    public bool Present;
    1.39 +    public int Percentage;
    1.40 +  }
    1.41 +
    1.42 +  [StructLayout(LayoutKind.Sequential, Pack = 8)]
    1.43 +  public struct NvPStates {
    1.44 +    public uint Version;
    1.45 +    public uint Flags;
    1.46 +    [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_PSTATES_PER_GPU)]
    1.47 +    public NvPState[] PStates;
    1.48 +  }
    1.49 +
    1.50 +  [StructLayout(LayoutKind.Sequential, Pack = 8)]
    1.51 +  public struct NvUsages {
    1.52 +    public uint Version;
    1.53 +    [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_USAGES_PER_GPU)]
    1.54 +    public uint[] Usage;
    1.55 +  }
    1.56 +
    1.57 +  [StructLayout(LayoutKind.Sequential, Pack = 8)]
    1.58 +  public struct NvCooler {
    1.59 +    public int Type;
    1.60 +    public int Controller;
    1.61 +    public int DefaultMin;
    1.62 +    public int DefaultMax;
    1.63 +    public int CurrentMin;
    1.64 +    public int CurrentMax;
    1.65 +    public int CurrentLevel;
    1.66 +    public int DefaultPolicy;
    1.67 +    public int CurrentPolicy;
    1.68 +    public int Target;
    1.69 +    public int ControlType;
    1.70 +    public int Active;
    1.71 +  }
    1.72 +
    1.73 +  [StructLayout(LayoutKind.Sequential, Pack = 8)]
    1.74 +  public struct NvGPUCoolerSettings {
    1.75 +    public uint Version;
    1.76 +    public uint Count;
    1.77 +    [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_COOLER_PER_GPU)]
    1.78 +    public NvCooler[] Cooler;
    1.79 +  }
    1.80 +
    1.81 +  [StructLayout(LayoutKind.Sequential, Pack = 8)]
    1.82 +  public struct NvMemoryInfo {
    1.83 +    public uint Version;
    1.84 +    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 
    1.85 +      NVAPI.MAX_MEMORY_VALUES_PER_GPU)]
    1.86 +    public uint[] Values;
    1.87 +  }
    1.88 +
    1.89 +  [StructLayout(LayoutKind.Sequential, Pack = 8)]
    1.90 +  public struct NvDisplayDriverVersion {
    1.91 +    public uint Version;
    1.92 +    public uint DriverVersion;
    1.93 +    public uint BldChangeListNum;
    1.94 +    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NVAPI.SHORT_STRING_MAX)]
    1.95 +    public string BuildBranch;
    1.96 +    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NVAPI.SHORT_STRING_MAX)]
    1.97 +    public string Adapter;
    1.98 +  } 
    1.99 +
   1.100    public class NVAPI {
   1.101 -          
   1.102 -    private const int SHORT_STRING_MAX = 64;
   1.103  
   1.104 -    public const int MAX_THERMAL_SENSORS_PER_GPU = 3;
   1.105      public const int MAX_PHYSICAL_GPUS = 64;
   1.106 -    public static readonly int GPU_THERMAL_SETTINGS_VER =
   1.107 +    public const int SHORT_STRING_MAX = 64;
   1.108 +
   1.109 +    public const int MAX_THERMAL_SENSORS_PER_GPU = 3;    
   1.110 +    public const int MAX_CLOCKS_PER_GPU = 0x120;
   1.111 +    public const int MAX_PSTATES_PER_GPU = 8;
   1.112 +    public const int MAX_USAGES_PER_GPU = 33;
   1.113 +    public const int MAX_COOLER_PER_GPU = 20;
   1.114 +    public const int MAX_MEMORY_VALUES_PER_GPU = 5;
   1.115 +
   1.116 +    public static readonly uint GPU_THERMAL_SETTINGS_VER = (uint)
   1.117        Marshal.SizeOf(typeof(NvGPUThermalSettings)) | 0x10000;
   1.118 -            
   1.119 +    public static readonly uint GPU_CLOCKS_VER = (uint)
   1.120 +      Marshal.SizeOf(typeof(NvClocks)) | 0x20000;
   1.121 +    public static readonly uint GPU_PSTATES_VER = (uint)
   1.122 +      Marshal.SizeOf(typeof(NvPStates)) | 0x10000;
   1.123 +    public static readonly uint GPU_USAGES_VER = (uint)
   1.124 +      Marshal.SizeOf(typeof(NvUsages)) | 0x10000;
   1.125 +    public static readonly uint GPU_COOLER_SETTINGS_VER = (uint)
   1.126 +      Marshal.SizeOf(typeof(NvGPUCoolerSettings)) | 0x20000;
   1.127 +    public static readonly uint GPU_MEMORY_INFO_VER = (uint) 
   1.128 +      Marshal.SizeOf(typeof(NvMemoryInfo)) | 0x20000;
   1.129 +    public static readonly uint DISPLAY_DRIVER_VERSION_VER = (uint)
   1.130 +      Marshal.SizeOf(typeof(NvDisplayDriverVersion)) | 0x10000;
   1.131 +      
   1.132      private delegate IntPtr nvapi_QueryInterfaceDelegate(uint id);
   1.133      private delegate NvStatus NvAPI_InitializeDelegate();
   1.134      private delegate NvStatus NvAPI_GPU_GetFullNameDelegate(
   1.135 @@ -171,27 +260,57 @@
   1.136        ref NvDisplayHandle displayHandle);
   1.137      public delegate NvStatus NvAPI_GetPhysicalGPUsFromDisplayDelegate(
   1.138        NvDisplayHandle displayHandle, [Out] NvPhysicalGpuHandle[] gpuHandles, 
   1.139 -      out int gpuCount);
   1.140 +      out uint gpuCount);
   1.141      public delegate NvStatus NvAPI_EnumPhysicalGPUsDelegate(
   1.142        [Out] NvPhysicalGpuHandle[] gpuHandles, out int gpuCount);
   1.143      public delegate NvStatus NvAPI_GPU_GetTachReadingDelegate(
   1.144        NvPhysicalGpuHandle gpuHandle, out int value);
   1.145 +    public delegate NvStatus NvAPI_GPU_GetAllClocksDelegate(
   1.146 +      NvPhysicalGpuHandle gpuHandle, ref NvClocks nvClocks);
   1.147 +    public delegate NvStatus NvAPI_GPU_GetPStatesDelegate(
   1.148 +      NvPhysicalGpuHandle gpuHandle, ref NvPStates nvPStates);
   1.149 +    public delegate NvStatus NvAPI_GPU_GetUsagesDelegate(
   1.150 +      NvPhysicalGpuHandle gpuHandle, ref NvUsages nvUsages);
   1.151 +    public delegate NvStatus NvAPI_GPU_GetCoolerSettingsDelegate(
   1.152 +      NvPhysicalGpuHandle gpuHandle, int coolerIndex,
   1.153 +      ref NvGPUCoolerSettings nvGPUCoolerSettings);
   1.154 +    public delegate NvStatus NvAPI_GPU_GetMemoryInfoDelegate(
   1.155 +      NvDisplayHandle displayHandle, ref NvMemoryInfo nvMemoryInfo);
   1.156 +    public delegate NvStatus NvAPI_GetDisplayDriverVersionDelegate(
   1.157 +      NvDisplayHandle displayHandle, [In, Out] ref NvDisplayDriverVersion
   1.158 +      nvDisplayDriverVersion);
   1.159 +    public delegate NvStatus NvAPI_GetInterfaceVersionStringDelegate(
   1.160 +      StringBuilder version);
   1.161  
   1.162      private static bool available = false;
   1.163      private static nvapi_QueryInterfaceDelegate nvapi_QueryInterface;
   1.164      private static NvAPI_InitializeDelegate NvAPI_Initialize;
   1.165      private static NvAPI_GPU_GetFullNameDelegate _NvAPI_GPU_GetFullName;
   1.166 +    private static NvAPI_GetInterfaceVersionStringDelegate
   1.167 +      _NvAPI_GetInterfaceVersionString;
   1.168  
   1.169 -    public static NvAPI_GPU_GetThermalSettingsDelegate 
   1.170 +    public static readonly NvAPI_GPU_GetThermalSettingsDelegate 
   1.171        NvAPI_GPU_GetThermalSettings;
   1.172 -    public static NvAPI_EnumNvidiaDisplayHandleDelegate
   1.173 +    public static readonly NvAPI_EnumNvidiaDisplayHandleDelegate
   1.174        NvAPI_EnumNvidiaDisplayHandle;
   1.175 -    public static NvAPI_GetPhysicalGPUsFromDisplayDelegate
   1.176 +    public static readonly NvAPI_GetPhysicalGPUsFromDisplayDelegate
   1.177        NvAPI_GetPhysicalGPUsFromDisplay;
   1.178 -    public static NvAPI_EnumPhysicalGPUsDelegate
   1.179 +    public static readonly NvAPI_EnumPhysicalGPUsDelegate
   1.180        NvAPI_EnumPhysicalGPUs;
   1.181 -    public static NvAPI_GPU_GetTachReadingDelegate
   1.182 +    public static readonly NvAPI_GPU_GetTachReadingDelegate
   1.183        NvAPI_GPU_GetTachReading;
   1.184 +    public static readonly NvAPI_GPU_GetAllClocksDelegate
   1.185 +      NvAPI_GPU_GetAllClocks;
   1.186 +    public static readonly NvAPI_GPU_GetPStatesDelegate
   1.187 +      NvAPI_GPU_GetPStates;
   1.188 +    public static readonly NvAPI_GPU_GetUsagesDelegate
   1.189 +      NvAPI_GPU_GetUsages;
   1.190 +    public static readonly NvAPI_GPU_GetCoolerSettingsDelegate
   1.191 +      NvAPI_GPU_GetCoolerSettings;
   1.192 +    public static readonly NvAPI_GPU_GetMemoryInfoDelegate
   1.193 +      NvAPI_GPU_GetMemoryInfo;
   1.194 +    public static readonly NvAPI_GetDisplayDriverVersionDelegate
   1.195 +      NvAPI_GetDisplayDriverVersion;    
   1.196  
   1.197      public static NvStatus NvAPI_GPU_GetFullName(NvPhysicalGpuHandle gpuHandle,
   1.198        out string name) {
   1.199 @@ -205,6 +324,17 @@
   1.200        return status;
   1.201      }
   1.202  
   1.203 +    public static NvStatus NvAPI_GetInterfaceVersionString(out string version) {
   1.204 +      StringBuilder builder = new StringBuilder(SHORT_STRING_MAX);
   1.205 +      NvStatus status;
   1.206 +      if (_NvAPI_GetInterfaceVersionString != null)
   1.207 +        status = _NvAPI_GetInterfaceVersionString(builder);
   1.208 +      else
   1.209 +        status = NvStatus.FUNCTION_NOT_FOUND;
   1.210 +      version = builder.ToString();
   1.211 +      return status;
   1.212 +    }
   1.213 +
   1.214      private static string GetDllName() {
   1.215        if (IntPtr.Size == 4) {
   1.216          return "nvapi.dll";
   1.217 @@ -245,7 +375,15 @@
   1.218          GetDelegate(0x9ABDD40D, out NvAPI_EnumNvidiaDisplayHandle);
   1.219          GetDelegate(0x34EF9506, out NvAPI_GetPhysicalGPUsFromDisplay);
   1.220          GetDelegate(0xE5AC921F, out NvAPI_EnumPhysicalGPUs);
   1.221 -        GetDelegate(0x5F608315, out NvAPI_GPU_GetTachReading);        
   1.222 +        GetDelegate(0x5F608315, out NvAPI_GPU_GetTachReading);
   1.223 +        GetDelegate(0x1BD69F49, out NvAPI_GPU_GetAllClocks);
   1.224 +        GetDelegate(0x60DED2ED, out NvAPI_GPU_GetPStates);
   1.225 +        GetDelegate(0x189A1FDF, out NvAPI_GPU_GetUsages);
   1.226 +        GetDelegate(0xDA141340, out NvAPI_GPU_GetCoolerSettings);
   1.227 +        GetDelegate(0x774AA982, out NvAPI_GPU_GetMemoryInfo);
   1.228 +        GetDelegate(0xF951A4D1, out NvAPI_GetDisplayDriverVersion);
   1.229 +        GetDelegate(0x01053FA5, out _NvAPI_GetInterfaceVersionString);
   1.230 +
   1.231          available = true;
   1.232        }
   1.233      }
     2.1 --- a/Hardware/Nvidia/NvidiaGPU.cs	Sat Jun 12 12:15:00 2010 +0000
     2.2 +++ b/Hardware/Nvidia/NvidiaGPU.cs	Sun Jun 27 10:24:27 2010 +0000
     2.3 @@ -38,6 +38,7 @@
     2.4  using System;
     2.5  using System.Collections.Generic;
     2.6  using System.Drawing;
     2.7 +using System.Text;
     2.8  
     2.9  namespace OpenHardwareMonitor.Hardware.Nvidia {
    2.10    public class NvidiaGPU : Hardware, IHardware {
    2.11 @@ -46,11 +47,18 @@
    2.12      private Image icon;
    2.13      private int adapterIndex;
    2.14      private NvPhysicalGpuHandle handle;
    2.15 +    private NvDisplayHandle? displayHandle;
    2.16  
    2.17      private Sensor[] temperatures;
    2.18      private Sensor fan = null;
    2.19 +    private Sensor[] clocks;
    2.20 +    private Sensor[] loads;
    2.21 +    private Sensor control;
    2.22 +    private Sensor memoryLoad;
    2.23  
    2.24 -    public NvidiaGPU(int adapterIndex, NvPhysicalGpuHandle handle) {
    2.25 +    public NvidiaGPU(int adapterIndex, NvPhysicalGpuHandle handle, 
    2.26 +      NvDisplayHandle? displayHandle) 
    2.27 +    {
    2.28        string gpuName;
    2.29        if (NVAPI.NvAPI_GPU_GetFullName(handle, out gpuName) == NvStatus.OK) {
    2.30          this.name = "NVIDIA " + gpuName.Trim();
    2.31 @@ -60,6 +68,7 @@
    2.32        this.icon = Utilities.EmbeddedResources.GetImage("nvidia.png");
    2.33        this.adapterIndex = adapterIndex;
    2.34        this.handle = handle;
    2.35 +      this.displayHandle = displayHandle;
    2.36  
    2.37        NvGPUThermalSettings settings = GetThermalSettings();
    2.38        temperatures = new Sensor[settings.Count];
    2.39 @@ -87,6 +96,21 @@
    2.40            ActivateSensor(fan);
    2.41          }
    2.42        }
    2.43 +
    2.44 +      clocks = new Sensor[3];
    2.45 +      clocks[0] = new Sensor("GPU Core", 0, SensorType.Clock, this);
    2.46 +      clocks[1] = new Sensor("GPU Memory", 1, SensorType.Clock, this);
    2.47 +      clocks[2] = new Sensor("GPU Shader", 2, SensorType.Clock, this);
    2.48 +      for (int i = 0; i < clocks.Length; i++)
    2.49 +        ActivateSensor(clocks[i]);
    2.50 +
    2.51 +      loads = new Sensor[3];
    2.52 +      loads[0] = new Sensor("GPU Core", 0, SensorType.Load, this);
    2.53 +      loads[1] = new Sensor("GPU Memory Controller", 1, SensorType.Load, this);
    2.54 +      loads[2] = new Sensor("GPU Video Engine", 2, SensorType.Load, this);
    2.55 +      memoryLoad = new Sensor("GPU Memory", 3, SensorType.Load, this);
    2.56 +
    2.57 +      control = new Sensor("GPU Fan", 0, SensorType.Control, this);
    2.58      }
    2.59  
    2.60      public override string Name {
    2.61 @@ -106,13 +130,25 @@
    2.62        settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
    2.63        settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
    2.64        settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
    2.65 -      if (NVAPI.NvAPI_GPU_GetThermalSettings(handle, (int)NvThermalTarget.ALL,
    2.66 +      if (NVAPI.NvAPI_GPU_GetThermalSettings != null &&
    2.67 +        NVAPI.NvAPI_GPU_GetThermalSettings(handle, (int)NvThermalTarget.ALL,
    2.68          ref settings) != NvStatus.OK) {
    2.69          settings.Count = 0;        
    2.70        }
    2.71        return settings;
    2.72      }
    2.73  
    2.74 +    private uint[] GetClocks() {
    2.75 +      NvClocks clocks = new NvClocks();
    2.76 +      clocks.Version = NVAPI.GPU_CLOCKS_VER;
    2.77 +      clocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
    2.78 +      if (NVAPI.NvAPI_GPU_GetAllClocks != null &&
    2.79 +        NVAPI.NvAPI_GPU_GetAllClocks(handle, ref clocks) == NvStatus.OK) {
    2.80 +        return clocks.Clock;
    2.81 +      }
    2.82 +      return null;
    2.83 +    }
    2.84 +
    2.85      public override void Update() {
    2.86        NvGPUThermalSettings settings = GetThermalSettings();
    2.87        foreach (Sensor sensor in temperatures) 
    2.88 @@ -123,6 +159,264 @@
    2.89          NVAPI.NvAPI_GPU_GetTachReading(handle, out value);
    2.90          fan.Value = value;
    2.91        }
    2.92 +
    2.93 +      uint[] values = GetClocks();
    2.94 +      if (values != null) {
    2.95 +        clocks[0].Value = 0.001f * values[0];
    2.96 +        clocks[1].Value = 0.001f * values[8];
    2.97 +        clocks[2].Value = 0.001f * values[14];
    2.98 +        if (values[30] != 0) {
    2.99 +          clocks[0].Value = 0.0005f * values[30];
   2.100 +          clocks[2].Value = 0.001f * values[30];
   2.101 +        }
   2.102 +      }
   2.103 +
   2.104 +      NvPStates states = new NvPStates();
   2.105 +      states.Version = NVAPI.GPU_PSTATES_VER;
   2.106 +      states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
   2.107 +      if (NVAPI.NvAPI_GPU_GetPStates != null && 
   2.108 +        NVAPI.NvAPI_GPU_GetPStates(handle, ref states) == NvStatus.OK) {
   2.109 +        for (int i = 0; i < 3; i++)
   2.110 +          if (states.PStates[i].Present) {
   2.111 +            loads[i].Value = states.PStates[i].Percentage;
   2.112 +            ActivateSensor(loads[i]);
   2.113 +          }
   2.114 +      } else {
   2.115 +        NvUsages usages = new NvUsages();
   2.116 +        usages.Version = NVAPI.GPU_USAGES_VER;
   2.117 +        usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
   2.118 +        if (NVAPI.NvAPI_GPU_GetUsages != null &&
   2.119 +          NVAPI.NvAPI_GPU_GetUsages(handle, ref usages) == NvStatus.OK) {
   2.120 +          loads[0].Value = usages.Usage[2];
   2.121 +          loads[1].Value = usages.Usage[6];
   2.122 +          loads[2].Value = usages.Usage[10];
   2.123 +          for (int i = 0; i < 3; i++)
   2.124 +            ActivateSensor(loads[i]);
   2.125 +        }
   2.126 +      }
   2.127 +
   2.128 +      NvGPUCoolerSettings coolerSettings = new NvGPUCoolerSettings();
   2.129 +      coolerSettings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
   2.130 +      coolerSettings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
   2.131 +      if (NVAPI.NvAPI_GPU_GetCoolerSettings != null && 
   2.132 +        NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, ref coolerSettings) ==
   2.133 +        NvStatus.OK && coolerSettings.Count > 0) {
   2.134 +        control.Value = coolerSettings.Cooler[0].CurrentLevel;
   2.135 +        ActivateSensor(control);
   2.136 +      }
   2.137 +
   2.138 +      NvMemoryInfo memoryInfo = new NvMemoryInfo();
   2.139 +      memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
   2.140 +      memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
   2.141 +      if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue &&
   2.142 +        NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value, ref memoryInfo) == 
   2.143 +        NvStatus.OK) 
   2.144 +      {
   2.145 +        uint totalMemory = memoryInfo.Values[0];
   2.146 +        uint freeMemory = memoryInfo.Values[4];
   2.147 +        float usedMemory = Math.Max(totalMemory - freeMemory, 0);
   2.148 +        memoryLoad.Value = 100f * usedMemory / totalMemory;
   2.149 +        ActivateSensor(memoryLoad);
   2.150 +      }
   2.151 +    }
   2.152 +
   2.153 +    public override string GetReport() {
   2.154 +      StringBuilder r = new StringBuilder();
   2.155 +
   2.156 +      r.AppendLine("Nvidia GPU");
   2.157 +      r.AppendLine();
   2.158 +
   2.159 +      r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
   2.160 +      r.AppendFormat("Index: {0}{1}", adapterIndex, Environment.NewLine);
   2.161 +      
   2.162 +      if (displayHandle.HasValue && NVAPI.NvAPI_GetDisplayDriverVersion != null) 
   2.163 +      {
   2.164 +        NvDisplayDriverVersion driverVersion = new NvDisplayDriverVersion();
   2.165 +        driverVersion.Version = NVAPI.DISPLAY_DRIVER_VERSION_VER;
   2.166 +        if (NVAPI.NvAPI_GetDisplayDriverVersion(displayHandle.Value,
   2.167 +          ref driverVersion) == NvStatus.OK) {
   2.168 +          r.Append("Driver Version: ");
   2.169 +          r.Append(driverVersion.DriverVersion / 100);
   2.170 +          r.Append(".");
   2.171 +          r.Append((driverVersion.DriverVersion % 100).ToString("00"));
   2.172 +          r.AppendLine();
   2.173 +          r.Append("Driver Branch: ");
   2.174 +          r.AppendLine(driverVersion.BuildBranch);
   2.175 +        }
   2.176 +      }
   2.177 +      r.AppendLine();
   2.178 +
   2.179 +      if (NVAPI.NvAPI_GPU_GetThermalSettings != null) {
   2.180 +        NvGPUThermalSettings settings = new NvGPUThermalSettings();
   2.181 +        settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
   2.182 +        settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
   2.183 +        settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
   2.184 +
   2.185 +        NvStatus status = NVAPI.NvAPI_GPU_GetThermalSettings(handle,
   2.186 +          (int)NvThermalTarget.ALL, ref settings);
   2.187 +
   2.188 +        r.AppendLine("Thermal Settings");
   2.189 +        r.AppendLine();
   2.190 +        if (status == NvStatus.OK) {
   2.191 +          for (int i = 0; i < settings.Count; i++) {
   2.192 +            r.AppendFormat(" Sensor[{0}].Controller: {1}{2}", i,
   2.193 +              settings.Sensor[i].Controller, Environment.NewLine);
   2.194 +            r.AppendFormat(" Sensor[{0}].DefaultMinTemp: {1}{2}", i,
   2.195 +              settings.Sensor[i].DefaultMinTemp, Environment.NewLine);
   2.196 +            r.AppendFormat(" Sensor[{0}].DefaultMaxTemp: {1}{2}", i,
   2.197 +              settings.Sensor[i].DefaultMaxTemp, Environment.NewLine);
   2.198 +            r.AppendFormat(" Sensor[{0}].CurrentTemp: {1}{2}", i,
   2.199 +              settings.Sensor[i].CurrentTemp, Environment.NewLine);
   2.200 +            r.AppendFormat(" Sensor[{0}].Target: {1}{2}", i,
   2.201 +              settings.Sensor[i].Target, Environment.NewLine);
   2.202 +          }
   2.203 +        } else {
   2.204 +          r.Append(" Status: ");
   2.205 +          r.AppendLine(status.ToString());
   2.206 +        }
   2.207 +        r.AppendLine();
   2.208 +      }      
   2.209 +
   2.210 +      if (NVAPI.NvAPI_GPU_GetAllClocks != null) {
   2.211 +        NvClocks clocks = new NvClocks();
   2.212 +        clocks.Version = NVAPI.GPU_CLOCKS_VER;
   2.213 +        clocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
   2.214 +        NvStatus status = NVAPI.NvAPI_GPU_GetAllClocks(handle, ref clocks);
   2.215 +
   2.216 +        r.AppendLine("Clocks");
   2.217 +        r.AppendLine();
   2.218 +        if (status == NvStatus.OK) {
   2.219 +          for (int i = 0; i < clocks.Clock.Length; i++)
   2.220 +            if (clocks.Clock[i] > 0) {
   2.221 +              r.AppendFormat(" Clock[{0}]: {1}{2}", i, clocks.Clock[i],
   2.222 +                Environment.NewLine);
   2.223 +            }
   2.224 +        } else {
   2.225 +          r.Append(" Status: ");
   2.226 +          r.AppendLine(status.ToString());
   2.227 +        }
   2.228 +        r.AppendLine();
   2.229 +      }         
   2.230 +           
   2.231 +      if (NVAPI.NvAPI_GPU_GetTachReading != null) {
   2.232 +        int tachValue; 
   2.233 +        NvStatus status = NVAPI.NvAPI_GPU_GetTachReading(handle, out tachValue);
   2.234 +
   2.235 +        r.AppendLine("Tachometer");
   2.236 +        r.AppendLine();
   2.237 +        if (status == NvStatus.OK) {
   2.238 +          r.AppendFormat(" Value: {0}{1}", tachValue, Environment.NewLine);
   2.239 +        } else {
   2.240 +          r.Append(" Status: ");
   2.241 +          r.AppendLine(status.ToString());
   2.242 +        }
   2.243 +        r.AppendLine();
   2.244 +      }
   2.245 +
   2.246 +      if (NVAPI.NvAPI_GPU_GetPStates != null) {
   2.247 +        NvPStates states = new NvPStates();
   2.248 +        states.Version = NVAPI.GPU_PSTATES_VER;
   2.249 +        states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
   2.250 +        NvStatus status = NVAPI.NvAPI_GPU_GetPStates(handle, ref states);
   2.251 +
   2.252 +        r.AppendLine("P-States");
   2.253 +        r.AppendLine();
   2.254 +        if (status == NvStatus.OK) {
   2.255 +          for (int i = 0; i < states.PStates.Length; i++)
   2.256 +            if (states.PStates[i].Present)
   2.257 +              r.AppendFormat(" Percentage[{0}]: {1}{2}", i,
   2.258 +                states.PStates[i].Percentage, Environment.NewLine);
   2.259 +        } else {
   2.260 +          r.Append(" Status: ");
   2.261 +          r.AppendLine(status.ToString());
   2.262 +        }
   2.263 +        r.AppendLine();
   2.264 +      }
   2.265 +
   2.266 +      if (NVAPI.NvAPI_GPU_GetUsages != null) {
   2.267 +        NvUsages usages = new NvUsages();
   2.268 +        usages.Version = NVAPI.GPU_USAGES_VER;
   2.269 +        usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
   2.270 +        NvStatus status = NVAPI.NvAPI_GPU_GetUsages(handle, ref usages);
   2.271 +     
   2.272 +        r.AppendLine("Usages");
   2.273 +        r.AppendLine();
   2.274 +        if (status == NvStatus.OK) {
   2.275 +          for (int i = 0; i < usages.Usage.Length; i++)
   2.276 +            if (usages.Usage[i] > 0)
   2.277 +              r.AppendFormat(" Usage[{0}]: {1}{2}", i,
   2.278 +                usages.Usage[i], Environment.NewLine);
   2.279 +        } else {
   2.280 +          r.Append(" Status: ");
   2.281 +          r.AppendLine(status.ToString());
   2.282 +        }
   2.283 +        r.AppendLine();
   2.284 +      }
   2.285 +
   2.286 +      if (NVAPI.NvAPI_GPU_GetCoolerSettings != null) {
   2.287 +        NvGPUCoolerSettings settings = new NvGPUCoolerSettings();
   2.288 +        settings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
   2.289 +        settings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
   2.290 +        NvStatus status =
   2.291 +          NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, ref settings);
   2.292 +
   2.293 +        r.AppendLine("Cooler Settings");
   2.294 +        r.AppendLine();
   2.295 +        if (status == NvStatus.OK) {
   2.296 +          for (int i = 0; i < settings.Count; i++) {
   2.297 +            r.AppendFormat(" Cooler[{0}].Type: {1}{2}", i,
   2.298 +              settings.Cooler[i].Type, Environment.NewLine);
   2.299 +            r.AppendFormat(" Cooler[{0}].Controller: {1}{2}", i,
   2.300 +              settings.Cooler[i].Controller, Environment.NewLine);
   2.301 +            r.AppendFormat(" Cooler[{0}].DefaultMin: {1}{2}", i,
   2.302 +              settings.Cooler[i].DefaultMin, Environment.NewLine);
   2.303 +            r.AppendFormat(" Cooler[{0}].DefaultMax: {1}{2}", i,
   2.304 +              settings.Cooler[i].DefaultMax, Environment.NewLine);
   2.305 +            r.AppendFormat(" Cooler[{0}].CurrentMin: {1}{2}", i,
   2.306 +              settings.Cooler[i].CurrentMin, Environment.NewLine);
   2.307 +            r.AppendFormat(" Cooler[{0}].CurrentMax: {1}{2}", i,
   2.308 +              settings.Cooler[i].CurrentMax, Environment.NewLine);
   2.309 +            r.AppendFormat(" Cooler[{0}].CurrentLevel: {1}{2}", i,
   2.310 +              settings.Cooler[i].CurrentLevel, Environment.NewLine);
   2.311 +            r.AppendFormat(" Cooler[{0}].DefaultPolicy: {1}{2}", i,
   2.312 +              settings.Cooler[i].DefaultPolicy, Environment.NewLine);
   2.313 +            r.AppendFormat(" Cooler[{0}].CurrentPolicy: {1}{2}", i,
   2.314 +              settings.Cooler[i].CurrentPolicy, Environment.NewLine);
   2.315 +            r.AppendFormat(" Cooler[{0}].Target: {1}{2}", i,
   2.316 +              settings.Cooler[i].Target, Environment.NewLine);
   2.317 +            r.AppendFormat(" Cooler[{0}].ControlType: {1}{2}", i,
   2.318 +              settings.Cooler[i].ControlType, Environment.NewLine);
   2.319 +            r.AppendFormat(" Cooler[{0}].Active: {1}{2}", i,
   2.320 +              settings.Cooler[i].Active, Environment.NewLine);
   2.321 +          }
   2.322 +        } else {
   2.323 +          r.Append(" Status: ");
   2.324 +          r.AppendLine(status.ToString());
   2.325 +        }
   2.326 +        r.AppendLine();
   2.327 +      }
   2.328 +
   2.329 +      if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue) {
   2.330 +        NvMemoryInfo memoryInfo = new NvMemoryInfo();
   2.331 +        memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
   2.332 +        memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
   2.333 +        NvStatus status = NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value, 
   2.334 +          ref memoryInfo);
   2.335 +
   2.336 +        r.AppendLine("Memory Info");
   2.337 +        r.AppendLine();
   2.338 +        if (status == NvStatus.OK) {
   2.339 +          for (int i = 0; i < memoryInfo.Values.Length; i++)
   2.340 +            r.AppendFormat(" Value[{0}]: {1}{2}", i,
   2.341 +                memoryInfo.Values[i], Environment.NewLine);
   2.342 +        } else {
   2.343 +          r.Append(" Status: ");
   2.344 +          r.AppendLine(status.ToString());
   2.345 +        }
   2.346 +        r.AppendLine();
   2.347 +      }
   2.348 +
   2.349 +      return r.ToString();
   2.350      }
   2.351    }
   2.352  }
     3.1 --- a/Hardware/Nvidia/NvidiaGroup.cs	Sat Jun 12 12:15:00 2010 +0000
     3.2 +++ b/Hardware/Nvidia/NvidiaGroup.cs	Sun Jun 27 10:24:27 2010 +0000
     3.3 @@ -53,25 +53,68 @@
     3.4        report.AppendLine("NVAPI");
     3.5        report.AppendLine();
     3.6  
     3.7 +      string version;
     3.8 +      if (NVAPI.NvAPI_GetInterfaceVersionString(out version) == NvStatus.OK) {
     3.9 +        report.Append("Version: ");
    3.10 +        report.AppendLine(version);
    3.11 +      }
    3.12 +
    3.13        NvPhysicalGpuHandle[] handles = 
    3.14          new NvPhysicalGpuHandle[NVAPI.MAX_PHYSICAL_GPUS];
    3.15 -
    3.16 +      int count;
    3.17        if (NVAPI.NvAPI_EnumPhysicalGPUs == null) {
    3.18          report.AppendLine("Error: NvAPI_EnumPhysicalGPUs not available");
    3.19          report.AppendLine();
    3.20          return;
    3.21 +      } else {        
    3.22 +        NvStatus status = NVAPI.NvAPI_EnumPhysicalGPUs(handles, out count);
    3.23 +        if (status != NvStatus.OK) {
    3.24 +          report.AppendLine("Status: " + status.ToString());
    3.25 +          report.AppendLine();
    3.26 +          return;
    3.27 +        }
    3.28        }
    3.29  
    3.30 -      int count;
    3.31 -      if (NVAPI.NvAPI_EnumPhysicalGPUs(handles, out count) != NvStatus.OK)
    3.32 -        return;
    3.33 +      IDictionary<NvPhysicalGpuHandle, NvDisplayHandle> displayHandles =
    3.34 +        new Dictionary<NvPhysicalGpuHandle, NvDisplayHandle>();
    3.35 +
    3.36 +      if (NVAPI.NvAPI_EnumNvidiaDisplayHandle != null &&
    3.37 +        NVAPI.NvAPI_GetPhysicalGPUsFromDisplay != null) 
    3.38 +      {
    3.39 +        NvStatus status = NvStatus.OK;
    3.40 +        int i = 0;
    3.41 +        while (status == NvStatus.OK) {
    3.42 +          NvDisplayHandle displayHandle = new NvDisplayHandle();
    3.43 +          status = NVAPI.NvAPI_EnumNvidiaDisplayHandle(i, ref displayHandle);
    3.44 +          i++;
    3.45 +
    3.46 +          if (status == NvStatus.OK) {
    3.47 +            NvPhysicalGpuHandle[] handlesFromDisplay =
    3.48 +              new NvPhysicalGpuHandle[NVAPI.MAX_PHYSICAL_GPUS];
    3.49 +            uint countFromDisplay;
    3.50 +            if (NVAPI.NvAPI_GetPhysicalGPUsFromDisplay(displayHandle,
    3.51 +              handlesFromDisplay, out countFromDisplay) == NvStatus.OK) {
    3.52 +              for (int j = 0; j < countFromDisplay; j++) {
    3.53 +                if (!displayHandles.ContainsKey(handlesFromDisplay[j]))
    3.54 +                  displayHandles.Add(handlesFromDisplay[j], displayHandle);
    3.55 +              }
    3.56 +            }
    3.57 +          }
    3.58 +        }
    3.59 +      }
    3.60  
    3.61        report.Append("Number of GPUs: ");
    3.62 -      report.AppendLine(count.ToString());
    3.63 +      report.AppendLine(count.ToString());      
    3.64 +      
    3.65 +      for (int i = 0; i < count; i++) {    
    3.66 +        NvDisplayHandle displayHandle;
    3.67 +        if (displayHandles.TryGetValue(handles[i], out displayHandle))
    3.68 +          hardware.Add(new NvidiaGPU(i, handles[i], displayHandle));                            
    3.69 +        else
    3.70 +          hardware.Add(new NvidiaGPU(i, handles[i], null));   
    3.71 +      }
    3.72 +
    3.73        report.AppendLine();
    3.74 -
    3.75 -      for (int i = 0; i < count; i++) 
    3.76 -        hardware.Add(new NvidiaGPU(i, handles[i]));
    3.77      }
    3.78  
    3.79      public IHardware[] Hardware {
    3.80 @@ -84,7 +127,6 @@
    3.81        return report.ToString();
    3.82      }
    3.83  
    3.84 -    public void Close() {
    3.85 -    }
    3.86 +    public void Close() { }
    3.87    }
    3.88  }