Added a simple way to customize the sensor gadget background. If any of the files gadget_background.png, gadget_image.png, gadget_foreground.png, gadget_bar_background.png or gadget_bar_foreground.png is present in the working directory then these files are used instead of the built in files.
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-2012
20 the Initial Developer. All Rights Reserved.
25 Alternatively, the contents of this file may be used under the terms of
26 either the GNU General Public License Version 2 or later (the "GPL"), or
27 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 in which case the provisions of the GPL or the LGPL are applicable instead
29 of those above. If you wish to allow use of your version of this file only
30 under the terms of either the GPL or the LGPL, and not to allow others to
31 use your version of this file under the terms of the MPL, indicate your
32 decision by deleting the provisions above and replace them with the notice
33 and other provisions required by the GPL or the LGPL. If you do not delete
34 the provisions above, a recipient may use your version of this file under
35 the terms of any one of the MPL, the GPL or the LGPL.
40 using System.Globalization;
43 namespace OpenHardwareMonitor.Hardware.Nvidia {
44 internal class NvidiaGPU : Hardware {
46 private readonly int adapterIndex;
47 private readonly NvPhysicalGpuHandle handle;
48 private readonly NvDisplayHandle? displayHandle;
50 private readonly Sensor[] temperatures;
51 private readonly Sensor fan;
52 private readonly Sensor[] clocks;
53 private readonly Sensor[] loads;
54 private readonly Sensor control;
55 private readonly Sensor memoryLoad;
56 private readonly Control fanControl;
58 private bool restoreDefaultFanSpeedRequired;
59 private NvLevel initialFanSpeedValue;
61 public NvidiaGPU(int adapterIndex, NvPhysicalGpuHandle handle,
62 NvDisplayHandle? displayHandle, ISettings settings)
63 : base(GetName(handle), new Identifier("nvidiagpu",
64 adapterIndex.ToString(CultureInfo.InvariantCulture)), settings) {
65 this.adapterIndex = adapterIndex;
67 this.displayHandle = displayHandle;
69 NvGPUThermalSettings thermalSettings = GetThermalSettings();
70 temperatures = new Sensor[thermalSettings.Count];
71 for (int i = 0; i < temperatures.Length; i++) {
72 NvSensor sensor = thermalSettings.Sensor[i];
74 switch (sensor.Target) {
75 case NvThermalTarget.BOARD: name = "GPU Board"; break;
76 case NvThermalTarget.GPU: name = "GPU Core"; break;
77 case NvThermalTarget.MEMORY: name = "GPU Memory"; break;
78 case NvThermalTarget.POWER_SUPPLY: name = "GPU Power Supply"; break;
79 case NvThermalTarget.UNKNOWN: name = "GPU Unknown"; break;
80 default: name = "GPU"; break;
82 temperatures[i] = new Sensor(name, i, SensorType.Temperature, this,
83 new ParameterDescription[0], settings);
84 ActivateSensor(temperatures[i]);
88 if (NVAPI.NvAPI_GPU_GetTachReading != null &&
89 NVAPI.NvAPI_GPU_GetTachReading(handle, out value) == NvStatus.OK) {
91 fan = new Sensor("GPU", 0, SensorType.Fan, this, settings);
96 clocks = new Sensor[3];
97 clocks[0] = new Sensor("GPU Core", 0, SensorType.Clock, this, settings);
98 clocks[1] = new Sensor("GPU Memory", 1, SensorType.Clock, this, settings);
99 clocks[2] = new Sensor("GPU Shader", 2, SensorType.Clock, this, settings);
100 for (int i = 0; i < clocks.Length; i++)
101 ActivateSensor(clocks[i]);
103 loads = new Sensor[3];
104 loads[0] = new Sensor("GPU Core", 0, SensorType.Load, this, settings);
105 loads[1] = new Sensor("GPU Memory Controller", 1, SensorType.Load, this, settings);
106 loads[2] = new Sensor("GPU Video Engine", 2, SensorType.Load, this, settings);
107 memoryLoad = new Sensor("GPU Memory", 3, SensorType.Load, this, settings);
109 control = new Sensor("GPU Fan", 0, SensorType.Control, this, settings);
111 NvGPUCoolerSettings coolerSettings = GetCoolerSettings();
112 if (coolerSettings.Count > 0) {
113 fanControl = new Control(control, settings,
114 coolerSettings.Cooler[0].DefaultMin,
115 coolerSettings.Cooler[0].DefaultMax);
116 fanControl.ControlModeChanged += ControlModeChanged;
117 fanControl.SoftwareControlValueChanged += SoftwareControlValueChanged;
118 ControlModeChanged(fanControl);
119 control.Control = fanControl;
124 private static string GetName(NvPhysicalGpuHandle handle) {
126 if (NVAPI.NvAPI_GPU_GetFullName(handle, out gpuName) == NvStatus.OK) {
127 return "NVIDIA " + gpuName.Trim();
133 public override HardwareType HardwareType {
134 get { return HardwareType.GpuNvidia; }
137 private NvGPUThermalSettings GetThermalSettings() {
138 NvGPUThermalSettings settings = new NvGPUThermalSettings();
139 settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
140 settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
141 settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
142 if (!(NVAPI.NvAPI_GPU_GetThermalSettings != null &&
143 NVAPI.NvAPI_GPU_GetThermalSettings(handle, (int)NvThermalTarget.ALL,
144 ref settings) == NvStatus.OK))
151 private NvGPUCoolerSettings GetCoolerSettings() {
152 NvGPUCoolerSettings settings = new NvGPUCoolerSettings();
153 settings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
154 settings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
155 if (!(NVAPI.NvAPI_GPU_GetCoolerSettings != null &&
156 NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0,
157 ref settings) == NvStatus.OK))
164 private uint[] GetClocks() {
165 NvClocks allClocks = new NvClocks();
166 allClocks.Version = NVAPI.GPU_CLOCKS_VER;
167 allClocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
168 if (NVAPI.NvAPI_GPU_GetAllClocks != null &&
169 NVAPI.NvAPI_GPU_GetAllClocks(handle, ref allClocks) == NvStatus.OK) {
170 return allClocks.Clock;
175 public override void Update() {
176 NvGPUThermalSettings settings = GetThermalSettings();
177 foreach (Sensor sensor in temperatures)
178 sensor.Value = settings.Sensor[sensor.Index].CurrentTemp;
182 NVAPI.NvAPI_GPU_GetTachReading(handle, out value);
186 uint[] values = GetClocks();
187 if (values != null) {
188 clocks[0].Value = 0.001f * values[0];
189 clocks[1].Value = 0.001f * values[8];
190 clocks[2].Value = 0.001f * values[14];
191 if (values[30] != 0) {
192 clocks[0].Value = 0.0005f * values[30];
193 clocks[2].Value = 0.001f * values[30];
197 NvPStates states = new NvPStates();
198 states.Version = NVAPI.GPU_PSTATES_VER;
199 states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
200 if (NVAPI.NvAPI_GPU_GetPStates != null &&
201 NVAPI.NvAPI_GPU_GetPStates(handle, ref states) == NvStatus.OK) {
202 for (int i = 0; i < 3; i++)
203 if (states.PStates[i].Present) {
204 loads[i].Value = states.PStates[i].Percentage;
205 ActivateSensor(loads[i]);
208 NvUsages usages = new NvUsages();
209 usages.Version = NVAPI.GPU_USAGES_VER;
210 usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
211 if (NVAPI.NvAPI_GPU_GetUsages != null &&
212 NVAPI.NvAPI_GPU_GetUsages(handle, ref usages) == NvStatus.OK) {
213 loads[0].Value = usages.Usage[2];
214 loads[1].Value = usages.Usage[6];
215 loads[2].Value = usages.Usage[10];
216 for (int i = 0; i < 3; i++)
217 ActivateSensor(loads[i]);
222 NvGPUCoolerSettings coolerSettings = GetCoolerSettings();
223 if (coolerSettings.Count > 0) {
224 control.Value = coolerSettings.Cooler[0].CurrentLevel;
225 ActivateSensor(control);
228 NvMemoryInfo memoryInfo = new NvMemoryInfo();
229 memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
230 memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
231 if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue &&
232 NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value, ref memoryInfo) ==
234 uint totalMemory = memoryInfo.Values[0];
235 uint freeMemory = memoryInfo.Values[4];
236 float usedMemory = Math.Max(totalMemory - freeMemory, 0);
237 memoryLoad.Value = 100f * usedMemory / totalMemory;
238 ActivateSensor(memoryLoad);
242 public override string GetReport() {
243 StringBuilder r = new StringBuilder();
245 r.AppendLine("Nvidia GPU");
248 r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
249 r.AppendFormat("Index: {0}{1}", adapterIndex, Environment.NewLine);
251 if (displayHandle.HasValue && NVAPI.NvAPI_GetDisplayDriverVersion != null) {
252 NvDisplayDriverVersion driverVersion = new NvDisplayDriverVersion();
253 driverVersion.Version = NVAPI.DISPLAY_DRIVER_VERSION_VER;
254 if (NVAPI.NvAPI_GetDisplayDriverVersion(displayHandle.Value,
255 ref driverVersion) == NvStatus.OK) {
256 r.Append("Driver Version: ");
257 r.Append(driverVersion.DriverVersion / 100);
259 r.Append((driverVersion.DriverVersion % 100).ToString("00",
260 CultureInfo.InvariantCulture));
262 r.Append("Driver Branch: ");
263 r.AppendLine(driverVersion.BuildBranch);
268 if (NVAPI.NvAPI_GPU_GetPCIIdentifiers != null) {
269 uint deviceId, subSystemId, revisionId, extDeviceId;
271 NvStatus status = NVAPI.NvAPI_GPU_GetPCIIdentifiers(handle,
272 out deviceId, out subSystemId, out revisionId, out extDeviceId);
274 if (status == NvStatus.OK) {
275 r.Append("DeviceID: 0x");
276 r.AppendLine(deviceId.ToString("X", CultureInfo.InvariantCulture));
277 r.Append("SubSystemID: 0x");
278 r.AppendLine(subSystemId.ToString("X", CultureInfo.InvariantCulture));
279 r.Append("RevisionID: 0x");
280 r.AppendLine(revisionId.ToString("X", CultureInfo.InvariantCulture));
281 r.Append("ExtDeviceID: 0x");
282 r.AppendLine(extDeviceId.ToString("X", CultureInfo.InvariantCulture));
287 if (NVAPI.NvAPI_GPU_GetThermalSettings != null) {
288 NvGPUThermalSettings settings = new NvGPUThermalSettings();
289 settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
290 settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
291 settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
293 NvStatus status = NVAPI.NvAPI_GPU_GetThermalSettings(handle,
294 (int)NvThermalTarget.ALL, ref settings);
296 r.AppendLine("Thermal Settings");
298 if (status == NvStatus.OK) {
299 for (int i = 0; i < settings.Count; i++) {
300 r.AppendFormat(" Sensor[{0}].Controller: {1}{2}", i,
301 settings.Sensor[i].Controller, Environment.NewLine);
302 r.AppendFormat(" Sensor[{0}].DefaultMinTemp: {1}{2}", i,
303 settings.Sensor[i].DefaultMinTemp, Environment.NewLine);
304 r.AppendFormat(" Sensor[{0}].DefaultMaxTemp: {1}{2}", i,
305 settings.Sensor[i].DefaultMaxTemp, Environment.NewLine);
306 r.AppendFormat(" Sensor[{0}].CurrentTemp: {1}{2}", i,
307 settings.Sensor[i].CurrentTemp, Environment.NewLine);
308 r.AppendFormat(" Sensor[{0}].Target: {1}{2}", i,
309 settings.Sensor[i].Target, Environment.NewLine);
312 r.Append(" Status: ");
313 r.AppendLine(status.ToString());
318 if (NVAPI.NvAPI_GPU_GetAllClocks != null) {
319 NvClocks allClocks = new NvClocks();
320 allClocks.Version = NVAPI.GPU_CLOCKS_VER;
321 allClocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
322 NvStatus status = NVAPI.NvAPI_GPU_GetAllClocks(handle, ref allClocks);
324 r.AppendLine("Clocks");
326 if (status == NvStatus.OK) {
327 for (int i = 0; i < allClocks.Clock.Length; i++)
328 if (allClocks.Clock[i] > 0) {
329 r.AppendFormat(" Clock[{0}]: {1}{2}", i, allClocks.Clock[i],
330 Environment.NewLine);
333 r.Append(" Status: ");
334 r.AppendLine(status.ToString());
339 if (NVAPI.NvAPI_GPU_GetTachReading != null) {
341 NvStatus status = NVAPI.NvAPI_GPU_GetTachReading(handle, out tachValue);
343 r.AppendLine("Tachometer");
345 if (status == NvStatus.OK) {
346 r.AppendFormat(" Value: {0}{1}", tachValue, Environment.NewLine);
348 r.Append(" Status: ");
349 r.AppendLine(status.ToString());
354 if (NVAPI.NvAPI_GPU_GetPStates != null) {
355 NvPStates states = new NvPStates();
356 states.Version = NVAPI.GPU_PSTATES_VER;
357 states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
358 NvStatus status = NVAPI.NvAPI_GPU_GetPStates(handle, ref states);
360 r.AppendLine("P-States");
362 if (status == NvStatus.OK) {
363 for (int i = 0; i < states.PStates.Length; i++)
364 if (states.PStates[i].Present)
365 r.AppendFormat(" Percentage[{0}]: {1}{2}", i,
366 states.PStates[i].Percentage, Environment.NewLine);
368 r.Append(" Status: ");
369 r.AppendLine(status.ToString());
374 if (NVAPI.NvAPI_GPU_GetUsages != null) {
375 NvUsages usages = new NvUsages();
376 usages.Version = NVAPI.GPU_USAGES_VER;
377 usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
378 NvStatus status = NVAPI.NvAPI_GPU_GetUsages(handle, ref usages);
380 r.AppendLine("Usages");
382 if (status == NvStatus.OK) {
383 for (int i = 0; i < usages.Usage.Length; i++)
384 if (usages.Usage[i] > 0)
385 r.AppendFormat(" Usage[{0}]: {1}{2}", i,
386 usages.Usage[i], Environment.NewLine);
388 r.Append(" Status: ");
389 r.AppendLine(status.ToString());
394 if (NVAPI.NvAPI_GPU_GetCoolerSettings != null) {
395 NvGPUCoolerSettings settings = new NvGPUCoolerSettings();
396 settings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
397 settings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
399 NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, ref settings);
401 r.AppendLine("Cooler Settings");
403 if (status == NvStatus.OK) {
404 for (int i = 0; i < settings.Count; i++) {
405 r.AppendFormat(" Cooler[{0}].Type: {1}{2}", i,
406 settings.Cooler[i].Type, Environment.NewLine);
407 r.AppendFormat(" Cooler[{0}].Controller: {1}{2}", i,
408 settings.Cooler[i].Controller, Environment.NewLine);
409 r.AppendFormat(" Cooler[{0}].DefaultMin: {1}{2}", i,
410 settings.Cooler[i].DefaultMin, Environment.NewLine);
411 r.AppendFormat(" Cooler[{0}].DefaultMax: {1}{2}", i,
412 settings.Cooler[i].DefaultMax, Environment.NewLine);
413 r.AppendFormat(" Cooler[{0}].CurrentMin: {1}{2}", i,
414 settings.Cooler[i].CurrentMin, Environment.NewLine);
415 r.AppendFormat(" Cooler[{0}].CurrentMax: {1}{2}", i,
416 settings.Cooler[i].CurrentMax, Environment.NewLine);
417 r.AppendFormat(" Cooler[{0}].CurrentLevel: {1}{2}", i,
418 settings.Cooler[i].CurrentLevel, Environment.NewLine);
419 r.AppendFormat(" Cooler[{0}].DefaultPolicy: {1}{2}", i,
420 settings.Cooler[i].DefaultPolicy, Environment.NewLine);
421 r.AppendFormat(" Cooler[{0}].CurrentPolicy: {1}{2}", i,
422 settings.Cooler[i].CurrentPolicy, Environment.NewLine);
423 r.AppendFormat(" Cooler[{0}].Target: {1}{2}", i,
424 settings.Cooler[i].Target, Environment.NewLine);
425 r.AppendFormat(" Cooler[{0}].ControlType: {1}{2}", i,
426 settings.Cooler[i].ControlType, Environment.NewLine);
427 r.AppendFormat(" Cooler[{0}].Active: {1}{2}", i,
428 settings.Cooler[i].Active, Environment.NewLine);
431 r.Append(" Status: ");
432 r.AppendLine(status.ToString());
437 if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue) {
438 NvMemoryInfo memoryInfo = new NvMemoryInfo();
439 memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
440 memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
441 NvStatus status = NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value,
444 r.AppendLine("Memory Info");
446 if (status == NvStatus.OK) {
447 for (int i = 0; i < memoryInfo.Values.Length; i++)
448 r.AppendFormat(" Value[{0}]: {1}{2}", i,
449 memoryInfo.Values[i], Environment.NewLine);
451 r.Append(" Status: ");
452 r.AppendLine(status.ToString());
460 private void SoftwareControlValueChanged(IControl control) {
461 SaveDefaultFanSpeed();
462 NvGPUCoolerLevels coolerLevels = new NvGPUCoolerLevels();
463 coolerLevels.Version = NVAPI.GPU_COOLER_LEVELS_VER;
464 coolerLevels.Levels = new NvLevel[NVAPI.MAX_COOLER_PER_GPU];
465 coolerLevels.Levels[0].Level = (int)control.SoftwareValue;
466 coolerLevels.Levels[0].Policy = 1;
467 NVAPI.NvAPI_GPU_SetCoolerLevels(handle, 0, ref coolerLevels);
470 private void SaveDefaultFanSpeed() {
471 if (!restoreDefaultFanSpeedRequired) {
472 NvGPUCoolerSettings coolerSettings = GetCoolerSettings();
473 if (coolerSettings.Count > 0) {
474 restoreDefaultFanSpeedRequired = true;
475 initialFanSpeedValue.Level = coolerSettings.Cooler[0].CurrentLevel;
476 initialFanSpeedValue.Policy = coolerSettings.Cooler[0].CurrentPolicy;
481 private void ControlModeChanged(IControl control) {
482 if (control.ControlMode == ControlMode.Default) {
483 RestoreDefaultFanSpeed();
485 SoftwareControlValueChanged(control);
489 private void RestoreDefaultFanSpeed() {
490 if (restoreDefaultFanSpeedRequired) {
491 NvGPUCoolerLevels coolerLevels = new NvGPUCoolerLevels();
492 coolerLevels.Version = NVAPI.GPU_COOLER_LEVELS_VER;
493 coolerLevels.Levels = new NvLevel[NVAPI.MAX_COOLER_PER_GPU];
494 coolerLevels.Levels[0] = initialFanSpeedValue;
495 NVAPI.NvAPI_GPU_SetCoolerLevels(handle, 0, ref coolerLevels);
496 restoreDefaultFanSpeedRequired = false;