Hardware/Nvidia/NVAPI.cs
author moel.mich
Sun, 08 Aug 2010 13:57:26 +0000
changeset 165 813d8bc3192f
parent 140 04a5155c9c1a
child 167 b7cc9d09aefe
permissions -rw-r--r--
Refactored the hardware monitoring code into a library (Issue 101).
     1 /*
     2   
     3   Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4 
     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
     8  
     9   http://www.mozilla.org/MPL/
    10 
    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.
    14 
    15   The Original Code is the Open Hardware Monitor code.
    16 
    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.
    21 
    22   Contributor(s):
    23 
    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.
    35  
    36 */
    37 
    38 using System;
    39 using System.Collections.Generic;
    40 using System.Runtime.InteropServices;
    41 using System.Text;
    42 
    43 namespace OpenHardwareMonitor.Hardware.Nvidia {
    44 
    45   internal enum NvStatus {
    46     OK = 0,
    47     ERROR = -1,
    48     LIBRARY_NOT_FOUND = -2,
    49     NO_IMPLEMENTATION = -3,
    50     API_NOT_INTIALIZED = -4,
    51     INVALID_ARGUMENT = -5,
    52     NVIDIA_DEVICE_NOT_FOUND = -6,
    53     END_ENUMERATION = -7,
    54     INVALID_HANDLE = -8,
    55     INCOMPATIBLE_STRUCT_VERSION = -9,
    56     HANDLE_INVALIDATED = -10,
    57     OPENGL_CONTEXT_NOT_CURRENT = -11,
    58     NO_GL_EXPERT = -12,
    59     INSTRUMENTATION_DISABLED = -13,
    60     EXPECTED_LOGICAL_GPU_HANDLE = -100,
    61     EXPECTED_PHYSICAL_GPU_HANDLE = -101,
    62     EXPECTED_DISPLAY_HANDLE = -102,
    63     INVALID_COMBINATION = -103,
    64     NOT_SUPPORTED = -104,
    65     PORTID_NOT_FOUND = -105,
    66     EXPECTED_UNATTACHED_DISPLAY_HANDLE = -106,
    67     INVALID_PERF_LEVEL = -107,
    68     DEVICE_BUSY = -108,
    69     NV_PERSIST_FILE_NOT_FOUND = -109,
    70     PERSIST_DATA_NOT_FOUND = -110,
    71     EXPECTED_TV_DISPLAY = -111,
    72     EXPECTED_TV_DISPLAY_ON_DCONNECTOR = -112,
    73     NO_ACTIVE_SLI_TOPOLOGY = -113,
    74     SLI_RENDERING_MODE_NOTALLOWED = -114,
    75     EXPECTED_DIGITAL_FLAT_PANEL = -115,
    76     ARGUMENT_EXCEED_MAX_SIZE = -116,
    77     DEVICE_SWITCHING_NOT_ALLOWED = -117,
    78     TESTING_CLOCKS_NOT_SUPPORTED = -118,
    79     UNKNOWN_UNDERSCAN_CONFIG = -119,
    80     TIMEOUT_RECONFIGURING_GPU_TOPO = -120,
    81     DATA_NOT_FOUND = -121,
    82     EXPECTED_ANALOG_DISPLAY = -122,
    83     NO_VIDLINK = -123,
    84     REQUIRES_REBOOT = -124,
    85     INVALID_HYBRID_MODE = -125,
    86     MIXED_TARGET_TYPES = -126,
    87     SYSWOW64_NOT_SUPPORTED = -127,
    88     IMPLICIT_SET_GPU_TOPOLOGY_CHANGE_NOT_ALLOWED = -128,
    89     REQUEST_USER_TO_CLOSE_NON_MIGRATABLE_APPS = -129,
    90     OUT_OF_MEMORY = -130,
    91     WAS_STILL_DRAWING = -131,
    92     FILE_NOT_FOUND = -132,
    93     TOO_MANY_UNIQUE_STATE_OBJECTS = -133,
    94     INVALID_CALL = -134,
    95     D3D10_1_LIBRARY_NOT_FOUND = -135,
    96     FUNCTION_NOT_FOUND = -136
    97   }
    98 
    99   internal enum NvThermalController {
   100     NONE = 0,
   101     GPU_INTERNAL,  
   102     ADM1032,
   103     MAX6649,       
   104     MAX1617,      
   105     LM99,      
   106     LM89,         
   107     LM64,         
   108     ADT7473,
   109     SBMAX6649,
   110     VBIOSEVT,  
   111     OS,    
   112     UNKNOWN = -1,
   113   }
   114 
   115   internal enum NvThermalTarget {
   116     NONE = 0,
   117     GPU = 1,
   118     MEMORY = 2,
   119     POWER_SUPPLY = 4,
   120     BOARD = 8,
   121     ALL = 15,
   122     UNKNOWN = -1
   123   };
   124 
   125   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   126   internal struct NvSensor {
   127     public NvThermalController Controller;
   128     public uint DefaultMinTemp;
   129     public uint DefaultMaxTemp;
   130     public uint CurrentTemp;
   131     public NvThermalTarget Target;     
   132   }
   133 
   134   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   135   internal struct NvGPUThermalSettings {
   136     public uint Version;
   137     public uint Count;
   138     [MarshalAs(UnmanagedType.ByValArray, 
   139       SizeConst = NVAPI.MAX_THERMAL_SENSORS_PER_GPU)]
   140     public NvSensor[] Sensor;
   141   }
   142 
   143   [StructLayout(LayoutKind.Sequential)]
   144   internal struct NvDisplayHandle {
   145     private IntPtr ptr;
   146   }
   147 
   148   [StructLayout(LayoutKind.Sequential)]
   149   internal struct NvPhysicalGpuHandle {
   150     private IntPtr ptr;
   151   }
   152 
   153   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   154   internal struct NvClocks {
   155     public uint Version;
   156     [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_CLOCKS_PER_GPU)]
   157     public uint[] Clock;
   158   }
   159 
   160   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   161   internal struct NvPState {
   162     public bool Present;
   163     public int Percentage;
   164   }
   165 
   166   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   167   internal struct NvPStates {
   168     public uint Version;
   169     public uint Flags;
   170     [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_PSTATES_PER_GPU)]
   171     public NvPState[] PStates;
   172   }
   173 
   174   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   175   internal struct NvUsages {
   176     public uint Version;
   177     [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_USAGES_PER_GPU)]
   178     public uint[] Usage;
   179   }
   180 
   181   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   182   internal struct NvCooler {
   183     public int Type;
   184     public int Controller;
   185     public int DefaultMin;
   186     public int DefaultMax;
   187     public int CurrentMin;
   188     public int CurrentMax;
   189     public int CurrentLevel;
   190     public int DefaultPolicy;
   191     public int CurrentPolicy;
   192     public int Target;
   193     public int ControlType;
   194     public int Active;
   195   }
   196 
   197   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   198   internal struct NvGPUCoolerSettings {
   199     public uint Version;
   200     public uint Count;
   201     [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_COOLER_PER_GPU)]
   202     public NvCooler[] Cooler;
   203   }
   204 
   205   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   206   internal struct NvMemoryInfo {
   207     public uint Version;
   208     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 
   209       NVAPI.MAX_MEMORY_VALUES_PER_GPU)]
   210     public uint[] Values;
   211   }
   212 
   213   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   214   internal struct NvDisplayDriverVersion {
   215     public uint Version;
   216     public uint DriverVersion;
   217     public uint BldChangeListNum;
   218     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NVAPI.SHORT_STRING_MAX)]
   219     public string BuildBranch;
   220     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NVAPI.SHORT_STRING_MAX)]
   221     public string Adapter;
   222   }
   223 
   224   internal class NVAPI {
   225 
   226     public const int MAX_PHYSICAL_GPUS = 64;
   227     public const int SHORT_STRING_MAX = 64;
   228 
   229     public const int MAX_THERMAL_SENSORS_PER_GPU = 3;    
   230     public const int MAX_CLOCKS_PER_GPU = 0x120;
   231     public const int MAX_PSTATES_PER_GPU = 8;
   232     public const int MAX_USAGES_PER_GPU = 33;
   233     public const int MAX_COOLER_PER_GPU = 20;
   234     public const int MAX_MEMORY_VALUES_PER_GPU = 5;
   235 
   236     public static readonly uint GPU_THERMAL_SETTINGS_VER = (uint)
   237       Marshal.SizeOf(typeof(NvGPUThermalSettings)) | 0x10000;
   238     public static readonly uint GPU_CLOCKS_VER = (uint)
   239       Marshal.SizeOf(typeof(NvClocks)) | 0x20000;
   240     public static readonly uint GPU_PSTATES_VER = (uint)
   241       Marshal.SizeOf(typeof(NvPStates)) | 0x10000;
   242     public static readonly uint GPU_USAGES_VER = (uint)
   243       Marshal.SizeOf(typeof(NvUsages)) | 0x10000;
   244     public static readonly uint GPU_COOLER_SETTINGS_VER = (uint)
   245       Marshal.SizeOf(typeof(NvGPUCoolerSettings)) | 0x20000;
   246     public static readonly uint GPU_MEMORY_INFO_VER = (uint) 
   247       Marshal.SizeOf(typeof(NvMemoryInfo)) | 0x20000;
   248     public static readonly uint DISPLAY_DRIVER_VERSION_VER = (uint)
   249       Marshal.SizeOf(typeof(NvDisplayDriverVersion)) | 0x10000;
   250       
   251     private delegate IntPtr nvapi_QueryInterfaceDelegate(uint id);
   252     private delegate NvStatus NvAPI_InitializeDelegate();
   253     private delegate NvStatus NvAPI_GPU_GetFullNameDelegate(
   254       NvPhysicalGpuHandle gpuHandle, StringBuilder name);
   255 
   256     public delegate NvStatus NvAPI_GPU_GetThermalSettingsDelegate(
   257       NvPhysicalGpuHandle gpuHandle, int sensorIndex, 
   258       ref NvGPUThermalSettings nvGPUThermalSettings);
   259     public delegate NvStatus NvAPI_EnumNvidiaDisplayHandleDelegate(int thisEnum,
   260       ref NvDisplayHandle displayHandle);
   261     public delegate NvStatus NvAPI_GetPhysicalGPUsFromDisplayDelegate(
   262       NvDisplayHandle displayHandle, [Out] NvPhysicalGpuHandle[] gpuHandles, 
   263       out uint gpuCount);
   264     public delegate NvStatus NvAPI_EnumPhysicalGPUsDelegate(
   265       [Out] NvPhysicalGpuHandle[] gpuHandles, out int gpuCount);
   266     public delegate NvStatus NvAPI_GPU_GetTachReadingDelegate(
   267       NvPhysicalGpuHandle gpuHandle, out int value);
   268     public delegate NvStatus NvAPI_GPU_GetAllClocksDelegate(
   269       NvPhysicalGpuHandle gpuHandle, ref NvClocks nvClocks);
   270     public delegate NvStatus NvAPI_GPU_GetPStatesDelegate(
   271       NvPhysicalGpuHandle gpuHandle, ref NvPStates nvPStates);
   272     public delegate NvStatus NvAPI_GPU_GetUsagesDelegate(
   273       NvPhysicalGpuHandle gpuHandle, ref NvUsages nvUsages);
   274     public delegate NvStatus NvAPI_GPU_GetCoolerSettingsDelegate(
   275       NvPhysicalGpuHandle gpuHandle, int coolerIndex,
   276       ref NvGPUCoolerSettings nvGPUCoolerSettings);
   277     public delegate NvStatus NvAPI_GPU_GetMemoryInfoDelegate(
   278       NvDisplayHandle displayHandle, ref NvMemoryInfo nvMemoryInfo);
   279     public delegate NvStatus NvAPI_GetDisplayDriverVersionDelegate(
   280       NvDisplayHandle displayHandle, [In, Out] ref NvDisplayDriverVersion
   281       nvDisplayDriverVersion);
   282     public delegate NvStatus NvAPI_GetInterfaceVersionStringDelegate(
   283       StringBuilder version);
   284 
   285     private static bool available = false;
   286     private static nvapi_QueryInterfaceDelegate nvapi_QueryInterface;
   287     private static NvAPI_InitializeDelegate NvAPI_Initialize;
   288     private static NvAPI_GPU_GetFullNameDelegate _NvAPI_GPU_GetFullName;
   289     private static NvAPI_GetInterfaceVersionStringDelegate
   290       _NvAPI_GetInterfaceVersionString;
   291 
   292     public static readonly NvAPI_GPU_GetThermalSettingsDelegate 
   293       NvAPI_GPU_GetThermalSettings;
   294     public static readonly NvAPI_EnumNvidiaDisplayHandleDelegate
   295       NvAPI_EnumNvidiaDisplayHandle;
   296     public static readonly NvAPI_GetPhysicalGPUsFromDisplayDelegate
   297       NvAPI_GetPhysicalGPUsFromDisplay;
   298     public static readonly NvAPI_EnumPhysicalGPUsDelegate
   299       NvAPI_EnumPhysicalGPUs;
   300     public static readonly NvAPI_GPU_GetTachReadingDelegate
   301       NvAPI_GPU_GetTachReading;
   302     public static readonly NvAPI_GPU_GetAllClocksDelegate
   303       NvAPI_GPU_GetAllClocks;
   304     public static readonly NvAPI_GPU_GetPStatesDelegate
   305       NvAPI_GPU_GetPStates;
   306     public static readonly NvAPI_GPU_GetUsagesDelegate
   307       NvAPI_GPU_GetUsages;
   308     public static readonly NvAPI_GPU_GetCoolerSettingsDelegate
   309       NvAPI_GPU_GetCoolerSettings;
   310     public static readonly NvAPI_GPU_GetMemoryInfoDelegate
   311       NvAPI_GPU_GetMemoryInfo;
   312     public static readonly NvAPI_GetDisplayDriverVersionDelegate
   313       NvAPI_GetDisplayDriverVersion;    
   314 
   315     public static NvStatus NvAPI_GPU_GetFullName(NvPhysicalGpuHandle gpuHandle,
   316       out string name) {
   317       StringBuilder builder = new StringBuilder(SHORT_STRING_MAX);
   318       NvStatus status;
   319       if (_NvAPI_GPU_GetFullName != null)
   320         status = _NvAPI_GPU_GetFullName(gpuHandle, builder);
   321       else
   322         status = NvStatus.FUNCTION_NOT_FOUND;
   323       name = builder.ToString();
   324       return status;
   325     }
   326 
   327     public static NvStatus NvAPI_GetInterfaceVersionString(out string version) {
   328       StringBuilder builder = new StringBuilder(SHORT_STRING_MAX);
   329       NvStatus status;
   330       if (_NvAPI_GetInterfaceVersionString != null)
   331         status = _NvAPI_GetInterfaceVersionString(builder);
   332       else
   333         status = NvStatus.FUNCTION_NOT_FOUND;
   334       version = builder.ToString();
   335       return status;
   336     }
   337 
   338     private static string GetDllName() {
   339       if (IntPtr.Size == 4) {
   340         return "nvapi.dll";
   341       } else {
   342         return "nvapi64.dll";
   343       }
   344     }
   345 
   346     private static void GetDelegate<T>(uint id, out T newDelegate) 
   347       where T : class 
   348     {
   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(0x774AA982, out NvAPI_GPU_GetMemoryInfo);
   384         GetDelegate(0xF951A4D1, out NvAPI_GetDisplayDriverVersion);
   385         GetDelegate(0x01053FA5, out _NvAPI_GetInterfaceVersionString);
   386 
   387         available = true;
   388       }
   389     }
   390 
   391     public static bool IsAvailable {
   392       get { return available; }
   393     }
   394 
   395   }
   396 }