Entwickler-Ecke

Dateizugriff - NvApi vervollständigen


LittleBen - Mo 31.12.12 12:24
Titel: NvApi vervollständigen
Hallo,
seit Weihnachten bin ich der glückliche Besitzer einer GTX 680er Grafikkarte von Nvidia. Nun arbeite ich daran, mir ein kleines Programm zu schreiben, dass die wichtigsten Daten erfasst und auf einem selbst gebauten Display ausgibt. Nach Recherchen habe ich herausgefunden, dass man dafür die von Nvidia mitgeliefert NvApi.dll benötigt. Auf der Embarcadero-Seite habe ich dann die Header von den Funktionen dieser Dll in Delphi gefunden ->
http://cc.embarcadero.com/Download.aspx?id=26524
Doch leider musste ich feststellen, dass die Sammlung nicht vollständig ist...Direkt von Nvidia bekommt man die Header in C. Habe mir dann die Datei heruntergeladen (http://developer.download.nvidia.com/devzone/devcenter/tools/files/NVAPI-R304-developer.zip) und verglichen. Z.B. brauche ich noch die Funktion zum Auslesen der Lüfterrotation.

Quelltext
1:
NVAPI_INTERFACE NvAPI_GPU_GetTachReading(NvPhysicalGpuHandle hPhysicalGPU, NvU32 *pValue);                    

So sieht der Header dafür in C aus. Soweit kein Problem, muss halt noch in Delphi übersetzt werden.
Wo mein Problem liegt:
In der NvApi.pas hat der Autor zum Schluss alle Funktionen in ein Record gespeichert, mit ID.
Aber woher hat er die ID!? Hier mal der Code-Ausschnitt:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
type
  PNvAPIFuncRec = ^TNvAPIFuncRec;
  TNvAPIFuncRec = record
    ID: Cardinal;
    Func: Pointer;
  end;

const
  NvAPIFunctions: array[0..63of TNvAPIFuncRec = (
    (ID: $6C2D048C; Func: @@NvAPI_GetErrorMessage),
    (ID: $01053FA5; Func: @@NvAPI_GetInterfaceVersionString),
    (ID: $F951A4D1; Func: @@NvAPI_GetDisplayDriverVersion),
    (ID: $9ABDD40D; Func: @@NvAPI_EnumNvidiaDisplayHandle),
    (ID: $20DE9260; Func: @@NvAPI_EnumNvidiaUnAttachedDisplayHandle),
    (ID: $E5AC921F; Func: @@NvAPI_EnumPhysicalGPUs),
    (ID: $48B3EA59; Func: @@NvAPI_EnumLogicalGPUs),
    (ID: $34EF9506; Func: @@NvAPI_GetPhysicalGPUsFromDisplay),
    (ID: $5018ED61; Func: @@NvAPI_GetPhysicalGPUFromUnAttachedDisplay),
    (ID: $63F9799E; Func: @@NvAPI_CreateDisplayFromUnAttachedDisplay),
    (ID: $EE1370CF; Func: @@NvAPI_GetLogicalGPUFromDisplay),
    (ID: $ADD604D1; Func: @@NvAPI_GetLogicalGPUFromPhysicalGPU),
    (ID: $AEA3FA32; Func: @@NvAPI_GetPhysicalGPUsFromLogicalGPU),
    (ID: $35C29134; Func: @@NvAPI_GetAssociatedNvidiaDisplayHandle),
    (ID: $22A78B05; Func: @@NvAPI_GetAssociatedNvidiaDisplayName),
    (ID: $4888D790; Func: @@NvAPI_GetUnAttachedAssociatedDisplayName),
    (ID: $2863148D; Func: @@NvAPI_EnableHWCursor),
    (ID: $AB163097; Func: @@NvAPI_DisableHWCursor),
    (ID: $67B5DB55; Func: @@NvAPI_GetVBlankCounter),
    (ID: $3092AC32; Func: @@NvAPI_SetRefreshRateOverride),
    (ID: $D995937E; Func: @@NvAPI_GetAssociatedDisplayOutputId),
    (ID: $C64FF367; Func: @@NvAPI_GetDisplayPortInfo),
    (ID: $FA13E65A; Func: @@NvAPI_SetDisplayPort),
    (ID: $6AE16EC3; Func: @@NvAPI_GetHDMISupportInfo),
    (ID: $7D554F8E; Func: @@NvAPI_GPU_GetAllOutputs),
    (ID: $1730BFC9; Func: @@NvAPI_GPU_GetConnectedOutputs),
    (ID: $0680DE09; Func: @@NvAPI_GPU_GetConnectedSLIOutputs),
    (ID: $CF8CAF39; Func: @@NvAPI_GPU_GetConnectedOutputsWithLidState),
    (ID: $96043CC7; Func: @@NvAPI_GPU_GetConnectedSLIOutputsWithLidState),
    (ID: $BAAABFCC; Func: @@NvAPI_GPU_GetSystemType),
    (ID: $E3E89B6F; Func: @@NvAPI_GPU_GetActiveOutputs),
    (ID: $37D32E69; Func: @@NvAPI_GPU_GetEDID),
    (ID: $40A505E4; Func: @@NvAPI_GPU_GetOutputType),
    (ID: $34C9C2D4; Func: @@NvAPI_GPU_ValidateOutputCombination),
    (ID: $CEEE8E9F; Func: @@NvAPI_GPU_GetFullName),
    (ID: $2DDFB66E; Func: @@NvAPI_GPU_GetPCIIdentifiers),
    (ID: $C33BAEB1; Func: @@NvAPI_GPU_GetGPUType),
    (ID: $1BB18724; Func: @@NvAPI_GPU_GetBusType),
    (ID: $1BE0B8E5; Func: @@NvAPI_GPU_GetBusId),
    (ID: $2A0A350F; Func: @@NvAPI_GPU_GetBusSlotId),
    (ID: $E4715417; Func: @@NvAPI_GPU_GetIRQ),
    (ID: $ACC3DA0A; Func: @@NvAPI_GPU_GetVbiosRevision),
    (ID: $2D43FB31; Func: @@NvAPI_GPU_GetVbiosOEMRevision),
    (ID: $A561FD7D; Func: @@NvAPI_GPU_GetVbiosVersionString),
    (ID: $6E042794; Func: @@NvAPI_GPU_GetAGPAperture),
    (ID: $C74925A0; Func: @@NvAPI_GPU_GetCurrentAGPRate),
    (ID: $D048C3B1; Func: @@NvAPI_GPU_GetCurrentPCIEDownstreamWidth),
    (ID: $46FBEB03; Func: @@NvAPI_GPU_GetPhysicalFrameBufferSize),
    (ID: $5A04B644; Func: @@NvAPI_GPU_GetVirtualFrameBufferSize),
    (ID: $E3640A56; Func: @@NvAPI_GPU_GetThermalSettings),
    (ID: $2FDE12C5; Func: @@NvAPI_I2CRead),
    (ID: $E812EB07; Func: @@NvAPI_I2CWrite),
    (ID: $53DABBCA; Func: @@_NvAPI_SYS_GetChipSetInfo),
    (ID: $CDA14D8A; Func: @@NvAPI_SYS_GetLidAndDockInfo),
    (ID: $3805EF7A; Func: @@NvAPI_OGL_ExpertModeSet),
    (ID: $22ED9516; Func: @@NvAPI_OGL_ExpertModeGet),
    (ID: $B47A657E; Func: @@NvAPI_OGL_ExpertModeDefaultsSet),
    (ID: $AE921F12; Func: @@NvAPI_OGL_ExpertModeDefaultsGet),
    (ID: $0957D7B6; Func: @@NvAPI_SetView),
    (ID: $D6B99D89; Func: @@NvAPI_GetView),
    (ID: $06B89E68; Func: @@NvAPI_SetViewEx),
    (ID: $DBBC0AF4; Func: @@NvAPI_GetViewEx),
    (ID: $66FB7FC0; Func: @@NvAPI_GetSupportedViews),

    (ID: 0; Func: nil// stop signal
  );

function NotImplemented: NvAPI_Status; cdecl;
begin
  Result := NVAPI_NO_IMPLEMENTATION;
end;

function NvAPI_Initialize;
const
  NvAPILib = 'nvapi.dll';
  NvAPI_ID_INIT = $0150E828;
var
  Lib: THandle;
  nvapi_QueryInterface: function(ID: LongWord): Pointer; cdecl;
  InitFunc: function: Integer; stdcall;
  P: Pointer;
  Rec: PNvAPIFuncRec;
begin
  if Initialized then
  begin
    Result := NVAPI_OK;
    Exit;
  end;

  Lib := LoadLibrary(NvAPILib);
  if Lib <> 0 then
  begin
    nvapi_QueryInterface := GetProcAddress(Lib, 'nvapi_QueryInterface');
    Result := NVAPI_ERROR;
    if Assigned(nvapi_QueryInterface) then
    begin
      InitFunc := nvapi_QueryInterface(NvAPI_ID_INIT);
      if Assigned(InitFunc) then
      begin
        if InitFunc() >= 0 then
        begin
          { Initialize all function pointers }
          Rec := @NvAPIFunctions;
          while Rec.ID <> 0 do
          begin
            PPointer(Rec.Func)^ := @NotImplemented;
            P := nvapi_QueryInterface(Rec.ID);
            if P <> nil then
              PPointer(Rec.Func)^ := P;
            Inc(Rec);
          end;
          Result := NVAPI_OK;
        end;
      end;
    end;
  end
  else
    Result := NVAPI_LIBRARY_NOT_FOUND;

  Initialized := Result = NVAPI_OK;
end;

end.

Ich habe keine Ahnung, woher die ID kommt....
Kann mir da jemand helfen?

Viele Grüße und einen guten Rutsch ins neue Jahr!
Littleben


Gerd Kayser - Mo 31.12.12 12:53

Vielleicht hilft Dir das hier weiter: http://www.forum-3dcenter.org/vbulletin/archive/index.php/t-517614.html


LittleBen - Mo 31.12.12 16:36

Vielen Dank für den Tipp. Die seite hat mir zwar nicht direkt weiter geholfen, habe dann aber nochmal noch ein den IDs recherchiert. Dabei bin ich auf folgende Seite gekommen: http://code.google.com/p/open-hardware-monitor/source/browse/trunk/Hardware/Nvidia/NVAPI.cs?r=382. Dort finden sich so die wichtigsten Funktion, die noch nicht in der NvApi.pas vorhanden sind. Doch auch hier gibt es für mich ein Problem, denn der Code ist in C# geschrieben und habe davon keine Ahnung...genauer gesagt betrifft es nur die Records, die ich in Delphi umschreiben muss.
Wenn ich die Funktion NvApi_GPU_GetUsages benutzen will, benötige ich ein Record. Dieses sieht in C# so aus:

C#-Quelltext
1:
2:
3:
4:
5:
6:
[StructLayout(LayoutKind.Sequential, Pack = 8)]
  internal struct NvUsages {
    public uint Version;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_USAGES_PER_GPU)]
    public uint[] Usage;
  }

Habe es dann einfach mal probiert in Delphi umzuschreiben:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
  NV_USAGES = record
    version: NvU32;
    usage: array[0..NVAPI_MAX_USAGES_PER_GPU -1of
      record
        currentUsage: array of NvU32;
      end;
  end;
  TNvUsages = NV_USAGES;
  PNvUsages = ^TNvUsages;

Und die Funktion in C#:

C#-Quelltext
1:
2:
public delegate NvStatus NvAPI_GPU_GetUsagesDelegate(
      NvPhysicalGpuHandle gpuHandle, ref NvUsages nvUsages);

Delphi:

Delphi-Quelltext
1:
NvAPI_GPU_GetUsages: function(hPhysicalGPU: PNvPhysicalGpuHandle; nvUsages: PNvUsages): NvApi_Status; cdecl;                    


Kann mir jemand sagen, was an dem Record falsch ist? Ich habe aus dem public uint[] Usage; einfach ein Array gemacht, da ich nicht genau weiß was uint[] bedeutet. Das ist wahrscheinlich falsch, oder?

EDIT: Der Aufruf sieht so aus:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
procedure TestGPUAPI;
var
  phys  : TNvPhysicalGpuHandleArray;
  log   : TNvLogicalGpuHandleArray;
  cnt   : LongWord;
  i     : Integer;
  name  : NvAPI_ShortString;
  usages: TNvUsages;
  thermal : TNvGPUThermalSettings;
  res   : NvAPI_Status;
begin
  writeln('GPU API: ' );
  if NvAPI_EnumPhysicalGPUs(phys, cnt) = NVAPI_OK then begin
    writeln('Physical GPUs ', cnt);
    for i:=0 to cnt - 1 do
      if NvAPI_GPU_GetFullName(phys[i], name) = NVAPI_OK then begin
        write('  ', name,' ');
        FillChar(thermal, sizeof(thermal), 0);
        thermal.version:=NV_GPU_THERMAL_SETTINGS_VER;
        res:=NvAPI_GPU_GetThermalSettings(phys[i],0, @thermal);
        if res= NVAPI_OK then
          write('temp: ', thermal.sensor[0].currentTemp, ' C');
        writeln;
        write('  ');
        if NvAPI_GPU_GetTachReading(phys[i], cnt) = NVAPI_OK then
          write('Fan Speed: ', cnt);
        writeln;
        write('  ');
        
// ******************* Hier wird die Funktion aufgerufen **************** //
        FillChar(usages, sizeof(usages), 0);
        usages.version:= NV_DISPLAY_DRIVER_VERSION_VER;
        NvAPI_GPU_GetUsages(phys[i], @usages);
        writeln('Usages: ', usages.usage[0].currentUsage[0]);
// ********************************************************************** //
      end;
  end;
  if NvAPI_EnumLogicalGPUs(log, cnt) = NVAPI_OK then
    writeln('Logical GPUs ', cnt);

  writeln;
end;


jaenicke - Mo 31.12.12 17:42

Das ist einfach nur ein Array von uint Werten, das laut Marshal-Angabe als Wert und nicht als Pointer angegeben wird.

Delphi-Quelltext
1:
 usage: array[0..NVAPI_MAX_USAGES_PER_GPU -1of NvU32;                    


LittleBen - Mo 31.12.12 18:01

Eine Exception bekomme ich nun nicht mehr, aber die Funktion gibt "NVAPI_INCOMPATIBLE_STRUCT_VERSION" zurück. Also irgendetwas stimmt noch nicht...

EDIT: Habe es jetzt mit einer weiteren Struktur (bzw. Funktion) probiert, dort bekomme ich jedoch auch den Fehlerwert -9 zurück (inkompatible Versionen).

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
  NV_USAGES = record
    version: NvU32;
    usage: array[0..NVAPI_MAX_USAGES_PER_GPU -1of NvU32;
  end;
  TNvUsages = NV_USAGES;
  PNvUsages = ^TNvUsages;

  NV_MEMORY_INFO = record
    version: NvU32;
    values: array[0..NVAPI_MAX_MEMORY_VALUES_PER_GPU -1of NvU32;
  end;
  TNvMemoryInfo = NV_MEMORY_INFO;
  PNvMemoryInfo = ^TNvMemoryInfo;

Aber die Strukturen stimmen doch jetzt überein?!

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
[StructLayout(LayoutKind.Sequential, Pack = 8)]
  internal struct NvUsages {
    public uint Version;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = NVAPI.MAX_USAGES_PER_GPU)]
    public uint[] Usage;
  }

[StructLayout(LayoutKind.Sequential, Pack = 8)]
  internal struct NvMemoryInfo {
    public uint Version;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst =
      NVAPI.MAX_MEMORY_VALUES_PER_GPU)]
    public uint[] Values;
  }


Flamefire - Mo 31.12.12 19:50

Bin mir nicht ganz sicher, aber 3 Dinge:
1) Probiere mal ein packed record (oder ein Alignment bis 32Bit, original will er 8 bit)
2)

C#-Quelltext
1:
2:
3:
NvUsages usages = new NvUsages();
        usages.Version = NVAPI.GPU_USAGES_VER;
        usages.Usage = new uint[NVAPI.MAX_USAGES_PER_GPU];

Kann es sein, dass es doch ein Pointer auf ein array ist? Kenne C# nicht wirklich, aber es sieht so aus...

3) Die richtige versionsnummer verwenden! Es ist GPU_USAGES_VER(=$10000) nicht NV_DISPLAY_DRIVER_VERSION_VER!


LittleBen - Mi 02.01.13 13:59

Also alle 3 Punkte sind es leider nicht, die den Error auslösen...
Nr. 1 nicht, weil bei der Struktur NV_GPU_THERMAL_SETTINGS, die in Delphi schon vorhanden ist, will er in dem CS-Code auch 8-Bit, doch in Delphi wird das auch nicht berücksichtigt und funktioniert trotzdem:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
  NV_GPU_THERMAL_SETTINGS = record
    version: NvU32;                   //structure version
    count: NvU32;                     //number of associated thermal sensors with the selected GPU
    sensor: array[0..NVAPI_MAX_THERMAL_SENSORS_PER_GPU - 1of
      record
        controller: NV_THERMAL_CONTROLLER;         //internal, ADM1032, MAX6649...
        defaultMinTemp: NvU32;                     //the min default temperature value of the thermal sensor in degrees centigrade
        defaultMaxTemp: NvU32;                     //the max default temperature value of the thermal sensor in degrees centigrade
        currentTemp: NvU32;                        //the current temperature value of the thermal sensor in degrees centigrade
        target: NV_THERMAL_TARGET;                 //thermal senor targeted @ GPU, memory, chipset, powersupply, canoas...
      end;
  end;
  TNvGPUThermalSettings = NV_GPU_THERMAL_SETTINGS;
  PNvGPUThermalSettings = ^TNvGPUThermalSettings;

Aufruf dieser Funktion habe ich bereits gepostet.
Nr. 2 kann es auch nicht sein, weil der Aufruf der Funktion NvAPI_GPU_GetThermalSettings funktioniert (ohne Pointer auf ein Array)
Nr. 3 habe ich ausprobiert, ändert sich aber nichts...


LittleBen - Mi 02.01.13 18:27

Ich poste jetzt einfach mal den ordnelich gemachten Code (Strukturen und Aufrufe). Vielleicht fällt euch etwas ins Auge...

NvApi.pas (Strukturen)

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
const
  NVAPI_MAX_USAGES_PER_GPU           = 33;
  NVAPI_MAX_MEMORY_VALUES_PER_GPU    = 5;
  NVAPI_MAX_COOLER_PER_GPU          = 20;

// --------------------- THERMAL war bereits vorhanden und funktioniert --------------------- //
///////////////////////////////////////////////////////////////////////////////////
//  Thermal API
//  Provides ability to get temperature levels from the various thermal sensors associated with the GPU

const
  NVAPI_MAX_THERMAL_SENSORS_PER_GPU = 3;

type
  NV_THERMAL_TARGET = (
    NVAPI_THERMAL_TARGET_NONE          = 0,
    NVAPI_THERMAL_TARGET_GPU           = 1,
    NVAPI_THERMAL_TARGET_MEMORY        = 2,
    NVAPI_THERMAL_TARGET_POWER_SUPPLY  = 4,
    NVAPI_THERMAL_TARGET_BOARD         = 8,
    NVAPI_THERMAL_TARGET_ALL           = 15,
    NVAPI_THERMAL_TARGET_UNKNOWN       = -1
  );

  NV_THERMAL_CONTROLLER = (
    NVAPI_THERMAL_CONTROLLER_NONE = 0,
    NVAPI_THERMAL_CONTROLLER_GPU_INTERNAL,
    NVAPI_THERMAL_CONTROLLER_ADM1032,
    NVAPI_THERMAL_CONTROLLER_MAX6649,
    NVAPI_THERMAL_CONTROLLER_MAX1617,
    NVAPI_THERMAL_CONTROLLER_LM99,
    NVAPI_THERMAL_CONTROLLER_LM89,
    NVAPI_THERMAL_CONTROLLER_LM64,
    NVAPI_THERMAL_CONTROLLER_ADT7473,
    NVAPI_THERMAL_CONTROLLER_SBMAX6649,
    NVAPI_THERMAL_CONTROLLER_VBIOSEVT,
    NVAPI_THERMAL_CONTROLLER_OS,
    NVAPI_THERMAL_CONTROLLER_UNKNOWN = -1
  );

  NV_GPU_THERMAL_SETTINGS = record
    version: NvU32;                   //structure version
    count: NvU32;                     //number of associated thermal sensors with the selected GPU
    sensor: array[0..NVAPI_MAX_THERMAL_SENSORS_PER_GPU - 1of
      record
        controller: NV_THERMAL_CONTROLLER;         //internal, ADM1032, MAX6649...
        defaultMinTemp: NvU32;                     //the min default temperature value of the thermal sensor in degrees centigrade
        defaultMaxTemp: NvU32;                     //the max default temperature value of the thermal sensor in degrees centigrade
        currentTemp: NvU32;                        //the current temperature value of the thermal sensor in degrees centigrade
        target: NV_THERMAL_TARGET;                 //thermal senor targeted @ GPU, memory, chipset, powersupply, canoas...
      end;
  end;
  TNvGPUThermalSettings = NV_GPU_THERMAL_SETTINGS;
  PNvGPUThermalSettings = ^TNvGPUThermalSettings;

// ------------------------------------------------------------------------------------------ //

///////////////////////////////////////////////////////////////////////////////////
//  Usages API

const
  NV_GPU_USAGES_VER = $10000;

type
  NV_USAGES = record
    Version: NvU32;
    Usage: array[0..NVAPI_MAX_USAGES_PER_GPU -1of NvU32;
  end;
  TNvUsages = NV_USAGES;
  PNvUsages = ^TNvUsages;

///////////////////////////////////////////////////////////////////////////////////
//  Memory API

const
  NV_GPU_MEMORY_INFO_VER = $20000;

type
  NV_MEMORY_INFO = record
    Version: NvU32;
    Values: array[0..NVAPI_MAX_MEMORY_VALUES_PER_GPU -1of NvU32;
  end;
  TNvMemoryInfo = NV_MEMORY_INFO;
  PNvMemoryInfo = ^TNvMemoryInfo;

///////////////////////////////////////////////////////////////////////////////////
//  Cooler API

const
  NV_GPU_COOLER_SETTINGS_VER = $20000;

type
  NV_COOLER_SETTINGS = record
    Version: NvU32;
    Count: NvU32;
    Cooler: array[0..NVAPI_MAX_COOLER_PER_GPU -1of
      record
        Controller: integer;
        DefaultMin: integer;
        DefaultMax: integer;
        CurrentMin: integer;
        CurrentMax: integer;
        CurrentLevel: integer;
        DefaultPolicy: integer;
        CurrentPolicy: integer;
        Target: integer;
        ControlType: integer;
        Active: integer;
      end;
  end;
  TNvCoolerSettings = NV_COOLER_SETTINGS;
  PNvCoolerSettings = ^TNvCoolerSettings;


const
  NV_GPU_COOLER_LEVELS_VER = $10000;

type
  NV_GPU_COOLER_LEVELS = record
    Version: NvU32;
    Levels: array[0..NVAPI_MAX_COOLER_PER_GPU -1of
      record
        Level: integer;
        Policy: integer;
      end;
  end;
  TNvGPUCoolerLevels = NV_GPU_COOLER_LEVELS;
  PNvGPUCoolerLevels = ^TNvGPUCoolerLevels;

{...}

var
  NvAPI_GPU_GetThermalSettings: function(hPhysicalGpu: PNvPhysicalGpuHandle; sensorIndex: NvU32; pThermalSettings: PNvGPUThermalSettings): NvAPI_Status; cdecl;  

  NvAPI_GPU_GetUsages: function(hPhysicalGPU: PNvPhysicalGpuHandle; nvUsages: PNvUsages): NvApi_Status; cdecl;

  NvAPI_GPU_GetMemoryInfo: function(pNvDispHandle: PNvDisplayHandle; nvMemoryInfo: PNvMemoryInfo): NvApi_Status; cdecl;

  NvAPI_GPU_GetCoolerSettings: function(hPhysicalGPU: PNvPhysicalGpuHandle; CoolerIndex: integer; NvCoolerSettings: PNvCoolerSettings): NvApi_Status; cdecl;


NvApiTest.pas (Verwendung)

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
procedure TestGPUAPI;
var n: Integer;
    nCount: LongWord;
    cName: NvAPI_ShortString;
    nSpeed: LongWord;

    Phys: TNvPhysicalGpuHandleArray;
    Log: TNvLogicalGpuHandleArray;

    Thermal: TNvGPUThermalSettings;
    Usages: TNvUsages;
    Memory: TNvMemoryInfo;
    Cooler: TNvCoolerSettings;
    Status: NvAPI_Status;
begin
  writeln('GPU API: ' );
  if NvAPI_EnumPhysicalGPUs(Phys, nCount) = NVAPI_OK then
  begin
   writeln('Physical GPUs ', nCount);
   for n:=0 to nCount - 1 do
   begin
    if NvAPI_GPU_GetFullName(Phys[n], cName) = NVAPI_OK then
    begin
     write('  ', cName, ' ');

     // ****************** TEMPERATUR ****************** //
     FillChar(Thermal, SizeOf(Thermal), 0);
     Thermal.Version:= NV_GPU_THERMAL_SETTINGS_VER;
     Status:= NvAPI_GPU_GetThermalSettings(Phys[n],0, @Thermal);
     if Status = NVAPI_OK then
     begin
      write('temp: ', Thermal.Sensor[0].CurrentTemp, ' C');
      writeln;
      write('  ');
     end
     else
      showmessage(inttostr(Integer(Status)));
     // ************************************************ //

     // ****************** FAN SPEED ******************* //
     Status:= NvAPI_GPU_GetTachReading(Phys[n], nSpeed);
     if Status = NVAPI_OK then
     begin
      write('Fan Speed: ', nSpeed);
      writeln;
      write('  ');
     end
     else
      showmessage(inttostr(Integer(Status)));
     // ************************************************ //

     // ******************** USAGES ******************** //
     FillChar(Usages, SizeOf(Usages), 0);
     Usages.Version:= NV_GPU_USAGES_VER;
     Status:= NvAPI_GPU_GetUsages(Phys[n], @Usages);
     if Status = NVAPI_OK then
     begin
      write('Usages: ', Usages.Usage[0]);
      writeln;
      write('  ');
     end
     else
      showmessage(inttostr(Integer(Status)));
     // ************************************************ //

     // ***************** MEMORY INFO ****************** //
     FillChar(Memory, SizeOf(Memory), 0);
     Memory.Version:= NV_GPU_MEMORY_INFO_VER;
     Status:= NvAPI_GPU_GetMemoryInfo(0, @Memory);
     if Status = NVAPI_OK then
     begin
      write('Memory: ', Memory.Values[0]);
      writeln;
      write('  ');
     end
     else
      showmessage(inttostr(Integer(Status)));
     // ************************************************ //

     // ***************** COOLER INFO ****************** //
     FillChar(Cooler, SizeOf(Cooler), 0);
     Cooler.Version:= NV_GPU_COOLER_SETTINGS_VER;
     Status:= NvAPI_GPU_GetCoolerSettings(Phys[n], 0, @Cooler);
     if Status = NVAPI_OK then
     begin
      write('Cooler: ', Cooler.Cooler[0].CurrentLevel);
      writeln;
      write('  ');
     end
     else
      showmessage(inttostr(Integer(Status)));
     // ************************************************ //
    end;
   end;
  end;

  if NvAPI_EnumLogicalGPUs(log, nCount) = NVAPI_OK then
    writeln('Logical GPUs ', nCount);

  writeln;
end;


Bei NvAPI_GPU_GetUsages und NvAPI_GPU_GetMemoryInfo bekommt man die Fehlermeldung NVAPI_INCOMPATIBLE_STRUCT_VERSION.
Bei NvAPI_GPU_GetCoolerSettings hängt sich das Programm auf.

Hat denn keiner eine Idee woran das liegen kann?

// EDIT: Ohhhhh sorry, doppel post, habe nicht drauf geachtet :oops:

// EDIT 2.0 : KOMMANDO ZURÜCK :autsch:
Die Konstanten müssen so aussehen -.-

Delphi-Quelltext
1:
2:
3:
4:
5:
const
  NV_GPU_USAGES_VER = NvU32(SizeOf(NV_USAGES) or ($10000));
  NV_GPU_MEMORY_INFO_VER = NvU32(SizeOf(NV_MEMORY_INFO) or ($20000));
  NV_GPU_COOLER_SETTINGS_VER = NvU32(SizeOf(NV_COOLER_SETTINGS) or ($20000));
  NV_GPU_COOLER_LEVELS_VER = NvU32(SizeOf(NV_GPU_COOLER_LEVELS) or ($10000));

Jetzt funktioniert alles ^^

Und hier das Endergebnis:
[url=http://www.abload.de/image.php?img=img_053411qis.jpg]user defined image[/url]