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