Adding SoundGraphDisplay and SensorFrontView classes.
They were respectively based on SystemTray and SensorNotifyIcon.
SoundGraphDisplay is now able to load iMONDisplay.dll providing it lives on your PATH.
Adding option to sensor context menu for adding it into FrontView.
3 This Source Code Form is subject to the terms of the Mozilla Public
4 License, v. 2.0. If a copy of the MPL was not distributed with this
5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 Copyright (C) 2009-2014 Michael Möller <mmoeller@openhardwaremonitor.org>
8 Copyright (C) 2011 Christian Vallières
13 using System.Globalization;
16 namespace OpenHardwareMonitor.Hardware.Nvidia {
17 internal class NvidiaGPU : Hardware {
19 private readonly int adapterIndex;
20 private readonly NvPhysicalGpuHandle handle;
21 private readonly NvDisplayHandle? displayHandle;
23 private readonly Sensor[] temperatures;
24 private readonly Sensor fan;
25 private readonly Sensor[] clocks;
26 private readonly Sensor[] loads;
27 private readonly Sensor control;
28 private readonly Sensor memoryLoad;
29 private readonly Control fanControl;
31 public NvidiaGPU(int adapterIndex, NvPhysicalGpuHandle handle,
32 NvDisplayHandle? displayHandle, ISettings settings)
33 : base(GetName(handle), new Identifier("nvidiagpu",
34 adapterIndex.ToString(CultureInfo.InvariantCulture)), settings) {
35 this.adapterIndex = adapterIndex;
37 this.displayHandle = displayHandle;
39 NvGPUThermalSettings thermalSettings = GetThermalSettings();
40 temperatures = new Sensor[thermalSettings.Count];
41 for (int i = 0; i < temperatures.Length; i++) {
42 NvSensor sensor = thermalSettings.Sensor[i];
44 switch (sensor.Target) {
45 case NvThermalTarget.BOARD: name = "GPU Board"; break;
46 case NvThermalTarget.GPU: name = "GPU Core"; break;
47 case NvThermalTarget.MEMORY: name = "GPU Memory"; break;
48 case NvThermalTarget.POWER_SUPPLY: name = "GPU Power Supply"; break;
49 case NvThermalTarget.UNKNOWN: name = "GPU Unknown"; break;
50 default: name = "GPU"; break;
52 temperatures[i] = new Sensor(name, i, SensorType.Temperature, this,
53 new ParameterDescription[0], settings);
54 ActivateSensor(temperatures[i]);
58 if (NVAPI.NvAPI_GPU_GetTachReading != null &&
59 NVAPI.NvAPI_GPU_GetTachReading(handle, out value) == NvStatus.OK) {
61 fan = new Sensor("GPU", 0, SensorType.Fan, this, settings);
66 clocks = new Sensor[3];
67 clocks[0] = new Sensor("GPU Core", 0, SensorType.Clock, this, settings);
68 clocks[1] = new Sensor("GPU Memory", 1, SensorType.Clock, this, settings);
69 clocks[2] = new Sensor("GPU Shader", 2, SensorType.Clock, this, settings);
70 for (int i = 0; i < clocks.Length; i++)
71 ActivateSensor(clocks[i]);
73 loads = new Sensor[3];
74 loads[0] = new Sensor("GPU Core", 0, SensorType.Load, this, settings);
75 loads[1] = new Sensor("GPU Memory Controller", 1, SensorType.Load, this, settings);
76 loads[2] = new Sensor("GPU Video Engine", 2, SensorType.Load, this, settings);
77 memoryLoad = new Sensor("GPU Memory", 3, SensorType.Load, this, settings);
79 control = new Sensor("GPU Fan", 0, SensorType.Control, this, settings);
81 NvGPUCoolerSettings coolerSettings = GetCoolerSettings();
82 if (coolerSettings.Count > 0) {
83 fanControl = new Control(control, settings,
84 coolerSettings.Cooler[0].DefaultMin,
85 coolerSettings.Cooler[0].DefaultMax);
86 fanControl.ControlModeChanged += ControlModeChanged;
87 fanControl.SoftwareControlValueChanged += SoftwareControlValueChanged;
88 ControlModeChanged(fanControl);
89 control.Control = fanControl;
94 private static string GetName(NvPhysicalGpuHandle handle) {
96 if (NVAPI.NvAPI_GPU_GetFullName(handle, out gpuName) == NvStatus.OK) {
97 return "NVIDIA " + gpuName.Trim();
103 public override HardwareType HardwareType {
104 get { return HardwareType.GpuNvidia; }
107 private NvGPUThermalSettings GetThermalSettings() {
108 NvGPUThermalSettings settings = new NvGPUThermalSettings();
109 settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
110 settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
111 settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
112 if (!(NVAPI.NvAPI_GPU_GetThermalSettings != null &&
113 NVAPI.NvAPI_GPU_GetThermalSettings(handle, (int)NvThermalTarget.ALL,
114 ref settings) == NvStatus.OK))
121 private NvGPUCoolerSettings GetCoolerSettings() {
122 NvGPUCoolerSettings settings = new NvGPUCoolerSettings();
123 settings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
124 settings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
125 if (!(NVAPI.NvAPI_GPU_GetCoolerSettings != null &&
126 NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0,
127 ref settings) == NvStatus.OK))
134 private uint[] GetClocks() {
135 NvClocks allClocks = new NvClocks();
136 allClocks.Version = NVAPI.GPU_CLOCKS_VER;
137 allClocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
138 if (NVAPI.NvAPI_GPU_GetAllClocks != null &&
139 NVAPI.NvAPI_GPU_GetAllClocks(handle, ref allClocks) == NvStatus.OK) {
140 return allClocks.Clock;
145 public override void Update() {
146 NvGPUThermalSettings settings = GetThermalSettings();
147 foreach (Sensor sensor in temperatures)
148 sensor.Value = settings.Sensor[sensor.Index].CurrentTemp;
152 NVAPI.NvAPI_GPU_GetTachReading(handle, out value);
156 uint[] values = GetClocks();
157 if (values != null) {
158 clocks[0].Value = 0.001f * values[0];
159 clocks[1].Value = 0.001f * values[8];
160 clocks[2].Value = 0.001f * values[14];
161 if (values[30] != 0) {
162 clocks[0].Value = 0.0005f * values[30];
163 clocks[2].Value = 0.001f * values[30];
167 NvPStates states = new NvPStates();
168 states.Version = NVAPI.GPU_PSTATES_VER;
169 states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
170 if (NVAPI.NvAPI_GPU_GetPStates != null &&
171 NVAPI.NvAPI_GPU_GetPStates(handle, ref states) == NvStatus.OK) {
172 for (int i = 0; i < 3; i++)
173 if (states.PStates[i].Present) {
174 loads[i].Value = states.PStates[i].Percentage;
175 ActivateSensor(loads[i]);
178 NvUsages usages = new NvUsages();
179 usages.Version = NVAPI.GPU_USAGES_VER;
180 usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
181 if (NVAPI.NvAPI_GPU_GetUsages != null &&
182 NVAPI.NvAPI_GPU_GetUsages(handle, ref usages) == NvStatus.OK) {
183 loads[0].Value = usages.Usage[2];
184 loads[1].Value = usages.Usage[6];
185 loads[2].Value = usages.Usage[10];
186 for (int i = 0; i < 3; i++)
187 ActivateSensor(loads[i]);
192 NvGPUCoolerSettings coolerSettings = GetCoolerSettings();
193 if (coolerSettings.Count > 0) {
194 control.Value = coolerSettings.Cooler[0].CurrentLevel;
195 ActivateSensor(control);
198 NvMemoryInfo memoryInfo = new NvMemoryInfo();
199 memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
200 memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
201 if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue &&
202 NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value, ref memoryInfo) ==
204 uint totalMemory = memoryInfo.Values[0];
205 uint freeMemory = memoryInfo.Values[4];
206 float usedMemory = Math.Max(totalMemory - freeMemory, 0);
207 memoryLoad.Value = 100f * usedMemory / totalMemory;
208 ActivateSensor(memoryLoad);
212 public override string GetReport() {
213 StringBuilder r = new StringBuilder();
215 r.AppendLine("Nvidia GPU");
218 r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
219 r.AppendFormat("Index: {0}{1}", adapterIndex, Environment.NewLine);
221 if (displayHandle.HasValue && NVAPI.NvAPI_GetDisplayDriverVersion != null) {
222 NvDisplayDriverVersion driverVersion = new NvDisplayDriverVersion();
223 driverVersion.Version = NVAPI.DISPLAY_DRIVER_VERSION_VER;
224 if (NVAPI.NvAPI_GetDisplayDriverVersion(displayHandle.Value,
225 ref driverVersion) == NvStatus.OK) {
226 r.Append("Driver Version: ");
227 r.Append(driverVersion.DriverVersion / 100);
229 r.Append((driverVersion.DriverVersion % 100).ToString("00",
230 CultureInfo.InvariantCulture));
232 r.Append("Driver Branch: ");
233 r.AppendLine(driverVersion.BuildBranch);
238 if (NVAPI.NvAPI_GPU_GetPCIIdentifiers != null) {
239 uint deviceId, subSystemId, revisionId, extDeviceId;
241 NvStatus status = NVAPI.NvAPI_GPU_GetPCIIdentifiers(handle,
242 out deviceId, out subSystemId, out revisionId, out extDeviceId);
244 if (status == NvStatus.OK) {
245 r.Append("DeviceID: 0x");
246 r.AppendLine(deviceId.ToString("X", CultureInfo.InvariantCulture));
247 r.Append("SubSystemID: 0x");
248 r.AppendLine(subSystemId.ToString("X", CultureInfo.InvariantCulture));
249 r.Append("RevisionID: 0x");
250 r.AppendLine(revisionId.ToString("X", CultureInfo.InvariantCulture));
251 r.Append("ExtDeviceID: 0x");
252 r.AppendLine(extDeviceId.ToString("X", CultureInfo.InvariantCulture));
257 if (NVAPI.NvAPI_GPU_GetThermalSettings != null) {
258 NvGPUThermalSettings settings = new NvGPUThermalSettings();
259 settings.Version = NVAPI.GPU_THERMAL_SETTINGS_VER;
260 settings.Count = NVAPI.MAX_THERMAL_SENSORS_PER_GPU;
261 settings.Sensor = new NvSensor[NVAPI.MAX_THERMAL_SENSORS_PER_GPU];
263 NvStatus status = NVAPI.NvAPI_GPU_GetThermalSettings(handle,
264 (int)NvThermalTarget.ALL, ref settings);
266 r.AppendLine("Thermal Settings");
268 if (status == NvStatus.OK) {
269 for (int i = 0; i < settings.Count; i++) {
270 r.AppendFormat(" Sensor[{0}].Controller: {1}{2}", i,
271 settings.Sensor[i].Controller, Environment.NewLine);
272 r.AppendFormat(" Sensor[{0}].DefaultMinTemp: {1}{2}", i,
273 settings.Sensor[i].DefaultMinTemp, Environment.NewLine);
274 r.AppendFormat(" Sensor[{0}].DefaultMaxTemp: {1}{2}", i,
275 settings.Sensor[i].DefaultMaxTemp, Environment.NewLine);
276 r.AppendFormat(" Sensor[{0}].CurrentTemp: {1}{2}", i,
277 settings.Sensor[i].CurrentTemp, Environment.NewLine);
278 r.AppendFormat(" Sensor[{0}].Target: {1}{2}", i,
279 settings.Sensor[i].Target, Environment.NewLine);
282 r.Append(" Status: ");
283 r.AppendLine(status.ToString());
288 if (NVAPI.NvAPI_GPU_GetAllClocks != null) {
289 NvClocks allClocks = new NvClocks();
290 allClocks.Version = NVAPI.GPU_CLOCKS_VER;
291 allClocks.Clock = new uint[NVAPI.MAX_CLOCKS_PER_GPU];
292 NvStatus status = NVAPI.NvAPI_GPU_GetAllClocks(handle, ref allClocks);
294 r.AppendLine("Clocks");
296 if (status == NvStatus.OK) {
297 for (int i = 0; i < allClocks.Clock.Length; i++)
298 if (allClocks.Clock[i] > 0) {
299 r.AppendFormat(" Clock[{0}]: {1}{2}", i, allClocks.Clock[i],
300 Environment.NewLine);
303 r.Append(" Status: ");
304 r.AppendLine(status.ToString());
309 if (NVAPI.NvAPI_GPU_GetTachReading != null) {
311 NvStatus status = NVAPI.NvAPI_GPU_GetTachReading(handle, out tachValue);
313 r.AppendLine("Tachometer");
315 if (status == NvStatus.OK) {
316 r.AppendFormat(" Value: {0}{1}", tachValue, Environment.NewLine);
318 r.Append(" Status: ");
319 r.AppendLine(status.ToString());
324 if (NVAPI.NvAPI_GPU_GetPStates != null) {
325 NvPStates states = new NvPStates();
326 states.Version = NVAPI.GPU_PSTATES_VER;
327 states.PStates = new NvPState[NVAPI.MAX_PSTATES_PER_GPU];
328 NvStatus status = NVAPI.NvAPI_GPU_GetPStates(handle, ref states);
330 r.AppendLine("P-States");
332 if (status == NvStatus.OK) {
333 for (int i = 0; i < states.PStates.Length; i++)
334 if (states.PStates[i].Present)
335 r.AppendFormat(" Percentage[{0}]: {1}{2}", i,
336 states.PStates[i].Percentage, Environment.NewLine);
338 r.Append(" Status: ");
339 r.AppendLine(status.ToString());
344 if (NVAPI.NvAPI_GPU_GetUsages != null) {
345 NvUsages usages = new NvUsages();
346 usages.Version = NVAPI.GPU_USAGES_VER;
347 usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];
348 NvStatus status = NVAPI.NvAPI_GPU_GetUsages(handle, ref usages);
350 r.AppendLine("Usages");
352 if (status == NvStatus.OK) {
353 for (int i = 0; i < usages.Usage.Length; i++)
354 if (usages.Usage[i] > 0)
355 r.AppendFormat(" Usage[{0}]: {1}{2}", i,
356 usages.Usage[i], Environment.NewLine);
358 r.Append(" Status: ");
359 r.AppendLine(status.ToString());
364 if (NVAPI.NvAPI_GPU_GetCoolerSettings != null) {
365 NvGPUCoolerSettings settings = new NvGPUCoolerSettings();
366 settings.Version = NVAPI.GPU_COOLER_SETTINGS_VER;
367 settings.Cooler = new NvCooler[NVAPI.MAX_COOLER_PER_GPU];
369 NVAPI.NvAPI_GPU_GetCoolerSettings(handle, 0, ref settings);
371 r.AppendLine("Cooler Settings");
373 if (status == NvStatus.OK) {
374 for (int i = 0; i < settings.Count; i++) {
375 r.AppendFormat(" Cooler[{0}].Type: {1}{2}", i,
376 settings.Cooler[i].Type, Environment.NewLine);
377 r.AppendFormat(" Cooler[{0}].Controller: {1}{2}", i,
378 settings.Cooler[i].Controller, Environment.NewLine);
379 r.AppendFormat(" Cooler[{0}].DefaultMin: {1}{2}", i,
380 settings.Cooler[i].DefaultMin, Environment.NewLine);
381 r.AppendFormat(" Cooler[{0}].DefaultMax: {1}{2}", i,
382 settings.Cooler[i].DefaultMax, Environment.NewLine);
383 r.AppendFormat(" Cooler[{0}].CurrentMin: {1}{2}", i,
384 settings.Cooler[i].CurrentMin, Environment.NewLine);
385 r.AppendFormat(" Cooler[{0}].CurrentMax: {1}{2}", i,
386 settings.Cooler[i].CurrentMax, Environment.NewLine);
387 r.AppendFormat(" Cooler[{0}].CurrentLevel: {1}{2}", i,
388 settings.Cooler[i].CurrentLevel, Environment.NewLine);
389 r.AppendFormat(" Cooler[{0}].DefaultPolicy: {1}{2}", i,
390 settings.Cooler[i].DefaultPolicy, Environment.NewLine);
391 r.AppendFormat(" Cooler[{0}].CurrentPolicy: {1}{2}", i,
392 settings.Cooler[i].CurrentPolicy, Environment.NewLine);
393 r.AppendFormat(" Cooler[{0}].Target: {1}{2}", i,
394 settings.Cooler[i].Target, Environment.NewLine);
395 r.AppendFormat(" Cooler[{0}].ControlType: {1}{2}", i,
396 settings.Cooler[i].ControlType, Environment.NewLine);
397 r.AppendFormat(" Cooler[{0}].Active: {1}{2}", i,
398 settings.Cooler[i].Active, Environment.NewLine);
401 r.Append(" Status: ");
402 r.AppendLine(status.ToString());
407 if (NVAPI.NvAPI_GPU_GetMemoryInfo != null && displayHandle.HasValue) {
408 NvMemoryInfo memoryInfo = new NvMemoryInfo();
409 memoryInfo.Version = NVAPI.GPU_MEMORY_INFO_VER;
410 memoryInfo.Values = new uint[NVAPI.MAX_MEMORY_VALUES_PER_GPU];
411 NvStatus status = NVAPI.NvAPI_GPU_GetMemoryInfo(displayHandle.Value,
414 r.AppendLine("Memory Info");
416 if (status == NvStatus.OK) {
417 for (int i = 0; i < memoryInfo.Values.Length; i++)
418 r.AppendFormat(" Value[{0}]: {1}{2}", i,
419 memoryInfo.Values[i], Environment.NewLine);
421 r.Append(" Status: ");
422 r.AppendLine(status.ToString());
430 private void SoftwareControlValueChanged(IControl control) {
431 NvGPUCoolerLevels coolerLevels = new NvGPUCoolerLevels();
432 coolerLevels.Version = NVAPI.GPU_COOLER_LEVELS_VER;
433 coolerLevels.Levels = new NvLevel[NVAPI.MAX_COOLER_PER_GPU];
434 coolerLevels.Levels[0].Level = (int)control.SoftwareValue;
435 coolerLevels.Levels[0].Policy = 1;
436 NVAPI.NvAPI_GPU_SetCoolerLevels(handle, 0, ref coolerLevels);
439 private void ControlModeChanged(IControl control) {
440 switch (control.ControlMode) {
441 case ControlMode.Undefined:
443 case ControlMode.Default:
444 SetDefaultFanSpeed();
446 case ControlMode.Software:
447 SoftwareControlValueChanged(control);
454 private void SetDefaultFanSpeed() {
455 NvGPUCoolerLevels coolerLevels = new NvGPUCoolerLevels();
456 coolerLevels.Version = NVAPI.GPU_COOLER_LEVELS_VER;
457 coolerLevels.Levels = new NvLevel[NVAPI.MAX_COOLER_PER_GPU];
458 coolerLevels.Levels[0].Policy = 0x20;
459 NVAPI.NvAPI_GPU_SetCoolerLevels(handle, 0, ref coolerLevels);
462 public override void Close() {
463 if (this.fanControl != null) {
464 this.fanControl.ControlModeChanged -= ControlModeChanged;
465 this.fanControl.SoftwareControlValueChanged -=
466 SoftwareControlValueChanged;
468 if (this.fanControl.ControlMode != ControlMode.Undefined)
469 SetDefaultFanSpeed();