I have an OpenGL library written in c++ that is used from a C# application using C++/CLI adapters. My problem is that if the application is used on laptops with Nvidia Optim
If your software fails on Intel, then you won't be able to run it on 50% of the laptops. So I'd suggest fixing this instead.
Than being said, you can perfectly create profiles by code. Just use NvAPI. This code does exactly this, but beware, you probably shouldn't mess with the global profile and create your own instead :
NvAPI_Status status;
// (0) Initialize NVAPI. This must be done first of all
status = NvAPI_Initialize();
if (status != NVAPI_OK)
PrintError(status, __LINE__);
// (1) Create the session handle to access driver settings
NvDRSSessionHandle hSession = 0;
status = NvAPI_DRS_CreateSession(&hSession);
if (status != NVAPI_OK)
PrintError(status, __LINE__);
// (2) load all the system settings into the session
status = NvAPI_DRS_LoadSettings(hSession);
if (status != NVAPI_OK)
PrintError(status, __LINE__);
// (3) Obtain the Base profile. Any setting needs to be inside
// a profile, putting a setting on the Base Profile enforces it
// for all the processes on the system
NvDRSProfileHandle hProfile = 0;
status = NvAPI_DRS_GetBaseProfile(hSession, &hProfile);
if (status != NVAPI_OK)
PrintError(status, __LINE__);
NVDRS_SETTING drsSetting1 = {0};
drsSetting1.version = NVDRS_SETTING_VER;
drsSetting1.settingId = SHIM_MCCOMPAT_ID;
drsSetting1.settingType = NVDRS_DWORD_TYPE;
NVDRS_SETTING drsSetting2 = {0};
drsSetting2.version = NVDRS_SETTING_VER;
drsSetting2.settingId = SHIM_RENDERING_MODE_ID;
drsSetting2.settingType = NVDRS_DWORD_TYPE;
NVDRS_SETTING drsSetting3 = {0};
drsSetting3.version = NVDRS_SETTING_VER;
drsSetting3.settingId = SHIM_RENDERING_OPTIONS_ID;
drsSetting3.settingType = NVDRS_DWORD_TYPE;
if( ForceIntegrated ){
drsSetting1.u32CurrentValue = SHIM_MCCOMPAT_INTEGRATED;
drsSetting2.u32CurrentValue = SHIM_RENDERING_MODE_INTEGRATED;
drsSetting3.u32CurrentValue = SHIM_RENDERING_OPTIONS_DEFAULT_RENDERING_MODE | SHIM_RENDERING_OPTIONS_IGPU_TRANSCODING;
}else{
drsSetting1.u32CurrentValue = SHIM_MCCOMPAT_ENABLE;
drsSetting2.u32CurrentValue = SHIM_RENDERING_MODE_ENABLE;
drsSetting3.u32CurrentValue = SHIM_RENDERING_OPTIONS_DEFAULT_RENDERING_MODE;
}
status = NvAPI_DRS_SetSetting(hSession, hProfile, &drsSetting1);
if (status != NVAPI_OK)
PrintError(status, __LINE__);
status = NvAPI_DRS_SetSetting(hSession, hProfile, &drsSetting2);
if (status != NVAPI_OK)
PrintError(status, __LINE__);
status = NvAPI_DRS_SetSetting(hSession, hProfile, &drsSetting3);
if (status != NVAPI_OK)
PrintError(status, __LINE__);
// (5) Now we apply (or save) our changes to the system
status = NvAPI_DRS_SaveSettings(hSession);
if (status != NVAPI_OK)
PrintError(status, __LINE__);
// (6) We clean up. This is analogous to doing a free()
NvAPI_DRS_DestroySession(hSession);
hSession = 0;
At startup, test if your profile exists. If not, create it (and you'll probably have to restart yourself too). NvAPI is a static lib, and will gracefully return an error code on non-NVIDIA hardware, so you can ship with it safely.
EDIT : Looks like there's an easier way. From GLFW 3 source code :
// Applications exporting this symbol with this value will be automatically
// directed to the high-performance GPU on nVidia Optimus systems
//
GLFWAPI DWORD NvOptimusEnablement = 0x00000001;