Hardware/Nvidia/NVAPI.cs
author sl
Sun, 03 Feb 2013 18:01:50 +0100
changeset 391 ca4c0e7ae75d
parent 334 013e148e8f12
permissions -rw-r--r--
Converted project to VisualStudio 2012.
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.
     1 /*
     2  
     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/.
     6  
     7   Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
     8 	Copyright (C) 2011 Christian Vallières
     9  
    10 */
    11 
    12 using System;
    13 using System.Runtime.InteropServices;
    14 using System.Text;
    15 
    16 namespace OpenHardwareMonitor.Hardware.Nvidia {
    17 
    18   internal enum NvStatus {
    19     OK = 0,
    20     ERROR = -1,
    21     LIBRARY_NOT_FOUND = -2,
    22     NO_IMPLEMENTATION = -3,
    23     API_NOT_INTIALIZED = -4,
    24     INVALID_ARGUMENT = -5,
    25     NVIDIA_DEVICE_NOT_FOUND = -6,
    26     END_ENUMERATION = -7,
    27     INVALID_HANDLE = -8,
    28     INCOMPATIBLE_STRUCT_VERSION = -9,
    29     HANDLE_INVALIDATED = -10,
    30     OPENGL_CONTEXT_NOT_CURRENT = -11,
    31     NO_GL_EXPERT = -12,
    32     INSTRUMENTATION_DISABLED = -13,
    33     EXPECTED_LOGICAL_GPU_HANDLE = -100,
    34     EXPECTED_PHYSICAL_GPU_HANDLE = -101,
    35     EXPECTED_DISPLAY_HANDLE = -102,
    36     INVALID_COMBINATION = -103,
    37     NOT_SUPPORTED = -104,
    38     PORTID_NOT_FOUND = -105,
    39     EXPECTED_UNATTACHED_DISPLAY_HANDLE = -106,
    40     INVALID_PERF_LEVEL = -107,
    41     DEVICE_BUSY = -108,
    42     NV_PERSIST_FILE_NOT_FOUND = -109,
    43     PERSIST_DATA_NOT_FOUND = -110,
    44     EXPECTED_TV_DISPLAY = -111,
    45     EXPECTED_TV_DISPLAY_ON_DCONNECTOR = -112,
    46     NO_ACTIVE_SLI_TOPOLOGY = -113,
    47     SLI_RENDERING_MODE_NOTALLOWED = -114,
    48     EXPECTED_DIGITAL_FLAT_PANEL = -115,
    49     ARGUMENT_EXCEED_MAX_SIZE = -116,
    50     DEVICE_SWITCHING_NOT_ALLOWED = -117,
    51     TESTING_CLOCKS_NOT_SUPPORTED = -118,
    52     UNKNOWN_UNDERSCAN_CONFIG = -119,
    53     TIMEOUT_RECONFIGURING_GPU_TOPO = -120,
    54     DATA_NOT_FOUND = -121,
    55     EXPECTED_ANALOG_DISPLAY = -122,
    56     NO_VIDLINK = -123,
    57     REQUIRES_REBOOT = -124,
    58     INVALID_HYBRID_MODE = -125,
    59     MIXED_TARGET_TYPES = -126,
    60     SYSWOW64_NOT_SUPPORTED = -127,
    61     IMPLICIT_SET_GPU_TOPOLOGY_CHANGE_NOT_ALLOWED = -128,
    62     REQUEST_USER_TO_CLOSE_NON_MIGRATABLE_APPS = -129,
    63     OUT_OF_MEMORY = -130,
    64     WAS_STILL_DRAWING = -131,
    65     FILE_NOT_FOUND = -132,
    66     TOO_MANY_UNIQUE_STATE_OBJECTS = -133,
    67     INVALID_CALL = -134,
    68     D3D10_1_LIBRARY_NOT_FOUND = -135,
    69     FUNCTION_NOT_FOUND = -136
    70   }
    71 
    72   internal enum NvThermalController {
    73     NONE = 0,
    74     GPU_INTERNAL,
    75     ADM1032,
    76     MAX6649,
    77     MAX1617,
    78     LM99,
    79     LM89,
    80     LM64,
    81     ADT7473,
    82     SBMAX6649,
    83     VBIOSEVT,
    84     OS,
    85     UNKNOWN = -1,
    86   }
    87 
    88   internal enum NvThermalTarget {
    89     NONE = 0,
    90     GPU = 1,
    91     MEMORY = 2,
    92     POWER_SUPPLY = 4,
    93     BOARD = 8,
    94     ALL = 15,
    95     UNKNOWN = -1
    96   };
    97 
    98   [StructLayout(LayoutKind.Sequential, Pack = 8)]
    99   internal struct NvSensor {
   100     public NvThermalController Controller;
   101     public uint DefaultMinTemp;
   102     public uint DefaultMaxTemp;
   103     public uint CurrentTemp;
   104     public NvThermalTarget Target;
   105   }
   106 
   107   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   108   internal struct NvGPUThermalSettings {
   109     public uint Version;
   110     public uint Count;
   111     [MarshalAs(UnmanagedType.ByValArray,
   112       SizeConst = NVAPI.MAX_THERMAL_SENSORS_PER_GPU)]
   113     public NvSensor[] Sensor;
   114   }
   115 
   116   [StructLayout(LayoutKind.Sequential)]
   117   internal struct NvDisplayHandle {
   118     private readonly IntPtr ptr;
   119   }
   120 
   121   [StructLayout(LayoutKind.Sequential)]
   122   internal struct NvPhysicalGpuHandle {
   123     private readonly IntPtr ptr;
   124   }
   125 
   126   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   127   internal struct NvClocks {
   128     public uint Version;
   129     [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_CLOCKS_PER_GPU)]
   130     public uint[] Clock;
   131   }
   132 
   133   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   134   internal struct NvPState {
   135     public bool Present;
   136     public int Percentage;
   137   }
   138 
   139   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   140   internal struct NvPStates {
   141     public uint Version;
   142     public uint Flags;
   143     [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_PSTATES_PER_GPU)]
   144     public NvPState[] PStates;
   145   }
   146 
   147   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   148   internal struct NvUsages {
   149     public uint Version;
   150     [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_USAGES_PER_GPU)]
   151     public uint[] Usage;
   152   }
   153 
   154   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   155   internal struct NvCooler {
   156     public int Type;
   157     public int Controller;
   158     public int DefaultMin;
   159     public int DefaultMax;
   160     public int CurrentMin;
   161     public int CurrentMax;
   162     public int CurrentLevel;
   163     public int DefaultPolicy;
   164     public int CurrentPolicy;
   165     public int Target;
   166     public int ControlType;
   167     public int Active;
   168   }
   169 
   170   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   171   internal struct NvGPUCoolerSettings {
   172     public uint Version;
   173     public uint Count;
   174     [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_COOLER_PER_GPU)]
   175     public NvCooler[] Cooler;
   176   }
   177 
   178   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   179   internal struct NvLevel {
   180     public int Level;
   181     public int Policy;
   182   }
   183 
   184   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   185   internal struct NvGPUCoolerLevels {
   186     public uint Version;
   187     [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_COOLER_PER_GPU)]
   188     public NvLevel[] Levels;
   189   }
   190 
   191   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   192   internal struct NvMemoryInfo {
   193     public uint Version;
   194     [MarshalAs(UnmanagedType.ByValArray, SizeConst =
   195       NVAPI.MAX_MEMORY_VALUES_PER_GPU)]
   196     public uint[] Values;
   197   }
   198 
   199   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   200   internal struct NvDisplayDriverVersion {
   201     public uint Version;
   202     public uint DriverVersion;
   203     public uint BldChangeListNum;
   204     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NVAPI.SHORT_STRING_MAX)]
   205     public string BuildBranch;
   206     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NVAPI.SHORT_STRING_MAX)]
   207     public string Adapter;
   208   }
   209 
   210   internal class NVAPI {
   211 
   212     public const int MAX_PHYSICAL_GPUS = 64;
   213     public const int SHORT_STRING_MAX = 64;
   214 
   215     public const int MAX_THERMAL_SENSORS_PER_GPU = 3;
   216     public const int MAX_CLOCKS_PER_GPU = 0x120;
   217     public const int MAX_PSTATES_PER_GPU = 8;
   218     public const int MAX_USAGES_PER_GPU = 33;
   219     public const int MAX_COOLER_PER_GPU = 20;
   220     public const int MAX_MEMORY_VALUES_PER_GPU = 5;
   221 
   222     public static readonly uint GPU_THERMAL_SETTINGS_VER = (uint)
   223       Marshal.SizeOf(typeof(NvGPUThermalSettings)) | 0x10000;
   224     public static readonly uint GPU_CLOCKS_VER = (uint)
   225       Marshal.SizeOf(typeof(NvClocks)) | 0x20000;
   226     public static readonly uint GPU_PSTATES_VER = (uint)
   227       Marshal.SizeOf(typeof(NvPStates)) | 0x10000;
   228     public static readonly uint GPU_USAGES_VER = (uint)
   229       Marshal.SizeOf(typeof(NvUsages)) | 0x10000;
   230     public static readonly uint GPU_COOLER_SETTINGS_VER = (uint)
   231       Marshal.SizeOf(typeof(NvGPUCoolerSettings)) | 0x20000;
   232     public static readonly uint GPU_MEMORY_INFO_VER = (uint)
   233       Marshal.SizeOf(typeof(NvMemoryInfo)) | 0x20000;
   234     public static readonly uint DISPLAY_DRIVER_VERSION_VER = (uint)
   235       Marshal.SizeOf(typeof(NvDisplayDriverVersion)) | 0x10000;
   236     public static readonly uint GPU_COOLER_LEVELS_VER = (uint)
   237       Marshal.SizeOf(typeof(NvGPUCoolerLevels)) | 0x10000;
   238 
   239     private delegate IntPtr nvapi_QueryInterfaceDelegate(uint id);
   240     private delegate NvStatus NvAPI_InitializeDelegate();
   241     private delegate NvStatus NvAPI_GPU_GetFullNameDelegate(
   242       NvPhysicalGpuHandle gpuHandle, StringBuilder name);
   243 
   244     public delegate NvStatus NvAPI_GPU_GetThermalSettingsDelegate(
   245       NvPhysicalGpuHandle gpuHandle, int sensorIndex,
   246       ref NvGPUThermalSettings nvGPUThermalSettings);
   247     public delegate NvStatus NvAPI_EnumNvidiaDisplayHandleDelegate(int thisEnum,
   248       ref NvDisplayHandle displayHandle);
   249     public delegate NvStatus NvAPI_GetPhysicalGPUsFromDisplayDelegate(
   250       NvDisplayHandle displayHandle, [Out] NvPhysicalGpuHandle[] gpuHandles,
   251       out uint gpuCount);
   252     public delegate NvStatus NvAPI_EnumPhysicalGPUsDelegate(
   253       [Out] NvPhysicalGpuHandle[] gpuHandles, out int gpuCount);
   254     public delegate NvStatus NvAPI_GPU_GetTachReadingDelegate(
   255       NvPhysicalGpuHandle gpuHandle, out int value);
   256     public delegate NvStatus NvAPI_GPU_GetAllClocksDelegate(
   257       NvPhysicalGpuHandle gpuHandle, ref NvClocks nvClocks);
   258     public delegate NvStatus NvAPI_GPU_GetPStatesDelegate(
   259       NvPhysicalGpuHandle gpuHandle, ref NvPStates nvPStates);
   260     public delegate NvStatus NvAPI_GPU_GetUsagesDelegate(
   261       NvPhysicalGpuHandle gpuHandle, ref NvUsages nvUsages);
   262     public delegate NvStatus NvAPI_GPU_GetCoolerSettingsDelegate(
   263       NvPhysicalGpuHandle gpuHandle, int coolerIndex,
   264       ref NvGPUCoolerSettings nvGPUCoolerSettings);
   265     public delegate NvStatus NvAPI_GPU_SetCoolerLevelsDelegate(
   266       NvPhysicalGpuHandle gpuHandle, int coolerIndex,
   267       ref NvGPUCoolerLevels NvGPUCoolerLevels);
   268     public delegate NvStatus NvAPI_GPU_GetMemoryInfoDelegate(
   269       NvDisplayHandle displayHandle, ref NvMemoryInfo nvMemoryInfo);
   270     public delegate NvStatus NvAPI_GetDisplayDriverVersionDelegate(
   271       NvDisplayHandle displayHandle, [In, Out] ref NvDisplayDriverVersion
   272       nvDisplayDriverVersion);
   273     public delegate NvStatus NvAPI_GetInterfaceVersionStringDelegate(
   274       StringBuilder version);
   275     public delegate NvStatus NvAPI_GPU_GetPCIIdentifiersDelegate(
   276       NvPhysicalGpuHandle gpuHandle, out uint deviceId, out uint subSystemId, 
   277       out uint revisionId, out uint extDeviceId);
   278 
   279     private static readonly bool available;
   280     private static readonly nvapi_QueryInterfaceDelegate nvapi_QueryInterface;
   281     private static readonly NvAPI_InitializeDelegate NvAPI_Initialize;
   282     private static readonly NvAPI_GPU_GetFullNameDelegate
   283       _NvAPI_GPU_GetFullName;
   284     private static readonly NvAPI_GetInterfaceVersionStringDelegate
   285       _NvAPI_GetInterfaceVersionString;
   286 
   287     public static readonly NvAPI_GPU_GetThermalSettingsDelegate
   288       NvAPI_GPU_GetThermalSettings;
   289     public static readonly NvAPI_EnumNvidiaDisplayHandleDelegate
   290       NvAPI_EnumNvidiaDisplayHandle;
   291     public static readonly NvAPI_GetPhysicalGPUsFromDisplayDelegate
   292       NvAPI_GetPhysicalGPUsFromDisplay;
   293     public static readonly NvAPI_EnumPhysicalGPUsDelegate
   294       NvAPI_EnumPhysicalGPUs;
   295     public static readonly NvAPI_GPU_GetTachReadingDelegate
   296       NvAPI_GPU_GetTachReading;
   297     public static readonly NvAPI_GPU_GetAllClocksDelegate
   298       NvAPI_GPU_GetAllClocks;
   299     public static readonly NvAPI_GPU_GetPStatesDelegate
   300       NvAPI_GPU_GetPStates;
   301     public static readonly NvAPI_GPU_GetUsagesDelegate
   302       NvAPI_GPU_GetUsages;
   303     public static readonly NvAPI_GPU_GetCoolerSettingsDelegate
   304       NvAPI_GPU_GetCoolerSettings;
   305     public static readonly NvAPI_GPU_SetCoolerLevelsDelegate
   306       NvAPI_GPU_SetCoolerLevels;
   307     public static readonly NvAPI_GPU_GetMemoryInfoDelegate
   308       NvAPI_GPU_GetMemoryInfo;
   309     public static readonly NvAPI_GetDisplayDriverVersionDelegate
   310       NvAPI_GetDisplayDriverVersion;
   311     public static readonly NvAPI_GPU_GetPCIIdentifiersDelegate
   312       NvAPI_GPU_GetPCIIdentifiers;
   313 
   314     private NVAPI() { }
   315 
   316     public static NvStatus NvAPI_GPU_GetFullName(NvPhysicalGpuHandle gpuHandle,
   317       out string name) {
   318       StringBuilder builder = new StringBuilder(SHORT_STRING_MAX);
   319       NvStatus status;
   320       if (_NvAPI_GPU_GetFullName != null)
   321         status = _NvAPI_GPU_GetFullName(gpuHandle, builder);
   322       else
   323         status = NvStatus.FUNCTION_NOT_FOUND;
   324       name = builder.ToString();
   325       return status;
   326     }
   327 
   328     public static NvStatus NvAPI_GetInterfaceVersionString(out string version) {
   329       StringBuilder builder = new StringBuilder(SHORT_STRING_MAX);
   330       NvStatus status;
   331       if (_NvAPI_GetInterfaceVersionString != null)
   332         status = _NvAPI_GetInterfaceVersionString(builder);
   333       else
   334         status = NvStatus.FUNCTION_NOT_FOUND;
   335       version = builder.ToString();
   336       return status;
   337     }
   338 
   339     private static string GetDllName() {
   340       if (IntPtr.Size == 4) {
   341         return "nvapi.dll";
   342       } else {
   343         return "nvapi64.dll";
   344       }
   345     }
   346 
   347     private static void GetDelegate<T>(uint id, out T newDelegate)
   348       where T : class {
   349       IntPtr ptr = nvapi_QueryInterface(id);
   350       if (ptr != IntPtr.Zero) {
   351         newDelegate =
   352           Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T;
   353       } else {
   354         newDelegate = null;
   355       }
   356     }
   357 
   358     static NVAPI() {
   359       DllImportAttribute attribute = new DllImportAttribute(GetDllName());
   360       attribute.CallingConvention = CallingConvention.Cdecl;
   361       attribute.PreserveSig = true;
   362       attribute.EntryPoint = "nvapi_QueryInterface";
   363       PInvokeDelegateFactory.CreateDelegate(attribute,
   364         out nvapi_QueryInterface);
   365 
   366       try {
   367         GetDelegate(0x0150E828, out NvAPI_Initialize);
   368       } catch (DllNotFoundException) { return; } 
   369         catch (EntryPointNotFoundException) { return; } 
   370         catch (ArgumentNullException) { return; }
   371 
   372       if (NvAPI_Initialize() == NvStatus.OK) {
   373         GetDelegate(0xE3640A56, out NvAPI_GPU_GetThermalSettings);
   374         GetDelegate(0xCEEE8E9F, out _NvAPI_GPU_GetFullName);
   375         GetDelegate(0x9ABDD40D, out NvAPI_EnumNvidiaDisplayHandle);
   376         GetDelegate(0x34EF9506, out NvAPI_GetPhysicalGPUsFromDisplay);
   377         GetDelegate(0xE5AC921F, out NvAPI_EnumPhysicalGPUs);
   378         GetDelegate(0x5F608315, out NvAPI_GPU_GetTachReading);
   379         GetDelegate(0x1BD69F49, out NvAPI_GPU_GetAllClocks);
   380         GetDelegate(0x60DED2ED, out NvAPI_GPU_GetPStates);
   381         GetDelegate(0x189A1FDF, out NvAPI_GPU_GetUsages);
   382         GetDelegate(0xDA141340, out NvAPI_GPU_GetCoolerSettings);
   383         GetDelegate(0x891FA0AE, out NvAPI_GPU_SetCoolerLevels);
   384         GetDelegate(0x774AA982, out NvAPI_GPU_GetMemoryInfo);
   385         GetDelegate(0xF951A4D1, out NvAPI_GetDisplayDriverVersion);
   386         GetDelegate(0x01053FA5, out _NvAPI_GetInterfaceVersionString);
   387         GetDelegate(0x2DDFB66E, out NvAPI_GPU_GetPCIIdentifiers);
   388 
   389         available = true;
   390       }
   391     }
   392 
   393     public static bool IsAvailable {
   394       get { return available; }
   395     }
   396 
   397   }
   398 }