Custom Timings/Resolution via NVAPI not working

I have two environments that I’m testing the following code on - both of which give me different results.

bool setDesktopResolutionNVAPI(int horizontal, int vertical) {

		NvAPI_Status result = NVAPI_ERROR;
		NvU32 primaryDisplayId = 0;

		result = NvAPI_Initialize();

		if(result != NVAPI_OK) {
			printf("Could not initialize NvAPI");
			return false;
		}

		MONITORINFOEX monInfo;
		HMONITOR hMon;
		const POINT ptZero = {0, 0};

		// determine the location of the primary monitor
		hMon = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
		ZeroMemory(&monInfo, sizeof(monInfo));
		monInfo.cbSize = sizeof(monInfo);
		GetMonitorInfo(hMon, &monInfo);

		result = NvAPI_DISP_GetDisplayIdByDisplayName(monInfo.szDevice, &primaryDisplayId);

		if(result != NVAPI_OK) {
			printf("Could not get display ID from device");
			NvAPI_Unload();
			return false;
		}

		NV_DISPLAYCONFIG_PATH_INFO_V2* pathInfo = NULL;
		NvU32 deviceCount = 0;
		NV_CUSTOM_DISPLAY cd[NVAPI_MAX_DISPLAYS] = {0};

		float refreshRate = 60;
		// timing computation (to get timing that suits the changes made)
		NV_TIMING_FLAG flag = {0};
		NV_TIMING_INPUT timing = {0};
		timing.version = NV_TIMING_INPUT_VER;
		timing.height = vertical;
		timing.width = horizontal;
		timing.rr = refreshRate;
		timing.flag = flag;
		timing.type = NV_TIMING_OVERRIDE_AUTO;

		result = NvAPI_DISP_GetTiming(primaryDisplayId, &timing, &cd[0].timing);

		if(result != NVAPI_OK) {
			printf("Failed to get timing for display"); // failed to get custom display timing
			NvAPI_Unload();
			return false;
		}

		cd[0].width = horizontal;
		cd[0].height = vertical;
		cd[0].xRatio = 1;
		cd[0].yRatio = 1;
		cd[0].srcPartition = {0, 0, 1.0, 1.0};
		cd[0].depth = 0;
		cd[0].version = NV_CUSTOM_DISPLAY_VER;

		result = NvAPI_DISP_TryCustomDisplay(&primaryDisplayId, 1, cd);

		if(result != NVAPI_OK) {
			printf("Could not set custom resolution");
			NvAPI_DISP_RevertCustomDisplayTrial(&primaryDisplayId, 1);
			NvAPI_Unload();
			return false;
		} else {
			NvAPI_DISP_SaveCustomDisplay(&primaryDisplayId, 1, true, true);
		}

		NvAPI_Unload();

		return true;
	}

This function succeeds when attempting to change resolutions that are registered under NVIDIA Control Panel. I’ve added custom (unnatural) resolutions to the list manually. This has been tested with a Quadro P4000 connected to a primary display.

However, when the custom resolution is not registered under NVIDIA Control Panel, NvAPI_DISP_TryCustomDisplay fails with NVAPI_ERROR.

On a GPU instance with a Tesla M60, NvAPI_DISP_GetTiming returns NVAPI_ERROR all the time. This makes some sort of sense, but ultimately I can’t call NvAPI_DISP_TryCustomDisplay without setting a proper timing.

I’ve looked around online for similar errors that people have been getting, and some people have been saying that I need the NDA version of NVAPI in order to get this to work. Can anyone shed some light on this?

1 Like

Adding the following code seems to have worked on the Quadro.

cd[0].depth = 32;
cd[0].colorFormat = NV_FORMAT_A8R8G8B8;

The documentation provided seems inconsistent with the values punched in here. From nvapi.h

NvU32                   depth;             //!< Source surface color depth."0" means all 8/16/32bpp
NV_FORMAT               colorFormat;       //!< Color format (optional)

I should be able to have depth set to 0 (which I presume to be auto) and the color format is stated to be optional.

1 Like

Did a little bit more digging on the Tesla side of things -

This seems to work

timing.type = NV_TIMING_OVERRIDE_CVT_RB;

This seems to fail

timing.type = NV_TIMING_OVERRIDE_AUTO;
1 Like

Hi, First of all, thanks for the post. I am working on the same API too. But I am getting strange problems. Time to time NvAPI_DISP_TryCustomDisplay getting API Error. A few seconds later it works.

Also, this API couldn’t change the resolution to 4K or any custom resolution higher than 2K.

Do you have any idea about that?

Thanks for your help. I hope you are still checking this post too :)