Forcing hardware accelerated rendering

前端 未结 5 784
迷失自我
迷失自我 2021-01-08 00:58

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

5条回答
  •  北海茫月
    2021-01-08 01:22

    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;
    

提交回复
热议问题