Hardware/Nvidia/NvidiaGPU.cs
author moel.mich
Sun, 19 Jun 2011 12:41:18 +0000
changeset 298 96263190189a
parent 195 0ee888c485d5
child 309 65a1ae21325d
permissions -rw-r--r--
Added support for saving and restoring the sensor history for the last 24h. The sensor history is now saved in a reduced format (duplicate values are removed, gaps are marked with a NAN sensor value.
     1 /*
     2   
     3   Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4 
     5   The contents of this file are subject to the Mozilla Public License Version
     6   1.1 (the "License"); you may not use this file except in compliance with
     7   the License. You may obtain a copy of the License at
     8  
     9   http://www.mozilla.org/MPL/
    10 
    11   Software distributed under the License is distributed on an "AS IS" basis,
    12   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    13   for the specific language governing rights and limitations under the License.
    14 
    15   The Original Code is the Open Hardware Monitor code.
    16 
    17   The Initial Developer of the Original Code is 
    18   Michael Möller <m.moeller@gmx.ch>.
    19   Portions created by the Initial Developer are Copyright (C) 2009-2011
    20   the Initial Developer. All Rights Reserved.
    21 
    22   Contributor(s):
    23 
    24   Alternatively, the contents of this file may be used under the terms of
    25   either the GNU General Public License Version 2 or later (the "GPL"), or
    26   the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    27   in which case the provisions of the GPL or the LGPL are applicable instead
    28   of those above. If you wish to allow use of your version of this file only
    29   under the terms of either the GPL or the LGPL, and not to allow others to
    30   use your version of this file under the terms of the MPL, indicate your
    31   decision by deleting the provisions above and replace them with the notice
    32   and other provisions required by the GPL or the LGPL. If you do not delete
    33   the provisions above, a recipient may use your version of this file under
    34   the terms of any one of the MPL, the GPL or the LGPL.
    35  
    36 */
    37 
    38 using System;
    39 using System.Globalization;
    40 using System.Text;
    41 
    42 namespace OpenHardwareMonitor.Hardware.Nvidia {
    43   internal class NvidiaGPU : Hardware {
    44 
    45     private readonly int adapterIndex;
    46     private readonly NvPhysicalGpuHandle handle;
    47     private readonly NvDisplayHandle? displayHandle;
    48 
    49     private readonly Sensor[] temperatures;
    50     private readonly Sensor fan;
    51     private readonly Sensor[] clocks;
    52     private readonly Sensor[] loads;
    53     private readonly Sensor control;
    54     private readonly Sensor memoryLoad;
    55 
    56     public NvidiaGPU(int adapterIndex, NvPhysicalGpuHandle handle, 
    57       NvDisplayHandle? displayHandle, ISettings settings) 
    58       : base(GetName(handle), new Identifier("nvidiagpu", 
    59           adapterIndex.ToString(CultureInfo.InvariantCulture)), settings)
    60     {
    61       this.adapterIndex = adapterIndex;
    62       this.handle = handle;
    63       this.displayHandle = displayHandle;
    64 
    65       NvGPUThermalSettings thermalSettings = GetThermalSettings();
    66       temperatures = new Sensor[thermalSettings.Count];
    67       for (int i = 0; i < temperatures.Length; i++) {
    68         NvSensor sensor = thermalSettings.Sensor[i];
    69         string name;
    70         switch (sensor.Target) {
    71           case NvThermalTarget.BOARD: name = "GPU Board"; break;
    72           case NvThermalTarget.GPU: name = "GPU Core"; break;
    73           case NvThermalTarget.MEMORY: name = "GPU Memory"; break;
    74           case NvThermalTarget.POWER_SUPPLY: name = "GPU Power Supply"; break;
    75           case NvThermalTarget.UNKNOWN: name = "GPU Unknown"; break;
    76           default: name = "GPU"; break;
    77         }
    78         temperatures[i] = new Sensor(name, i, SensorType.Temperature, this,
    79           new ParameterDescription[0], settings);
    80         ActivateSensor(temperatures[i]);
    81       }
    82 
    83       int value;
    84       if (NVAPI.NvAPI_GPU_GetTachReading != null &&
    85         NVAPI.NvAPI_GPU_GetTachReading(handle, out value) == NvStatus.OK) {
    86         if (value > 0) {
    87           fan = new Sensor("GPU", 0, SensorType.Fan, this, settings);
    88           ActivateSensor(fan);
    89         }
    90       }
    91 
    92       clocks = new Sensor[3];
    93       clocks[0] = new Sensor("GPU Core", 0, SensorType.Clock, this, settings);
    94       clocks[1] = new Sensor("GPU Memory", 1, SensorType.Clock, this, settings);
    95       clocks[2] = new Sensor("GPU Shader", 2, SensorType.Clock, this, settings);
    96       for (int i = 0; i < clocks.Length; i++)
    97         ActivateSensor(clocks[i]);
    98 
    99       loads = new Sensor[3];
   100       loads[0] = new Sensor("GPU Core", 0, SensorType.Load, this, settings);
   101       loads[1] = new Sensor("GPU Memory Controller", 1, SensorType.Load, this, settings);
   102       loads[2] = new Sensor("GPU Video Engine", 2, SensorType.Load, this, settings);
   103       memoryLoad = new Sensor("GPU Memory", 3, SensorType.Load, this, settings);
   104 
   105       control = new Sensor("GPU Fan", 0, SensorType.Control, this, settings);
   106     }
   107 
   108     private static string GetName(NvPhysicalGpuHandle handle) {
   109       string gpuName;
   110       if (NVAPI.NvAPI_GPU_GetFullName(handle, out gpuName) == NvStatus.OK) {
   111         return "NVIDIA " + gpuName.Trim();
   112       } else {
   113         return "NVIDIA";
   114       }
   115     }
   116 
   117     public override HardwareType HardwareType {
   118       get { return HardwareType.GpuNvidia; }
   119     }
   120 
   121     private NvGPUThermalSettings GetThermalSettings() {
   122       NvGPUThermalSettings settings = new NvGPUThermalSettings();
   123       settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
   124       settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
   125       settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
   126       if (NVAPI.NvAPI_GPU_GetThermalSettings != null &&
   127         NVAPI.NvAPI_GPU_GetThermalSettings(handle, (int)NvThermalTarget.ALL,
   128         ref settings) != NvStatus.OK) {
   129         settings.Count = 0;        
   130       }
   131       return settings;
   132     }
   133 
   134     private uint[] GetClocks() {
   135       NvClocks allClocks = new NvClocks();
   136       allClocks.Version = NVAPI.GPU_CLOCKS_VER;
   137       allClocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
   138       if (NVAPI.NvAPI_GPU_GetAllClocks != null &&
   139         NVAPI.NvAPI_GPU_GetAllClocks(handle, ref allClocks) == NvStatus.OK) {
   140         return allClocks.Clock;
   141       }
   142       return null;
   143     }
   144 
   145     public override void Update() {
   146       NvGPUThermalSettings settings = GetThermalSettings();
   147       foreach (Sensor sensor in temperatures) 
   148         sensor.Value = settings.Sensor[sensor.Index].CurrentTemp;
   149 
   150       if (fan != null) {
   151         int value = 0;
   152         NVAPI.NvAPI_GPU_GetTachReading(handle, out value);
   153         fan.Value = value;
   154       }
   155 
   156       uint[] values = GetClocks();
   157       if (values != null) {
   158         clocks[0].Value = 0.001f * values[0];
   159         clocks[1].Value = 0.001f * values[8];
   160         clocks[2].Value = 0.001f * values[14];
   161         if (values[30] != 0) {
   162           clocks[0].Value = 0.0005f * values[30];
   163           clocks[2].Value = 0.001f * values[30];
   164         }
   165       }
   166 
   167       NvPStates states = new NvPStates();
   168       states.Version = NVAPI.GPU_PSTATES_VER;
   169       states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
   170       if (NVAPI.NvAPI_GPU_GetPStates != null && 
   171         NVAPI.NvAPI_GPU_GetPStates(handle, ref states) == NvStatus.OK) {
   172         for (int i = 0; i < 3; i++)
   173           if (states.PStates[i].Present) {
   174             loads[i].Value = states.PStates[i].Percentage;
   175             ActivateSensor(loads[i]);
   176           }
   177       } else {
   178         NvUsages usages = new NvUsages();
   179         usages.Version = NVAPI.GPU_USAGES_VER;
   180         usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
   181         if (NVAPI.NvAPI_GPU_GetUsages != null &&
   182           NVAPI.NvAPI_GPU_GetUsages(handle, ref usages) == NvStatus.OK) {
   183           loads[0].Value = usages.Usage[2];
   184           loads[1].Value = usages.Usage[6];
   185           loads[2].Value = usages.Usage[10];
   186           for (int i = 0; i < 3; i++)
   187             ActivateSensor(loads[i]);
   188         }
   189       }
   190 
   191       NvGPUCoolerSettings coolerSettings = new NvGPUCoolerSettings();
   192       coolerSettings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
   193       coolerSettings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
   194       if (NVAPI.NvAPI_GPU_GetCoolerSettings != null && 
   195         NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, ref coolerSettings) ==
   196         NvStatus.OK && coolerSettings.Count > 0) {
   197         control.Value = coolerSettings.Cooler[0].CurrentLevel;
   198         ActivateSensor(control);
   199       }
   200 
   201       NvMemoryInfo memoryInfo = new NvMemoryInfo();
   202       memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
   203       memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
   204       if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue &&
   205         NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value, ref memoryInfo) == 
   206         NvStatus.OK) 
   207       {
   208         uint totalMemory = memoryInfo.Values[0];
   209         uint freeMemory = memoryInfo.Values[4];
   210         float usedMemory = Math.Max(totalMemory - freeMemory, 0);
   211         memoryLoad.Value = 100f * usedMemory / totalMemory;
   212         ActivateSensor(memoryLoad);
   213       }
   214     }
   215 
   216     public override string GetReport() {
   217       StringBuilder r = new StringBuilder();
   218 
   219       r.AppendLine("Nvidia GPU");
   220       r.AppendLine();
   221 
   222       r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
   223       r.AppendFormat("Index: {0}{1}", adapterIndex, Environment.NewLine);
   224       
   225       if (displayHandle.HasValue && NVAPI.NvAPI_GetDisplayDriverVersion != null) 
   226       {
   227         NvDisplayDriverVersion driverVersion = new NvDisplayDriverVersion();
   228         driverVersion.Version = NVAPI.DISPLAY_DRIVER_VERSION_VER;
   229         if (NVAPI.NvAPI_GetDisplayDriverVersion(displayHandle.Value,
   230           ref driverVersion) == NvStatus.OK) {
   231           r.Append("Driver Version: ");
   232           r.Append(driverVersion.DriverVersion / 100);
   233           r.Append(".");
   234           r.Append((driverVersion.DriverVersion % 100).ToString("00", 
   235             CultureInfo.InvariantCulture));
   236           r.AppendLine();
   237           r.Append("Driver Branch: ");
   238           r.AppendLine(driverVersion.BuildBranch);
   239         }
   240       }
   241       r.AppendLine();
   242 
   243       if (NVAPI.NvAPI_GPU_GetThermalSettings != null) {
   244         NvGPUThermalSettings settings = new NvGPUThermalSettings();
   245         settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
   246         settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
   247         settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
   248 
   249         NvStatus status = NVAPI.NvAPI_GPU_GetThermalSettings(handle,
   250           (int)NvThermalTarget.ALL, ref settings);
   251 
   252         r.AppendLine("Thermal Settings");
   253         r.AppendLine();
   254         if (status == NvStatus.OK) {
   255           for (int i = 0; i < settings.Count; i++) {
   256             r.AppendFormat(" Sensor[{0}].Controller: {1}{2}", i,
   257               settings.Sensor[i].Controller, Environment.NewLine);
   258             r.AppendFormat(" Sensor[{0}].DefaultMinTemp: {1}{2}", i,
   259               settings.Sensor[i].DefaultMinTemp, Environment.NewLine);
   260             r.AppendFormat(" Sensor[{0}].DefaultMaxTemp: {1}{2}", i,
   261               settings.Sensor[i].DefaultMaxTemp, Environment.NewLine);
   262             r.AppendFormat(" Sensor[{0}].CurrentTemp: {1}{2}", i,
   263               settings.Sensor[i].CurrentTemp, Environment.NewLine);
   264             r.AppendFormat(" Sensor[{0}].Target: {1}{2}", i,
   265               settings.Sensor[i].Target, Environment.NewLine);
   266           }
   267         } else {
   268           r.Append(" Status: ");
   269           r.AppendLine(status.ToString());
   270         }
   271         r.AppendLine();
   272       }      
   273 
   274       if (NVAPI.NvAPI_GPU_GetAllClocks != null) {
   275         NvClocks allClocks = new NvClocks();
   276         allClocks.Version = NVAPI.GPU_CLOCKS_VER;
   277         allClocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
   278         NvStatus status = NVAPI.NvAPI_GPU_GetAllClocks(handle, ref allClocks);
   279 
   280         r.AppendLine("Clocks");
   281         r.AppendLine();
   282         if (status == NvStatus.OK) {
   283           for (int i = 0; i < allClocks.Clock.Length; i++)
   284             if (allClocks.Clock[i] > 0) {
   285               r.AppendFormat(" Clock[{0}]: {1}{2}", i, allClocks.Clock[i],
   286                 Environment.NewLine);
   287             }
   288         } else {
   289           r.Append(" Status: ");
   290           r.AppendLine(status.ToString());
   291         }
   292         r.AppendLine();
   293       }         
   294            
   295       if (NVAPI.NvAPI_GPU_GetTachReading != null) {
   296         int tachValue; 
   297         NvStatus status = NVAPI.NvAPI_GPU_GetTachReading(handle, out tachValue);
   298 
   299         r.AppendLine("Tachometer");
   300         r.AppendLine();
   301         if (status == NvStatus.OK) {
   302           r.AppendFormat(" Value: {0}{1}", tachValue, Environment.NewLine);
   303         } else {
   304           r.Append(" Status: ");
   305           r.AppendLine(status.ToString());
   306         }
   307         r.AppendLine();
   308       }
   309 
   310       if (NVAPI.NvAPI_GPU_GetPStates != null) {
   311         NvPStates states = new NvPStates();
   312         states.Version = NVAPI.GPU_PSTATES_VER;
   313         states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
   314         NvStatus status = NVAPI.NvAPI_GPU_GetPStates(handle, ref states);
   315 
   316         r.AppendLine("P-States");
   317         r.AppendLine();
   318         if (status == NvStatus.OK) {
   319           for (int i = 0; i < states.PStates.Length; i++)
   320             if (states.PStates[i].Present)
   321               r.AppendFormat(" Percentage[{0}]: {1}{2}", i,
   322                 states.PStates[i].Percentage, Environment.NewLine);
   323         } else {
   324           r.Append(" Status: ");
   325           r.AppendLine(status.ToString());
   326         }
   327         r.AppendLine();
   328       }
   329 
   330       if (NVAPI.NvAPI_GPU_GetUsages != null) {
   331         NvUsages usages = new NvUsages();
   332         usages.Version = NVAPI.GPU_USAGES_VER;
   333         usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
   334         NvStatus status = NVAPI.NvAPI_GPU_GetUsages(handle, ref usages);
   335      
   336         r.AppendLine("Usages");
   337         r.AppendLine();
   338         if (status == NvStatus.OK) {
   339           for (int i = 0; i < usages.Usage.Length; i++)
   340             if (usages.Usage[i] > 0)
   341               r.AppendFormat(" Usage[{0}]: {1}{2}", i,
   342                 usages.Usage[i], Environment.NewLine);
   343         } else {
   344           r.Append(" Status: ");
   345           r.AppendLine(status.ToString());
   346         }
   347         r.AppendLine();
   348       }
   349 
   350       if (NVAPI.NvAPI_GPU_GetCoolerSettings != null) {
   351         NvGPUCoolerSettings settings = new NvGPUCoolerSettings();
   352         settings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
   353         settings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
   354         NvStatus status =
   355           NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, ref settings);
   356 
   357         r.AppendLine("Cooler Settings");
   358         r.AppendLine();
   359         if (status == NvStatus.OK) {
   360           for (int i = 0; i < settings.Count; i++) {
   361             r.AppendFormat(" Cooler[{0}].Type: {1}{2}", i,
   362               settings.Cooler[i].Type, Environment.NewLine);
   363             r.AppendFormat(" Cooler[{0}].Controller: {1}{2}", i,
   364               settings.Cooler[i].Controller, Environment.NewLine);
   365             r.AppendFormat(" Cooler[{0}].DefaultMin: {1}{2}", i,
   366               settings.Cooler[i].DefaultMin, Environment.NewLine);
   367             r.AppendFormat(" Cooler[{0}].DefaultMax: {1}{2}", i,
   368               settings.Cooler[i].DefaultMax, Environment.NewLine);
   369             r.AppendFormat(" Cooler[{0}].CurrentMin: {1}{2}", i,
   370               settings.Cooler[i].CurrentMin, Environment.NewLine);
   371             r.AppendFormat(" Cooler[{0}].CurrentMax: {1}{2}", i,
   372               settings.Cooler[i].CurrentMax, Environment.NewLine);
   373             r.AppendFormat(" Cooler[{0}].CurrentLevel: {1}{2}", i,
   374               settings.Cooler[i].CurrentLevel, Environment.NewLine);
   375             r.AppendFormat(" Cooler[{0}].DefaultPolicy: {1}{2}", i,
   376               settings.Cooler[i].DefaultPolicy, Environment.NewLine);
   377             r.AppendFormat(" Cooler[{0}].CurrentPolicy: {1}{2}", i,
   378               settings.Cooler[i].CurrentPolicy, Environment.NewLine);
   379             r.AppendFormat(" Cooler[{0}].Target: {1}{2}", i,
   380               settings.Cooler[i].Target, Environment.NewLine);
   381             r.AppendFormat(" Cooler[{0}].ControlType: {1}{2}", i,
   382               settings.Cooler[i].ControlType, Environment.NewLine);
   383             r.AppendFormat(" Cooler[{0}].Active: {1}{2}", i,
   384               settings.Cooler[i].Active, Environment.NewLine);
   385           }
   386         } else {
   387           r.Append(" Status: ");
   388           r.AppendLine(status.ToString());
   389         }
   390         r.AppendLine();
   391       }
   392 
   393       if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue) {
   394         NvMemoryInfo memoryInfo = new NvMemoryInfo();
   395         memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
   396         memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
   397         NvStatus status = NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value, 
   398           ref memoryInfo);
   399 
   400         r.AppendLine("Memory Info");
   401         r.AppendLine();
   402         if (status == NvStatus.OK) {
   403           for (int i = 0; i < memoryInfo.Values.Length; i++)
   404             r.AppendFormat(" Value[{0}]: {1}{2}", i,
   405                 memoryInfo.Values[i], Environment.NewLine);
   406         } else {
   407           r.Append(" Status: ");
   408           r.AppendLine(status.ToString());
   409         }
   410         r.AppendLine();
   411       }
   412 
   413       return r.ToString();
   414     }
   415   }
   416 }