Hardware/Nvidia/NvidiaGPU.cs
author moel.mich
Tue, 24 Aug 2010 20:14:54 +0000
changeset 174 51d62ed28ff5
parent 166 fa9dfbfc4145
child 176 c16fd81b520a
permissions -rw-r--r--
Fixed Issue 105 and Issue 106.
     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", 
   243             CultureInfo.InvariantCulture));
   244           r.AppendLine();
   245           r.Append("Driver Branch: ");
   246           r.AppendLine(driverVersion.BuildBranch);
   247         }
   248       }
   249       r.AppendLine();
   250 
   251       if (NVAPI.NvAPI_GPU_GetThermalSettings != null) {
   252         NvGPUThermalSettings settings = new NvGPUThermalSettings();
   253         settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
   254         settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
   255         settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
   256 
   257         NvStatus status = NVAPI.NvAPI_GPU_GetThermalSettings(handle,
   258           (int)NvThermalTarget.ALL, ref settings);
   259 
   260         r.AppendLine("Thermal Settings");
   261         r.AppendLine();
   262         if (status == NvStatus.OK) {
   263           for (int i = 0; i < settings.Count; i++) {
   264             r.AppendFormat(" Sensor[{0}].Controller: {1}{2}", i,
   265               settings.Sensor[i].Controller, Environment.NewLine);
   266             r.AppendFormat(" Sensor[{0}].DefaultMinTemp: {1}{2}", i,
   267               settings.Sensor[i].DefaultMinTemp, Environment.NewLine);
   268             r.AppendFormat(" Sensor[{0}].DefaultMaxTemp: {1}{2}", i,
   269               settings.Sensor[i].DefaultMaxTemp, Environment.NewLine);
   270             r.AppendFormat(" Sensor[{0}].CurrentTemp: {1}{2}", i,
   271               settings.Sensor[i].CurrentTemp, Environment.NewLine);
   272             r.AppendFormat(" Sensor[{0}].Target: {1}{2}", i,
   273               settings.Sensor[i].Target, Environment.NewLine);
   274           }
   275         } else {
   276           r.Append(" Status: ");
   277           r.AppendLine(status.ToString());
   278         }
   279         r.AppendLine();
   280       }      
   281 
   282       if (NVAPI.NvAPI_GPU_GetAllClocks != null) {
   283         NvClocks allClocks = new NvClocks();
   284         allClocks.Version = NVAPI.GPU_CLOCKS_VER;
   285         allClocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
   286         NvStatus status = NVAPI.NvAPI_GPU_GetAllClocks(handle, ref allClocks);
   287 
   288         r.AppendLine("Clocks");
   289         r.AppendLine();
   290         if (status == NvStatus.OK) {
   291           for (int i = 0; i < allClocks.Clock.Length; i++)
   292             if (allClocks.Clock[i] > 0) {
   293               r.AppendFormat(" Clock[{0}]: {1}{2}", i, allClocks.Clock[i],
   294                 Environment.NewLine);
   295             }
   296         } else {
   297           r.Append(" Status: ");
   298           r.AppendLine(status.ToString());
   299         }
   300         r.AppendLine();
   301       }         
   302            
   303       if (NVAPI.NvAPI_GPU_GetTachReading != null) {
   304         int tachValue; 
   305         NvStatus status = NVAPI.NvAPI_GPU_GetTachReading(handle, out tachValue);
   306 
   307         r.AppendLine("Tachometer");
   308         r.AppendLine();
   309         if (status == NvStatus.OK) {
   310           r.AppendFormat(" Value: {0}{1}", tachValue, Environment.NewLine);
   311         } else {
   312           r.Append(" Status: ");
   313           r.AppendLine(status.ToString());
   314         }
   315         r.AppendLine();
   316       }
   317 
   318       if (NVAPI.NvAPI_GPU_GetPStates != null) {
   319         NvPStates states = new NvPStates();
   320         states.Version = NVAPI.GPU_PSTATES_VER;
   321         states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
   322         NvStatus status = NVAPI.NvAPI_GPU_GetPStates(handle, ref states);
   323 
   324         r.AppendLine("P-States");
   325         r.AppendLine();
   326         if (status == NvStatus.OK) {
   327           for (int i = 0; i < states.PStates.Length; i++)
   328             if (states.PStates[i].Present)
   329               r.AppendFormat(" Percentage[{0}]: {1}{2}", i,
   330                 states.PStates[i].Percentage, Environment.NewLine);
   331         } else {
   332           r.Append(" Status: ");
   333           r.AppendLine(status.ToString());
   334         }
   335         r.AppendLine();
   336       }
   337 
   338       if (NVAPI.NvAPI_GPU_GetUsages != null) {
   339         NvUsages usages = new NvUsages();
   340         usages.Version = NVAPI.GPU_USAGES_VER;
   341         usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
   342         NvStatus status = NVAPI.NvAPI_GPU_GetUsages(handle, ref usages);
   343      
   344         r.AppendLine("Usages");
   345         r.AppendLine();
   346         if (status == NvStatus.OK) {
   347           for (int i = 0; i < usages.Usage.Length; i++)
   348             if (usages.Usage[i] > 0)
   349               r.AppendFormat(" Usage[{0}]: {1}{2}", i,
   350                 usages.Usage[i], Environment.NewLine);
   351         } else {
   352           r.Append(" Status: ");
   353           r.AppendLine(status.ToString());
   354         }
   355         r.AppendLine();
   356       }
   357 
   358       if (NVAPI.NvAPI_GPU_GetCoolerSettings != null) {
   359         NvGPUCoolerSettings settings = new NvGPUCoolerSettings();
   360         settings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
   361         settings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
   362         NvStatus status =
   363           NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, ref settings);
   364 
   365         r.AppendLine("Cooler Settings");
   366         r.AppendLine();
   367         if (status == NvStatus.OK) {
   368           for (int i = 0; i < settings.Count; i++) {
   369             r.AppendFormat(" Cooler[{0}].Type: {1}{2}", i,
   370               settings.Cooler[i].Type, Environment.NewLine);
   371             r.AppendFormat(" Cooler[{0}].Controller: {1}{2}", i,
   372               settings.Cooler[i].Controller, Environment.NewLine);
   373             r.AppendFormat(" Cooler[{0}].DefaultMin: {1}{2}", i,
   374               settings.Cooler[i].DefaultMin, Environment.NewLine);
   375             r.AppendFormat(" Cooler[{0}].DefaultMax: {1}{2}", i,
   376               settings.Cooler[i].DefaultMax, Environment.NewLine);
   377             r.AppendFormat(" Cooler[{0}].CurrentMin: {1}{2}", i,
   378               settings.Cooler[i].CurrentMin, Environment.NewLine);
   379             r.AppendFormat(" Cooler[{0}].CurrentMax: {1}{2}", i,
   380               settings.Cooler[i].CurrentMax, Environment.NewLine);
   381             r.AppendFormat(" Cooler[{0}].CurrentLevel: {1}{2}", i,
   382               settings.Cooler[i].CurrentLevel, Environment.NewLine);
   383             r.AppendFormat(" Cooler[{0}].DefaultPolicy: {1}{2}", i,
   384               settings.Cooler[i].DefaultPolicy, Environment.NewLine);
   385             r.AppendFormat(" Cooler[{0}].CurrentPolicy: {1}{2}", i,
   386               settings.Cooler[i].CurrentPolicy, Environment.NewLine);
   387             r.AppendFormat(" Cooler[{0}].Target: {1}{2}", i,
   388               settings.Cooler[i].Target, Environment.NewLine);
   389             r.AppendFormat(" Cooler[{0}].ControlType: {1}{2}", i,
   390               settings.Cooler[i].ControlType, Environment.NewLine);
   391             r.AppendFormat(" Cooler[{0}].Active: {1}{2}", i,
   392               settings.Cooler[i].Active, Environment.NewLine);
   393           }
   394         } else {
   395           r.Append(" Status: ");
   396           r.AppendLine(status.ToString());
   397         }
   398         r.AppendLine();
   399       }
   400 
   401       if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue) {
   402         NvMemoryInfo memoryInfo = new NvMemoryInfo();
   403         memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
   404         memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
   405         NvStatus status = NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value, 
   406           ref memoryInfo);
   407 
   408         r.AppendLine("Memory Info");
   409         r.AppendLine();
   410         if (status == NvStatus.OK) {
   411           for (int i = 0; i < memoryInfo.Values.Length; i++)
   412             r.AppendFormat(" Value[{0}]: {1}{2}", i,
   413                 memoryInfo.Values[i], Environment.NewLine);
   414         } else {
   415           r.Append(" Status: ");
   416           r.AppendLine(status.ToString());
   417         }
   418         r.AppendLine();
   419       }
   420 
   421       return r.ToString();
   422     }
   423   }
   424 }