Hardware/Nvidia/NvidiaGPU.cs
author moel.mich
Sun, 27 Jun 2010 10:24:27 +0000
changeset 140 04a5155c9c1a
parent 134 8b3b9b2e28e5
child 165 813d8bc3192f
permissions -rw-r--r--
Improved the support for Nvidia GPUs.
     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-2010
    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.Collections.Generic;
    40 using System.Drawing;
    41 using System.Text;
    42 
    43 namespace OpenHardwareMonitor.Hardware.Nvidia {
    44   public class NvidiaGPU : Hardware, IHardware {
    45 
    46     private string name;
    47     private Image icon;
    48     private int adapterIndex;
    49     private NvPhysicalGpuHandle handle;
    50     private NvDisplayHandle? displayHandle;
    51 
    52     private Sensor[] temperatures;
    53     private Sensor fan = null;
    54     private Sensor[] clocks;
    55     private Sensor[] loads;
    56     private Sensor control;
    57     private Sensor memoryLoad;
    58 
    59     public NvidiaGPU(int adapterIndex, NvPhysicalGpuHandle handle, 
    60       NvDisplayHandle? displayHandle) 
    61     {
    62       string gpuName;
    63       if (NVAPI.NvAPI_GPU_GetFullName(handle, out gpuName) == NvStatus.OK) {
    64         this.name = "NVIDIA " + gpuName.Trim();
    65       } else {
    66         this.name = "NVIDIA";
    67       }
    68       this.icon = Utilities.EmbeddedResources.GetImage("nvidia.png");
    69       this.adapterIndex = adapterIndex;
    70       this.handle = handle;
    71       this.displayHandle = displayHandle;
    72 
    73       NvGPUThermalSettings settings = GetThermalSettings();
    74       temperatures = new Sensor[settings.Count];
    75       for (int i = 0; i < temperatures.Length; i++) {
    76         NvSensor sensor = settings.Sensor[i];
    77         string name;
    78         switch (sensor.Target) {
    79           case NvThermalTarget.BOARD: name = "GPU Board"; break;
    80           case NvThermalTarget.GPU: name = "GPU Core"; break;
    81           case NvThermalTarget.MEMORY: name = "GPU Memory"; break;
    82           case NvThermalTarget.POWER_SUPPLY: name = "GPU Power Supply"; break;
    83           case NvThermalTarget.UNKNOWN: name = "GPU Unknown"; break;
    84           default: name = "GPU"; break;
    85         }
    86         temperatures[i] = new Sensor(name, i, SensorType.Temperature, this, 
    87           new ParameterDescription[0]);
    88         ActivateSensor(temperatures[i]);
    89       }
    90 
    91       int value;
    92       if (NVAPI.NvAPI_GPU_GetTachReading != null &&
    93         NVAPI.NvAPI_GPU_GetTachReading(handle, out value) == NvStatus.OK) {
    94         if (value > 0) {
    95           fan = new Sensor("GPU", 0, SensorType.Fan, this);
    96           ActivateSensor(fan);
    97         }
    98       }
    99 
   100       clocks = new Sensor[3];
   101       clocks[0] = new Sensor("GPU Core", 0, SensorType.Clock, this);
   102       clocks[1] = new Sensor("GPU Memory", 1, SensorType.Clock, this);
   103       clocks[2] = new Sensor("GPU Shader", 2, SensorType.Clock, this);
   104       for (int i = 0; i < clocks.Length; i++)
   105         ActivateSensor(clocks[i]);
   106 
   107       loads = new Sensor[3];
   108       loads[0] = new Sensor("GPU Core", 0, SensorType.Load, this);
   109       loads[1] = new Sensor("GPU Memory Controller", 1, SensorType.Load, this);
   110       loads[2] = new Sensor("GPU Video Engine", 2, SensorType.Load, this);
   111       memoryLoad = new Sensor("GPU Memory", 3, SensorType.Load, this);
   112 
   113       control = new Sensor("GPU Fan", 0, SensorType.Control, this);
   114     }
   115 
   116     public override string Name {
   117       get { return name; }
   118     }
   119 
   120     public override Identifier Identifier {
   121       get { return new Identifier("nvidiagpu", adapterIndex.ToString()); }
   122     }
   123 
   124     public override Image Icon {
   125       get { return icon; }
   126     }
   127 
   128     private NvGPUThermalSettings GetThermalSettings() {
   129       NvGPUThermalSettings settings = new NvGPUThermalSettings();
   130       settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
   131       settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
   132       settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
   133       if (NVAPI.NvAPI_GPU_GetThermalSettings != null &&
   134         NVAPI.NvAPI_GPU_GetThermalSettings(handle, (int)NvThermalTarget.ALL,
   135         ref settings) != NvStatus.OK) {
   136         settings.Count = 0;        
   137       }
   138       return settings;
   139     }
   140 
   141     private uint[] GetClocks() {
   142       NvClocks clocks = new NvClocks();
   143       clocks.Version = NVAPI.GPU_CLOCKS_VER;
   144       clocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
   145       if (NVAPI.NvAPI_GPU_GetAllClocks != null &&
   146         NVAPI.NvAPI_GPU_GetAllClocks(handle, ref clocks) == NvStatus.OK) {
   147         return clocks.Clock;
   148       }
   149       return null;
   150     }
   151 
   152     public override void Update() {
   153       NvGPUThermalSettings settings = GetThermalSettings();
   154       foreach (Sensor sensor in temperatures) 
   155         sensor.Value = settings.Sensor[sensor.Index].CurrentTemp;
   156 
   157       if (fan != null) {
   158         int value = 0;
   159         NVAPI.NvAPI_GPU_GetTachReading(handle, out value);
   160         fan.Value = value;
   161       }
   162 
   163       uint[] values = GetClocks();
   164       if (values != null) {
   165         clocks[0].Value = 0.001f * values[0];
   166         clocks[1].Value = 0.001f * values[8];
   167         clocks[2].Value = 0.001f * values[14];
   168         if (values[30] != 0) {
   169           clocks[0].Value = 0.0005f * values[30];
   170           clocks[2].Value = 0.001f * values[30];
   171         }
   172       }
   173 
   174       NvPStates states = new NvPStates();
   175       states.Version = NVAPI.GPU_PSTATES_VER;
   176       states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
   177       if (NVAPI.NvAPI_GPU_GetPStates != null && 
   178         NVAPI.NvAPI_GPU_GetPStates(handle, ref states) == NvStatus.OK) {
   179         for (int i = 0; i < 3; i++)
   180           if (states.PStates[i].Present) {
   181             loads[i].Value = states.PStates[i].Percentage;
   182             ActivateSensor(loads[i]);
   183           }
   184       } else {
   185         NvUsages usages = new NvUsages();
   186         usages.Version = NVAPI.GPU_USAGES_VER;
   187         usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
   188         if (NVAPI.NvAPI_GPU_GetUsages != null &&
   189           NVAPI.NvAPI_GPU_GetUsages(handle, ref usages) == NvStatus.OK) {
   190           loads[0].Value = usages.Usage[2];
   191           loads[1].Value = usages.Usage[6];
   192           loads[2].Value = usages.Usage[10];
   193           for (int i = 0; i < 3; i++)
   194             ActivateSensor(loads[i]);
   195         }
   196       }
   197 
   198       NvGPUCoolerSettings coolerSettings = new NvGPUCoolerSettings();
   199       coolerSettings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
   200       coolerSettings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
   201       if (NVAPI.NvAPI_GPU_GetCoolerSettings != null && 
   202         NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, ref coolerSettings) ==
   203         NvStatus.OK && coolerSettings.Count > 0) {
   204         control.Value = coolerSettings.Cooler[0].CurrentLevel;
   205         ActivateSensor(control);
   206       }
   207 
   208       NvMemoryInfo memoryInfo = new NvMemoryInfo();
   209       memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
   210       memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
   211       if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue &&
   212         NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value, ref memoryInfo) == 
   213         NvStatus.OK) 
   214       {
   215         uint totalMemory = memoryInfo.Values[0];
   216         uint freeMemory = memoryInfo.Values[4];
   217         float usedMemory = Math.Max(totalMemory - freeMemory, 0);
   218         memoryLoad.Value = 100f * usedMemory / totalMemory;
   219         ActivateSensor(memoryLoad);
   220       }
   221     }
   222 
   223     public override string GetReport() {
   224       StringBuilder r = new StringBuilder();
   225 
   226       r.AppendLine("Nvidia GPU");
   227       r.AppendLine();
   228 
   229       r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
   230       r.AppendFormat("Index: {0}{1}", adapterIndex, Environment.NewLine);
   231       
   232       if (displayHandle.HasValue && NVAPI.NvAPI_GetDisplayDriverVersion != null) 
   233       {
   234         NvDisplayDriverVersion driverVersion = new NvDisplayDriverVersion();
   235         driverVersion.Version = NVAPI.DISPLAY_DRIVER_VERSION_VER;
   236         if (NVAPI.NvAPI_GetDisplayDriverVersion(displayHandle.Value,
   237           ref driverVersion) == NvStatus.OK) {
   238           r.Append("Driver Version: ");
   239           r.Append(driverVersion.DriverVersion / 100);
   240           r.Append(".");
   241           r.Append((driverVersion.DriverVersion % 100).ToString("00"));
   242           r.AppendLine();
   243           r.Append("Driver Branch: ");
   244           r.AppendLine(driverVersion.BuildBranch);
   245         }
   246       }
   247       r.AppendLine();
   248 
   249       if (NVAPI.NvAPI_GPU_GetThermalSettings != null) {
   250         NvGPUThermalSettings settings = new NvGPUThermalSettings();
   251         settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
   252         settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
   253         settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
   254 
   255         NvStatus status = NVAPI.NvAPI_GPU_GetThermalSettings(handle,
   256           (int)NvThermalTarget.ALL, ref settings);
   257 
   258         r.AppendLine("Thermal Settings");
   259         r.AppendLine();
   260         if (status == NvStatus.OK) {
   261           for (int i = 0; i < settings.Count; i++) {
   262             r.AppendFormat(" Sensor[{0}].Controller: {1}{2}", i,
   263               settings.Sensor[i].Controller, Environment.NewLine);
   264             r.AppendFormat(" Sensor[{0}].DefaultMinTemp: {1}{2}", i,
   265               settings.Sensor[i].DefaultMinTemp, Environment.NewLine);
   266             r.AppendFormat(" Sensor[{0}].DefaultMaxTemp: {1}{2}", i,
   267               settings.Sensor[i].DefaultMaxTemp, Environment.NewLine);
   268             r.AppendFormat(" Sensor[{0}].CurrentTemp: {1}{2}", i,
   269               settings.Sensor[i].CurrentTemp, Environment.NewLine);
   270             r.AppendFormat(" Sensor[{0}].Target: {1}{2}", i,
   271               settings.Sensor[i].Target, Environment.NewLine);
   272           }
   273         } else {
   274           r.Append(" Status: ");
   275           r.AppendLine(status.ToString());
   276         }
   277         r.AppendLine();
   278       }      
   279 
   280       if (NVAPI.NvAPI_GPU_GetAllClocks != null) {
   281         NvClocks clocks = new NvClocks();
   282         clocks.Version = NVAPI.GPU_CLOCKS_VER;
   283         clocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
   284         NvStatus status = NVAPI.NvAPI_GPU_GetAllClocks(handle, ref clocks);
   285 
   286         r.AppendLine("Clocks");
   287         r.AppendLine();
   288         if (status == NvStatus.OK) {
   289           for (int i = 0; i < clocks.Clock.Length; i++)
   290             if (clocks.Clock[i] > 0) {
   291               r.AppendFormat(" Clock[{0}]: {1}{2}", i, clocks.Clock[i],
   292                 Environment.NewLine);
   293             }
   294         } else {
   295           r.Append(" Status: ");
   296           r.AppendLine(status.ToString());
   297         }
   298         r.AppendLine();
   299       }         
   300            
   301       if (NVAPI.NvAPI_GPU_GetTachReading != null) {
   302         int tachValue; 
   303         NvStatus status = NVAPI.NvAPI_GPU_GetTachReading(handle, out tachValue);
   304 
   305         r.AppendLine("Tachometer");
   306         r.AppendLine();
   307         if (status == NvStatus.OK) {
   308           r.AppendFormat(" Value: {0}{1}", tachValue, Environment.NewLine);
   309         } else {
   310           r.Append(" Status: ");
   311           r.AppendLine(status.ToString());
   312         }
   313         r.AppendLine();
   314       }
   315 
   316       if (NVAPI.NvAPI_GPU_GetPStates != null) {
   317         NvPStates states = new NvPStates();
   318         states.Version = NVAPI.GPU_PSTATES_VER;
   319         states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
   320         NvStatus status = NVAPI.NvAPI_GPU_GetPStates(handle, ref states);
   321 
   322         r.AppendLine("P-States");
   323         r.AppendLine();
   324         if (status == NvStatus.OK) {
   325           for (int i = 0; i < states.PStates.Length; i++)
   326             if (states.PStates[i].Present)
   327               r.AppendFormat(" Percentage[{0}]: {1}{2}", i,
   328                 states.PStates[i].Percentage, Environment.NewLine);
   329         } else {
   330           r.Append(" Status: ");
   331           r.AppendLine(status.ToString());
   332         }
   333         r.AppendLine();
   334       }
   335 
   336       if (NVAPI.NvAPI_GPU_GetUsages != null) {
   337         NvUsages usages = new NvUsages();
   338         usages.Version = NVAPI.GPU_USAGES_VER;
   339         usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
   340         NvStatus status = NVAPI.NvAPI_GPU_GetUsages(handle, ref usages);
   341      
   342         r.AppendLine("Usages");
   343         r.AppendLine();
   344         if (status == NvStatus.OK) {
   345           for (int i = 0; i < usages.Usage.Length; i++)
   346             if (usages.Usage[i] > 0)
   347               r.AppendFormat(" Usage[{0}]: {1}{2}", i,
   348                 usages.Usage[i], Environment.NewLine);
   349         } else {
   350           r.Append(" Status: ");
   351           r.AppendLine(status.ToString());
   352         }
   353         r.AppendLine();
   354       }
   355 
   356       if (NVAPI.NvAPI_GPU_GetCoolerSettings != null) {
   357         NvGPUCoolerSettings settings = new NvGPUCoolerSettings();
   358         settings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
   359         settings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
   360         NvStatus status =
   361           NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, ref settings);
   362 
   363         r.AppendLine("Cooler Settings");
   364         r.AppendLine();
   365         if (status == NvStatus.OK) {
   366           for (int i = 0; i < settings.Count; i++) {
   367             r.AppendFormat(" Cooler[{0}].Type: {1}{2}", i,
   368               settings.Cooler[i].Type, Environment.NewLine);
   369             r.AppendFormat(" Cooler[{0}].Controller: {1}{2}", i,
   370               settings.Cooler[i].Controller, Environment.NewLine);
   371             r.AppendFormat(" Cooler[{0}].DefaultMin: {1}{2}", i,
   372               settings.Cooler[i].DefaultMin, Environment.NewLine);
   373             r.AppendFormat(" Cooler[{0}].DefaultMax: {1}{2}", i,
   374               settings.Cooler[i].DefaultMax, Environment.NewLine);
   375             r.AppendFormat(" Cooler[{0}].CurrentMin: {1}{2}", i,
   376               settings.Cooler[i].CurrentMin, Environment.NewLine);
   377             r.AppendFormat(" Cooler[{0}].CurrentMax: {1}{2}", i,
   378               settings.Cooler[i].CurrentMax, Environment.NewLine);
   379             r.AppendFormat(" Cooler[{0}].CurrentLevel: {1}{2}", i,
   380               settings.Cooler[i].CurrentLevel, Environment.NewLine);
   381             r.AppendFormat(" Cooler[{0}].DefaultPolicy: {1}{2}", i,
   382               settings.Cooler[i].DefaultPolicy, Environment.NewLine);
   383             r.AppendFormat(" Cooler[{0}].CurrentPolicy: {1}{2}", i,
   384               settings.Cooler[i].CurrentPolicy, Environment.NewLine);
   385             r.AppendFormat(" Cooler[{0}].Target: {1}{2}", i,
   386               settings.Cooler[i].Target, Environment.NewLine);
   387             r.AppendFormat(" Cooler[{0}].ControlType: {1}{2}", i,
   388               settings.Cooler[i].ControlType, Environment.NewLine);
   389             r.AppendFormat(" Cooler[{0}].Active: {1}{2}", i,
   390               settings.Cooler[i].Active, Environment.NewLine);
   391           }
   392         } else {
   393           r.Append(" Status: ");
   394           r.AppendLine(status.ToString());
   395         }
   396         r.AppendLine();
   397       }
   398 
   399       if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue) {
   400         NvMemoryInfo memoryInfo = new NvMemoryInfo();
   401         memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
   402         memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
   403         NvStatus status = NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value, 
   404           ref memoryInfo);
   405 
   406         r.AppendLine("Memory Info");
   407         r.AppendLine();
   408         if (status == NvStatus.OK) {
   409           for (int i = 0; i < memoryInfo.Values.Length; i++)
   410             r.AppendFormat(" Value[{0}]: {1}{2}", i,
   411                 memoryInfo.Values[i], Environment.NewLine);
   412         } else {
   413           r.Append(" Status: ");
   414           r.AppendLine(status.ToString());
   415         }
   416         r.AppendLine();
   417       }
   418 
   419       return r.ToString();
   420     }
   421   }
   422 }