Twitter  Facebook  Google+  YouTube  E-Mail  RSS
The One Man MMO Project
The story of a lone developer's quest to build an online world :: MMO programming, design, and industry commentary
Enabling NVidia GPUs on Optimus Laptops
By Robert Basler on 2014-12-03 02:31:40
Homepage: onemanmmo.com email:one at onemanmmo dot com

Up until today I've been exporting NvOptimusEnablement to enable the NVidia card in my laptop (which also has an Intel card for 2D.) For whatever reason, it stopped working mysteriously this week which led to an hour of trying to figure out why it was all of a sudden taking 3 seconds to render each frame (Intel OpenGL is really, really sad.)

inteldoesntwork.png

The first step was to make sure I didn't waste time on this problem again in the future, so I added a popup when an Intel GPU is detected in the OpenGL vendor string like this:

if ( strstr( reinterpret_cast( glGetString( GL_VENDOR ) ), "Intel") != NULL )


The other way to get the NVidia GPU to be selected is to link to NVAPI. If there is no NVidia GPU the library does nothing.

I implemented all of this into one nice little C++ file. Just build it into your project and off you go. And I even put in NvOptimusEnablement for good measure.


#include <windows.h>
#include <sal.h>
#include "nvapi.h"

// Force NVidia Optimus to use NVidia GPU on drivers 302 and later.
// http://developer.download.nvidia.com/devzone/devcenter/gamegraphics/files/OptimusRenderingPolicies.pdf
extern "C" {
_declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
}

namespace Lair
{

// When NvOptimusEnablement fails, maybe this will work, linking NVapi.
class nVidia
{
public:
nVidia( void )
: ret( NvAPI_Initialize() )
{
}
~nVidia()
{
if ( ret == NVAPI_OK )
{
NvAPI_Unload();
}
}
NvAPI_Status ret;
};

// Global, so this gets executed with no other outside code.
nVidia gNvApi;
}

By Robert Basler on 2014-12-03 02:45:15
Homepage: onemanmmo.com email:one at onemanmmo dot com
Wow, did some more testing and even successfully loading NVAPI isn't enough to enable the NVidia card with the 334.75 drivers.
By Robert Basler on 2014-12-03 12:18:32
Homepage: onemanmmo.com email:one at onemanmmo dot com
This seems somewhat heavy-handed given the documentation, but it does work. I had to modify the popup to tell the user to restart The Imperial Realm::Miranda since this doesn't take effect until the next run. Might make this an installer step at some point.

#include <windows.h>
#include <sal.h>
#include "nvapi.h"
#include "NvApiDriverSettings.h"

// Force NVidia Optimus to use NVidia GPU on drivers 302 and later.
// http://developer.download.nvidia.com/devzone/devcenter/gamegraphics/files/OptimusRenderingPolicies.pdf
extern "C" {
_declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
}

namespace Lair
{

// When NvOptimusEnablement fails, we both link NVApi (also supposed to enable it)
// and specifically enable it in the driver settings.
class nVidia
{
public:
nVidia( void )
{
NvAPI_Status status;
// (0) Initialize NVAPI. This must be done first of all
status = NvAPI_Initialize();
if (status != NVAPI_OK)
{
return;
}
// (1) Create the session handle to access driver settings
NvDRSSessionHandle hSession = 0;
status = NvAPI_DRS_CreateSession(&hSession);
if (status != NVAPI_OK)
{
return;
}
// (2) load all the system settings into the session
status = NvAPI_DRS_LoadSettings(hSession);
if (status != NVAPI_OK)
{
return;
}
// (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)
{
return;
}
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;
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)
{
return;
}
status = NvAPI_DRS_SetSetting(hSession, hProfile, &drsSetting2);
if (status != NVAPI_OK)
{
return;
}
status = NvAPI_DRS_SetSetting(hSession, hProfile, &drsSetting3);
if (status != NVAPI_OK)
{
return;
}
// (5) Now we apply (or save) our changes to the system
status = NvAPI_DRS_SaveSettings(hSession);
if (status != NVAPI_OK)
{
return;
}
// (6) We clean up. This is analogous to doing a free()
NvAPI_DRS_DestroySession(hSession);
hSession = 0;
NvAPI_Unload();
}
~nVidia()
{
}
};

// Global, so this gets instantiated with no other outside code.
nVidia gNvApi;

}
By Robert Basler on 2015-04-21 11:36:42
Homepage: onemanmmo.com email:one at onemanmmo dot com
// For AMD Enduro this should do it on 13.35 and later drivers.
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;

New Comment

Cookie Warning

We were unable to retrieve our session cookie from your web browser. If pressing F5 once to reload this page does not get rid of this message, please read this to learn more.

You will not be able to post until you resolve this problem.

Comment (You can use HTML, but please double-check web link URLs and HTML tags!)
Your Name
Homepage (optional, don't include http://)
Email (optional, but automatically spam protected so please do)
What is 5 multiplied by 1? (What's this?)

  Admin Log In



[The Imperial Realm :: Miranda] [Blog] [Gallery] [About]
Terms Of Use & Privacy Policy