Fixed some Code Analysis warnings.
3 Version: MPL 1.1/GPL 2.0/LGPL 2.1
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
9 http://www.mozilla.org/MPL/
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.
15 The Original Code is the Open Hardware Monitor code.
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.
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.
39 using System.Collections.Generic;
40 using System.Globalization;
43 namespace OpenHardwareMonitor.Hardware.Nvidia {
44 internal class NvidiaGPU : Hardware, IHardware {
47 private int adapterIndex;
48 private NvPhysicalGpuHandle handle;
49 private NvDisplayHandle? displayHandle;
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;
58 public NvidiaGPU(int adapterIndex, NvPhysicalGpuHandle handle,
59 NvDisplayHandle? displayHandle, ISettings settings)
62 if (NVAPI.NvAPI_GPU_GetFullName(handle, out gpuName) == NvStatus.OK) {
63 this.name = "NVIDIA " + gpuName.Trim();
67 this.adapterIndex = adapterIndex;
69 this.displayHandle = displayHandle;
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];
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;
84 temperatures[i] = new Sensor(name, i, SensorType.Temperature, this,
85 new ParameterDescription[0], settings);
86 ActivateSensor(temperatures[i]);
90 if (NVAPI.NvAPI_GPU_GetTachReading != null &&
91 NVAPI.NvAPI_GPU_GetTachReading(handle, out value) == NvStatus.OK) {
93 fan = new Sensor("GPU", 0, SensorType.Fan, this, settings);
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]);
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);
111 control = new Sensor("GPU Fan", 0, SensorType.Control, this, settings);
114 public override string Name {
118 public override Identifier Identifier {
120 return new Identifier("nvidiagpu",
121 adapterIndex.ToString(CultureInfo.InvariantCulture));
125 public override HardwareType HardwareType {
126 get { return HardwareType.GPU; }
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) {
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;
153 public override void Update() {
154 NvGPUThermalSettings settings = GetThermalSettings();
155 foreach (Sensor sensor in temperatures)
156 sensor.Value = settings.Sensor[sensor.Index].CurrentTemp;
160 NVAPI.NvAPI_GPU_GetTachReading(handle, out value);
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];
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]);
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]);
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);
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) ==
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);
224 public override string GetReport() {
225 StringBuilder r = new StringBuilder();
227 r.AppendLine("Nvidia GPU");
230 r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
231 r.AppendFormat("Index: {0}{1}", adapterIndex, Environment.NewLine);
233 if (displayHandle.HasValue && NVAPI.NvAPI_GetDisplayDriverVersion != null)
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);
242 r.Append((driverVersion.DriverVersion % 100).ToString("00",
243 CultureInfo.InvariantCulture));
245 r.Append("Driver Branch: ");
246 r.AppendLine(driverVersion.BuildBranch);
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];
257 NvStatus status = NVAPI.NvAPI_GPU_GetThermalSettings(handle,
258 (int)NvThermalTarget.ALL, ref settings);
260 r.AppendLine("Thermal Settings");
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);
276 r.Append(" Status: ");
277 r.AppendLine(status.ToString());
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);
288 r.AppendLine("Clocks");
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);
297 r.Append(" Status: ");
298 r.AppendLine(status.ToString());
303 if (NVAPI.NvAPI_GPU_GetTachReading != null) {
305 NvStatus status = NVAPI.NvAPI_GPU_GetTachReading(handle, out tachValue);
307 r.AppendLine("Tachometer");
309 if (status == NvStatus.OK) {
310 r.AppendFormat(" Value: {0}{1}", tachValue, Environment.NewLine);
312 r.Append(" Status: ");
313 r.AppendLine(status.ToString());
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);
324 r.AppendLine("P-States");
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);
332 r.Append(" Status: ");
333 r.AppendLine(status.ToString());
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);
344 r.AppendLine("Usages");
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);
352 r.Append(" Status: ");
353 r.AppendLine(status.ToString());
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];
363 NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, ref settings);
365 r.AppendLine("Cooler Settings");
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);
395 r.Append(" Status: ");
396 r.AppendLine(status.ToString());
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,
408 r.AppendLine("Memory Info");
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);
415 r.Append(" Status: ");
416 r.AppendLine(status.ToString());