-
-
Save rickbrew/10e5c0fa3593ceb6f03766914f43a0c6 to your computer and use it in GitHub Desktop.
NVAPI establish application profile that disables GSync, FXAA, and sharpening
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This goes in the header file, which probably isn't necessary unless you're exporting the function from a DLL | |
__declspec(dllexport) NvAPI_Status (__stdcall EstablishNvApiApplicationProfile)( | |
const wchar_t* wszProfileName, // "Paint.NET" | |
const wchar_t* wszAppName, // EXE file path, or Package Family Name | |
const wchar_t* wszUserFriendlyName // EXE file name, or Package Family Name | |
); | |
// CPP file | |
#include "nvapi/nvapi.h" | |
#include "nvapi/NvApiDriverSettings.h" | |
#pragma comment(lib, "nvapi64.lib") | |
static void SetNVUString(NvAPI_UnicodeString& nvStr, const wchar_t* wcStr) | |
{ | |
memset(nvStr, 0, sizeof(NvU16) * NVAPI_UNICODE_STRING_MAX); | |
wcscpy_s(reinterpret_cast<wchar_t*>(nvStr), NVAPI_UNICODE_STRING_MAX, wcStr); | |
} | |
static NvAPI_Status SetSimpleNvDRSSetting( | |
NvDRSSessionHandle hSession, | |
NvDRSProfileHandle hProfile, | |
NvU32 settingId, | |
NVDRS_SETTING_TYPE settingType, | |
NvU32 u32CurrentValue) | |
{ | |
NVDRS_SETTING nvSetting = { 0 }; | |
nvSetting.version = NVDRS_SETTING_VER; | |
nvSetting.settingId = settingId; | |
nvSetting.settingType = settingType; | |
nvSetting.u32CurrentValue = u32CurrentValue; | |
return NvAPI_DRS_SetSetting(hSession, hProfile, &nvSetting); | |
} | |
NvAPI_Status (__stdcall EstablishNvApiApplicationProfile)( | |
const wchar_t* wszProfileName, | |
const wchar_t* wszAppName, | |
const wchar_t* wszUserFriendlyName) | |
{ | |
if (wszProfileName == NULL || wszAppName == NULL || wszUserFriendlyName == NULL) | |
{ | |
return NVAPI_INVALID_POINTER; | |
} | |
NvAPI_Status status = NVAPI_OK; | |
bool initialized = false; | |
if (NV_SUCCEEDED(status)) | |
{ | |
status = NvAPI_Initialize(); | |
if (NV_SUCCEEDED(status)) | |
{ | |
initialized = true; | |
} | |
} | |
NvDRSSessionHandle hSession = 0; | |
if (NV_SUCCEEDED(status)) | |
{ | |
status = NvAPI_DRS_CreateSession(&hSession); | |
} | |
if (NV_SUCCEEDED(status)) | |
{ | |
status = NvAPI_DRS_LoadSettings(hSession); | |
} | |
// Find or create the profile | |
NvDRSProfileHandle hProfile = 0; | |
if (NV_SUCCEEDED(status)) | |
{ | |
NVDRS_APPLICATION nvApplication = { 0 }; | |
nvApplication.version = NVDRS_APPLICATION_VER; | |
NvAPI_UnicodeString nvsAppName; | |
SetNVUString(nvsAppName, wszAppName); | |
// try to look up the profile by appName (path to EXE) | |
status = NvAPI_DRS_FindApplicationByName( | |
hSession, | |
nvsAppName, | |
&hProfile, | |
&nvApplication); | |
if (NV_FAILED(status)) | |
{ | |
NvAPI_UnicodeString nvsProfileName; | |
SetNVUString(nvsProfileName, wszProfileName); | |
// try to look up profile by the profile's name ("Paint.NET") | |
status = NvAPI_DRS_FindProfileByName( | |
hSession, | |
nvsProfileName, | |
&hProfile); | |
if (NV_FAILED(status)) | |
{ | |
NVDRS_PROFILE nvProfile = { 0 }; | |
nvProfile.version = NVDRS_PROFILE_VER; | |
nvProfile.isPredefined = 0; | |
SetNVUString(nvProfile.profileName, wszProfileName); | |
// create a new profile | |
status = NvAPI_DRS_CreateProfile( | |
hSession, | |
&nvProfile, | |
&hProfile); | |
} | |
// add our EXE to whichever profile we've got | |
if (NV_SUCCEEDED(status)) | |
{ | |
NVDRS_APPLICATION nvApplication2 = { 0 }; | |
nvApplication2.version = NVDRS_APPLICATION_VER; | |
nvApplication2.isPredefined = 0; | |
SetNVUString(nvApplication2.appName, wszAppName); | |
SetNVUString(nvApplication2.userFriendlyName, wszUserFriendlyName); | |
SetNVUString(nvApplication2.launcher, L""); | |
SetNVUString(nvApplication2.fileInFolder, L""); | |
status = NvAPI_DRS_CreateApplication( | |
hSession, | |
hProfile, | |
&nvApplication2); | |
} | |
} | |
} | |
// This is out here for easier debugging. Errors while setting individual settings are | |
// ignored in order to avoid derailing the whole process. | |
NvAPI_Status setSettingStatus = NVAPI_OK; | |
// Turn off "image sharpening" in the profile. This setting really messes up how the UI looks. | |
// TODO: did this change in the latest driver versions? removed or renamed? (dec 2020) | |
if (NV_SUCCEEDED(status)) | |
{ | |
setSettingStatus = SetSimpleNvDRSSetting( | |
hSession, | |
hProfile, | |
0x00598928, | |
NVDRS_DWORD_TYPE, | |
0); | |
} | |
// Turn off GSYNC, which doesn't work well for windowed applications | |
// "GSYNC - Application State" set to "Force Off" | |
// In the NVCPL, the "Monitor Technology" setting will then be greyed out and say "Not supported for this application". | |
// This is the same profile that Microsoft Visual Studio uses, and it's a WPF app that would also have problems with | |
// GSYNC. WPA (Windows Performance Analyzer), another WPF app, has the same problems if you don't modify its NVCP settings. | |
if (NV_SUCCEEDED(status)) | |
{ | |
setSettingStatus = SetSimpleNvDRSSetting( | |
hSession, | |
hProfile, | |
VRR_APP_OVERRIDE_ID, | |
NVDRS_DWORD_TYPE, | |
VRR_APP_OVERRIDE_FORCE_OFF); | |
} | |
// Disallow FXAA | |
if (NV_SUCCEEDED(status)) | |
{ | |
setSettingStatus = SetSimpleNvDRSSetting( | |
hSession, | |
hProfile, | |
FXAA_ALLOW_ID, | |
NVDRS_DWORD_TYPE, | |
FXAA_ALLOW_DISALLOWED); | |
} | |
if (NV_SUCCEEDED(status)) | |
{ | |
status = NvAPI_DRS_SaveSettings(hSession); | |
} | |
if (hSession != NULL) | |
{ | |
status = NvAPI_DRS_DestroySession(hSession); | |
hSession = NULL; | |
} | |
if (initialized) | |
{ | |
(void)NvAPI_Unload(); | |
} | |
return status; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment