NvAPI_GPU_GetMemoryInfoEx in dynamic mode (QueryInterface Magic Number)

Hello, I working on an Engine with DirectX. Inside the engine I display Video card information, like name, ram type, Temp, usage and etc. Unfortunately because the engine use AMD, NVIDIA and Intel, I’m forced to use dynamic way to avoid dll missing popup message from static version. The conversion work really fine, actually I made in one day.

Because NvAPI_GPU_GetMemoryInfo was deprecated I must use NvAPI_GPU_GetMemoryInfoEx. Habitually, to convert in dynamic way, we use GetProcAddress and dumpbin on the DLL.

NvAPI_QueryInterface = (NvAPI_QueryInterface_t)GetProcAddress(hDLL, "nvapi_QueryInterface");

But for this API we use a magic offset that you send to QueryInterface

NvAPI_GPU_GetMemoryInfo = (NvAPI_GPU_GetMemoryInfo_t)(*NvAPI_QueryInterface)(0x774AA982);

Now I need to know 2 thing.

  1. How get QueryInterface magic number from DLL or LIB?
  2. What is the offset of NvAPI_GPU_GetMemoryInfoEX?

Static-Way (Working with API SDK)

#include <stdio.h>
#include <nvapi.h>

#pragma comment(lib, "nvapi64.lib")

int main()
{
	
	if (NvAPI_Initialize() == NVAPI_OK)
	{
		unsigned long  gpuCount = 0;
		NvPhysicalGpuHandle gpuHandles[NVAPI_MAX_PHYSICAL_GPUS] = { NULL };

		NvAPI_EnumPhysicalGPUs(gpuHandles, &gpuCount);

		char nvNameAnsiString[1024] = "";
		NvAPI_GPU_GetFullName(gpuHandles[0], nvNameAnsiString);

		printf("Video Card : %s\n", nvNameAnsiString);

		NV_GPU_MEMORY_INFO_EX MemoryInfo = { NV_GPU_MEMORY_INFO_EX_VER };
		NvAPI_GPU_GetMemoryInfoEx(gpuHandles[0], &MemoryInfo);

		printf("Ram : %lld\n", MemoryInfo.availableDedicatedVideoMemory);

		//Only work if 4996 was disable
		#pragma warning(disable : 4996)
		NV_DISPLAY_DRIVER_MEMORY_INFO MemoryInfoV3 = { NV_DISPLAY_DRIVER_MEMORY_INFO_VER };
		NvAPI_GPU_GetMemoryInfo(gpuHandles[0], &MemoryInfoV3);

		printf("Ram (old): %lld\n", MemoryInfo.availableDedicatedVideoMemory);
	}

	return 0;
}

Dynamic-Way (Dont need API SDK, only a NVIDIA video card installed on your PC “DLL will be there”)

//*** Macro definition ******************************************************
#ifndef _RELENTLESS_NVIDIA_VIDEO_H__
	#define _RELENTLESS_NVIDIA_VIDEO_H__

#pragma once

//*** Include ***************************************************************
#include <RDPCStatus.h>

//*** NVIDIA ADL DLL Module ****************************************************
#define MAKE_NVAPI_VERSION(typeName,ver) (unsigned long)(sizeof(typeName) | ((ver) << 16))

#define NVAPI_MAX_THERMAL_SENSORS_PER_GPU 3

typedef enum
{
	NVAPI_THERMAL_TARGET_NONE = 0,
	NVAPI_THERMAL_TARGET_GPU = 1,     //!< GPU core temperature requires NvPhysicalGpuHandle
	NVAPI_THERMAL_TARGET_MEMORY = 2,     //!< GPU memory temperature requires NvPhysicalGpuHandle
	NVAPI_THERMAL_TARGET_POWER_SUPPLY = 4,     //!< GPU power supply temperature requires NvPhysicalGpuHandle
	NVAPI_THERMAL_TARGET_BOARD = 8,     //!< GPU board ambient temperature requires NvPhysicalGpuHandle
	NVAPI_THERMAL_TARGET_VCD_BOARD = 9,     //!< Visual Computing Device Board temperature requires NvVisualComputingDeviceHandle
	NVAPI_THERMAL_TARGET_VCD_INLET = 10,    //!< Visual Computing Device Inlet temperature requires NvVisualComputingDeviceHandle
	NVAPI_THERMAL_TARGET_VCD_OUTLET = 11,    //!< Visual Computing Device Outlet temperature requires NvVisualComputingDeviceHandle

	NVAPI_THERMAL_TARGET_ALL = 15,
	NVAPI_THERMAL_TARGET_UNKNOWN = -1,
} NV_THERMAL_TARGET;

typedef struct
{
	int   version;                //!< structure version 
	int   count;                  //!< number of associated thermal sensors
	struct
	{
		int       controller;        //!< internal, ADM1032, MAX6649...
		int                       defaultMinTemp;    //!< The min default temperature value of the thermal sensor in degree Celsius 
		int                       defaultMaxTemp;    //!< The max default temperature value of the thermal sensor in degree Celsius 
		int                       currentTemp;       //!< The current temperature value of the thermal sensor in degree Celsius 
		NV_THERMAL_TARGET           target;            //!< Thermal sensor targeted @ GPU, memory, chipset, powersupply, Visual Computing Device, etc.
	} sensor[NVAPI_MAX_THERMAL_SENSORS_PER_GPU];

} NV_GPU_THERMAL_SETTINGS;

#define NV_GPU_THERMAL_SETTINGS_VER   MAKE_NVAPI_VERSION(NV_GPU_THERMAL_SETTINGS,1)

// magic numbers, do not change them
#define NVAPI_MAX_PHYSICAL_GPUS   64
#define NVAPI_MAX_USAGES_PER_GPU  33  //34

typedef enum _NV_RAM_TYPE
{
	NV_RAM_TYPE_NONE,
	NV_RAM_TYPE_SDRAM,
	NV_RAM_TYPE_DDR1,
	NV_RAM_TYPE_DDR2,
	NV_RAM_TYPE_GDDR2,
	NV_RAM_TYPE_GDDR3,
	NV_RAM_TYPE_GDDR4,
	NV_RAM_TYPE_DDR3,
	NV_RAM_TYPE_GDDR5,
	NV_RAM_TYPE_LPDDR2
} NV_RAM_TYPE;

const char* RAMTYPESTR[] = { "None",  "SDRAM", "DDR1", "DDR2", "GDDR2", "GDDR3", "GDDR4", "DDR3", "GDDR5", "LPDDR2" };

typedef struct
{
	unsigned long version;                              //!< Structure version
	unsigned long usages[NVAPI_MAX_USAGES_PER_GPU];
} NV_USAGES_INFO;

#define NV_USAGES_INFO_VER  MAKE_NVAPI_VERSION(NV_USAGES_INFO, 1)

typedef enum _NV_COOLER_TYPE
{
	NVAPI_COOLER_TYPE_NONE = 0,
	NVAPI_COOLER_TYPE_FAN,
	NVAPI_COOLER_TYPE_WATER,
	NVAPI_COOLER_TYPE_LIQUID_NO2,
} NV_COOLER_TYPE;

// rev
typedef enum _NV_COOLER_CONTROLLER
{
	NVAPI_COOLER_CONTROLLER_NONE = 0,
	NVAPI_COOLER_CONTROLLER_ADI,
	NVAPI_COOLER_CONTROLLER_INTERNAL,
} NV_COOLER_CONTROLLER;

// rev
typedef enum _NV_COOLER_POLICY
{
	NVAPI_COOLER_POLICY_NONE = 0,
	NVAPI_COOLER_POLICY_MANUAL,                     // Manual adjustment of cooler level. Gets applied right away independent of temperature or performance level.
	NVAPI_COOLER_POLICY_PERF,                       // GPU performance controls the cooler level.
	NVAPI_COOLER_POLICY_TEMPERATURE_DISCRETE = 4,   // Discrete thermal levels control the cooler level.
	NVAPI_COOLER_POLICY_TEMPERATURE_CONTINUOUS = 8, // Cooler level adjusted at continuous thermal levels.
	NVAPI_COOLER_POLICY_HYBRID,                     // Hybrid of performance and temperature levels.
} NV_COOLER_POLICY;

typedef enum _NV_COOLER_TARGET
{
	NVAPI_COOLER_TARGET_NONE = 0,
	NVAPI_COOLER_TARGET_GPU,
	NVAPI_COOLER_TARGET_MEMORY,
	NVAPI_COOLER_TARGET_POWER_SUPPLY = 4,
	NVAPI_COOLER_TARGET_ALL = 7                    // This cooler cools all of the components related to its target gpu.
} NV_COOLER_TARGET;

// rev
typedef enum _NV_COOLER_CONTROL
{
	NVAPI_COOLER_CONTROL_NONE = 0,
	NVAPI_COOLER_CONTROL_TOGGLE,                   // ON/OFF
	NVAPI_COOLER_CONTROL_VARIABLE,                 // Suppports variable control.
} NV_COOLER_CONTROL;

// rev
typedef enum _NV_COOLER_ACTIVITY_LEVEL
{
	NVAPI_INACTIVE = 0,                             // inactive or unsupported
	NVAPI_ACTIVE = 1,                               // active and spinning in case of fan
} NV_COOLER_ACTIVITY_LEVEL;

#define NVAPI_MAX_COOLERS_PER_GPU   3

typedef struct _NV_GPU_COOLER_SETTINGS
{
	unsigned long version;                           // structure version
	unsigned long count;                             // number of associated coolers with the selected GPU
	struct
	{
		NV_COOLER_TYPE type;                 // type of cooler - FAN, WATER, LIQUID_NO2...
		NV_COOLER_CONTROLLER controller;     // internal, ADI...
		unsigned long defaultMinLevel;               // the min default value % of the cooler
		unsigned long defaultMaxLevel;               // the max default value % of the cooler
		unsigned long currentMinLevel;               // the current allowed min value % of the cooler
		unsigned long currentMaxLevel;               // the current allowed max value % of the cooler
		unsigned long currentLevel;                  // the current value % of the cooler
		NV_COOLER_POLICY defaultPolicy;      // cooler control policy - auto-perf, auto-thermal, manual, hybrid...
		NV_COOLER_POLICY currentPolicy;      // cooler control policy - auto-perf, auto-thermal, manual, hybrid...
		NV_COOLER_TARGET target;             // cooling target - GPU, memory, chipset, powersupply, canoas...
		NV_COOLER_CONTROL controlType;       // toggle or variable
		NV_COOLER_ACTIVITY_LEVEL active;     // is the cooler active - fan spinning...
	} cooler[NVAPI_MAX_COOLERS_PER_GPU];
} NV_GPU_COOLER_SETTINGS, * PNV_GPU_COOLER_SETTINGS;

#define NV_GPU_COOLER_SETTINGS_VER  MAKE_NVAPI_VERSION(NV_GPU_COOLER_SETTINGS, 1)

typedef struct
{
	unsigned long version;                           //!< Structure version
	unsigned long long dedicatedVideoMemory;              //!< Size(in bytes) of the physical framebuffer.
	unsigned long long availableDedicatedVideoMemory;     //!< Size(in bytes) of the available physical framebuffer for allocating video memory surfaces.
	unsigned long long systemVideoMemory;                 //!< Size(in bytes) of system memory the driver allocates at load time.
	unsigned long long sharedSystemMemory;                //!< Size(in bytes) of shared system memory that driver is allowed to commit for surfaces across all allocations.
	unsigned long long curAvailableDedicatedVideoMemory;  //!< Size(in bytes) of the current available physical framebuffer for allocating video memory surfaces.
	unsigned long long dedicatedVideoMemoryEvictionsSize; //!< Size(in bytes) of the total size of memory released as a result of the evictions.
	unsigned long long dedicatedVideoMemoryEvictionCount; //!< Indicates the number of eviction events that caused an allocation to be removed from dedicated video memory to free GPU //!< video memory to make room for other allocations.
	unsigned long long dedicatedVideoMemoryPromotionsSize;  //!< Size(in bytes) of the total size of memory allocated as a result of the promotions.
	unsigned long long dedicatedVideoMemoryPromotionCount;  //!< Indicates the number of promotion events that caused an allocation to be promoted to dedicated video memory 
} NV_GPU_MEMORY_INFO_EX;

#define NV_GPU_MEMORY_INFO_EX_VER  MAKE_NVAPI_VERSION(NV_GPU_MEMORY_INFO_EX, 1)

typedef struct
{
	unsigned long version;                        //!< Version info
	unsigned long dedicatedVideoMemory;           //!< Size(in kb) of the physical framebuffer.
	unsigned long availableDedicatedVideoMemory;  //!< Size(in kb) of the available physical framebuffer for allocating video memory surfaces.
	unsigned long systemVideoMemory;              //!< Size(in kb) of system memory the driver allocates at load time.
	unsigned long sharedSystemMemory;             //!< Size(in kb) of shared system memory that driver is allowed to commit for surfaces across all allocations.

} NV_DISPLAY_DRIVER_MEMORY_INFO_V1;


//! \ingroup driverapi
//! Used in NvAPI_GPU_GetMemoryInfo().
typedef struct
{
	unsigned long version;                           //!< Version info
	unsigned long dedicatedVideoMemory;              //!< Size(in kb) of the physical framebuffer.
	unsigned long availableDedicatedVideoMemory;     //!< Size(in kb) of the available physical framebuffer for allocating video memory surfaces.
	unsigned long systemVideoMemory;                 //!< Size(in kb) of system memory the driver allocates at load time.
	unsigned long sharedSystemMemory;                //!< Size(in kb) of shared system memory that driver is allowed to commit for surfaces across all allocations.
	unsigned long curAvailableDedicatedVideoMemory;  //!< Size(in kb) of the current available physical framebuffer for allocating video memory surfaces.

} NV_DISPLAY_DRIVER_MEMORY_INFO_V2;

typedef struct
{
	unsigned long version;                           //!< Version info
	unsigned long dedicatedVideoMemory;              //!< Size(in kb) of the physical framebuffer.
	unsigned long availableDedicatedVideoMemory;     //!< Size(in kb) of the available physical framebuffer for allocating video memory surfaces.
	unsigned long systemVideoMemory;                 //!< Size(in kb) of system memory the driver allocates at load time.
	unsigned long sharedSystemMemory;                //!< Size(in kb) of shared system memory that driver is allowed to commit for surfaces across all allocations.
	unsigned long curAvailableDedicatedVideoMemory;  //!< Size(in kb) of the current available physical framebuffer for allocating video memory surfaces.
	unsigned long dedicatedVideoMemoryEvictionsSize; //!< Size(in kb) of the total size of memory released as a result of the evictions.
	unsigned long dedicatedVideoMemoryEvictionCount; //!< Indicates the number of eviction events that caused an allocation to be removed from dedicated video memory to free GPU
	//!< video memory to make room for other allocations.
} NV_DISPLAY_DRIVER_MEMORY_INFO_V3;

typedef NV_DISPLAY_DRIVER_MEMORY_INFO_V3     NV_DISPLAY_DRIVER_MEMORY_INFO;

#define NV_DISPLAY_DRIVER_MEMORY_INFO_VER_1  MAKE_NVAPI_VERSION(NV_DISPLAY_DRIVER_MEMORY_INFO_V1,1)
#define NV_DISPLAY_DRIVER_MEMORY_INFO_VER_2  MAKE_NVAPI_VERSION(NV_DISPLAY_DRIVER_MEMORY_INFO_V2,2)
#define NV_DISPLAY_DRIVER_MEMORY_INFO_VER_3  MAKE_NVAPI_VERSION(NV_DISPLAY_DRIVER_MEMORY_INFO_V3,3)

#define NV_DISPLAY_DRIVER_MEMORY_INFO_VER    NV_DISPLAY_DRIVER_MEMORY_INFO_VER_3


typedef int* (*NvAPI_QueryInterface_t)(unsigned int offset);
typedef int (*NvAPI_Initialize_t)();
typedef int (*NvAPI_EnumPhysicalGPUs_t)(int** handles, int* count);
typedef int (*NvAPI_GPU_GetUsages_t)(int* handle, NV_USAGES_INFO* pusages);
typedef int (*NvAPI_GPU_GetCoolerSettings_t)(int* handle, unsigned long coolerIndex, NV_GPU_COOLER_SETTINGS* pCoolerInfo);
typedef int (*NvAPI_GPU_GetThermalSettings_t)(int* handle, int sensorIndex, NV_GPU_THERMAL_SETTINGS* temp);
typedef int (*NvAPI_GPU_GetTachReading_t)(int* handle, long* speed);
typedef int (*NvAPI_GPU_getFullName_t)(int* handle, char* name); 
typedef int (*NvAPI_GPU_GetRamType_t)(int* handle, NV_RAM_TYPE* pRamType);
typedef int (*NvAPI_GPU_GetMemoryInfo_t)(int* handle, NV_DISPLAY_DRIVER_MEMORY_INFO* pMemoryInfo);

//*** Class definition ******************************************************
class CRDNVidiaVideo
{
public:
	CRDNVidiaVideo(CRCArray<VideoCard*>* VideoCardList);
	~CRDNVidiaVideo();
	void Update(CRCArray<VideoCard*>* VideoCardList);

private:
	NvAPI_QueryInterface_t NvAPI_QueryInterface;
	NvAPI_Initialize_t NvAPI_Initialize;
	NvAPI_EnumPhysicalGPUs_t NvAPI_EnumPhysicalGPUs;
	NvAPI_GPU_GetUsages_t NvAPI_GPU_GetUsages;
	NvAPI_GPU_GetThermalSettings_t NvAPI_GPU_GetThermalSettings;
	NvAPI_GPU_GetTachReading_t NvAPI_GPU_GetTachReading;
	NvAPI_GPU_getFullName_t NvAPI_GPU_getFullName;
	NvAPI_GPU_GetRamType_t NvAPI_GPU_GetRamType;
	NvAPI_GPU_GetMemoryInfo_t NvAPI_GPU_GetMemoryInfo;
	NvAPI_GPU_GetCoolerSettings_t NvAPI_GPU_GetCoolerSettings;

	HINSTANCE hDLL;
};
//*** End macro definition **************************************************
#endif

//*** Macro definition ******************************************************
#ifndef _RELENTLESS_NVIDIA_VIDEO_CPP__
	#define _RELENTLESS_NVIDIA_VIDEO_CPP__

//*** Include ***************************************************************
//#include "RDNVidiaVideo.h"

//***************************************************************************
// Output        :
// Class name    : CRDAmdVideo
// Function name : CRDAmdVideo
// Description   : Constructor
// Input         : 
//***************************************************************************
CRDNVidiaVideo::CRDNVidiaVideo(CRCArray<VideoCard*>* VideoCardList)
{
	hDLL = LoadLibrary(L"nvapi64.dll");

	if (hDLL != NULL)
	{
		NvAPI_QueryInterface = (NvAPI_QueryInterface_t)GetProcAddress(hDLL, "nvapi_QueryInterface");

		// some useful internal functions that aren't exported by nvapi.dll
		NvAPI_Initialize = (NvAPI_Initialize_t)(*NvAPI_QueryInterface)(0x0150E828);
		NvAPI_EnumPhysicalGPUs = (NvAPI_EnumPhysicalGPUs_t)(*NvAPI_QueryInterface)(0xE5AC921F);
		NvAPI_GPU_GetUsages = (NvAPI_GPU_GetUsages_t)(*NvAPI_QueryInterface)(0x189A1FDF);
		NvAPI_GPU_GetThermalSettings = (NvAPI_GPU_GetThermalSettings_t)(*NvAPI_QueryInterface)(0xE3640A56);
		NvAPI_GPU_GetTachReading = (NvAPI_GPU_GetTachReading_t)(*NvAPI_QueryInterface)(0x5F608315UL);
		NvAPI_GPU_getFullName = (NvAPI_GPU_getFullName_t)(*NvAPI_QueryInterface)(0xCEEE8e9FUL);
		NvAPI_GPU_GetRamType = (NvAPI_GPU_GetRamType_t)(*NvAPI_QueryInterface)(0x57F7CAACUL);
		//NvAPI_GPU_GetRamBusWidth = (NvAPI_GPU_GetRamBusWidth_t)(*NvAPI_QueryInterface)(0x7975C581);
		//NvAPI_GPU_GetRamBankCount = (NvAPI_GPU_GetRamBankCount_t)(*NvAPI_QueryInterface)(0x17073A3CUL);
		NvAPI_GPU_GetMemoryInfo = (NvAPI_GPU_GetMemoryInfo_t)(*NvAPI_QueryInterface)(0x774AA982);
		NvAPI_GPU_GetCoolerSettings = (NvAPI_GPU_GetCoolerSettings_t)(*NvAPI_QueryInterface)(0xDA141340UL);

		if (NvAPI_Initialize != NULL && NvAPI_EnumPhysicalGPUs != NULL && NvAPI_EnumPhysicalGPUs != NULL && NvAPI_GPU_GetUsages != NULL)
		{
			(*NvAPI_Initialize)();

			int  gpuCount = 0;
			int* gpuHandles[NVAPI_MAX_PHYSICAL_GPUS] = { NULL };
			
			(*NvAPI_EnumPhysicalGPUs)(gpuHandles, &gpuCount);

			for (int GPUIndex = 0; GPUIndex < gpuCount; GPUIndex++)
			{
				VideoCard* AddElem = new VideoCard();
				AddElem->pAdapterIndex = gpuHandles[GPUIndex];

				char nvNameAnsiString[1024] = "";
				(*NvAPI_GPU_getFullName)(AddElem->pAdapterIndex, nvNameAnsiString);

				NV_RAM_TYPE RamType;
				(*NvAPI_GPU_GetRamType)(AddElem->pAdapterIndex, &RamType);

				//NV_GPU_MEMORY_INFO_EX memoryInfo = { sizeof(NV_GPU_MEMORY_INFO_EX) | (1 << 16) };
				NV_DISPLAY_DRIVER_MEMORY_INFO memoryInfo = { NV_DISPLAY_DRIVER_MEMORY_INFO_VER };
				(*NvAPI_GPU_GetMemoryInfo)(AddElem->pAdapterIndex, &memoryInfo);

				//unsigned long BusWidth;
				//(*NvAPI_GPU_GetRamBusWidth)(AddElem->pAdapterIndex, &BusWidth);

				//unsigned long BankCount;
				//(*NvAPI_GPU_GetRamBankCount)(AddElem->pAdapterIndex, &BankCount);

				strcpy_s(AddElem->AdapterName, nvNameAnsiString);
				strcpy_s(AddElem->MemoryType, RAMTYPESTR[RamType]);
				AddElem->MemorySize = memoryInfo.availableDedicatedVideoMemory;
				
				VideoCardList->Add(AddElem, 0, 0);
			}

		}
	}
}

//***************************************************************************
// Output        :
// Class name    : CRDAmdVideo
// Function name : CRDAmdVideo
// Description   : Constructor
// Input         : 
//***************************************************************************
CRDNVidiaVideo::~CRDNVidiaVideo()
{
}

//***************************************************************************
// Output        :
// Class name    : CRDAmdVideo
// Function name : CRDAmdVideo
// Description   : Constructor
// Input         : 
//***************************************************************************
void CRDNVidiaVideo::Update(CRCArray<VideoCard*>* VideoCardList)
{
	long NbElem = VideoCardList->GetNbElem();
	for (long i = 0; i < NbElem; i++)
	{
		VideoCard* CurrentData = VideoCardList->GetData(i);

		NV_GPU_THERMAL_SETTINGS nvgts;
		nvgts.version = NV_GPU_THERMAL_SETTINGS_VER;
		nvgts.count = 0;
		nvgts.sensor[0].controller = -1;
		nvgts.sensor[0].target = NVAPI_THERMAL_TARGET_GPU;
		(*NvAPI_GPU_GetThermalSettings)(CurrentData->pAdapterIndex, 0, &nvgts);
		
		NV_USAGES_INFO gpuUsages = { NV_USAGES_INFO_VER };
		(*NvAPI_GPU_GetUsages)(CurrentData->pAdapterIndex, &gpuUsages);
		
		long RPMSpeed = 0;
		(*NvAPI_GPU_GetTachReading)(CurrentData->pAdapterIndex, &RPMSpeed);
		
		NV_GPU_COOLER_SETTINGS coolerInfo = { NV_GPU_COOLER_SETTINGS_VER };
		(*NvAPI_GPU_GetCoolerSettings)(CurrentData->pAdapterIndex, NVAPI_COOLER_TARGET_ALL, &coolerInfo);

		CurrentData->Temperature = (float)nvgts.sensor[0].currentTemp;
		CurrentData->ActivityPercent = gpuUsages.usages[2];
		CurrentData->FanRPM = RPMSpeed;
		CurrentData->FanPercent = coolerInfo.cooler[0].currentLevel;
	}
}

//*** End macro definition **************************************************
#endif 

Dear @mathstlaurent

Thank you for contacting NVIDIA Developer Forum.
Our technical team has received your query and they have informed that the information you have requested can be found in NvAPI Open Source SDK. You can refer to the documentation available in the pdf file in the SDK folder. Here’s the link to the download page: Index of /XFree86/nvapi-open-source-sdk

We hope this resolves your query.

Thank you.
NVAPI Forum Moderator

Thanks, it’s really what I need. I found the query address of NvAPI_GPU_GetMemoryInfoEx at 0xc0599498.

We are happy that your query is resolved. I am marking this topic as Closed.

Thank you.
NVAPI Forum Moderator