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