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