Let's talk about the mysterious -gpu command line argument

I have seen this mentioned in two places, but is missing from the command line argument documentation. Seems really useful for helping users with laptops with Intel integrated graphics and a dedicated graphics card (nvidia/amd) to choose the correct gpu.

What do the indices mean? How does one correlate index 0 with either the integrated graphics or the dedicated graphics, or something else? Does index 0 always mean the dedicated graphics?

When I enumerate the graphics cards from the OS, sometimes the Intel one comes first and sometimes the dedicated graphics one comes first, depending on the machine. However, when I try to match that enumeration index with gpu X, it doesn’t always seem to choose the right one. It seems backwards sometimes. If you could explain a bit how Unity decides which index corresponds to which gpu I could then automate the choosing.

Thanks.

We use code equivalent to this:

IDXGIAdapter* SelectGPU(IDXGIFactory* factory, int gpuIndex)
{
    ComPtr<IDXGIAdapter> gpu;
    for (int i = 0; SUCCEEDED(factory->EnumAdapters(i, &gpu)); ++i)
    {
        if (i == gpuIndex)
            break;
    }
    return gpu;
}

Interesting, so this is how you are enumerating the graphics cards, which is different from what I am doing to enumerate them. (Windows IEnumWbemClassObject and Win32_VideoController queries). I’m trying to understand how to use this. So, I could enumerate them all, and look at their descriptions, and decide based on a string which index I want to pass as a parameter? Or can I myself force the choice in my unity app?

Can you explain, does index 0 always seem to correspond to the dedicated graphics card? In my testing of 5 different machines so far, index 0 seems to be the nvidia/amd card, just using the -gpu 0 parameter… Or is this purely coincidental?

Yes, as long as you do it in the same process, the order will be identical.

It’s complicated :). Generally, the order depends on the graphics driver. Normally, index 0 will be the GPU that’s connected to your primary monitor. On desktop computers, this is usually the dedicated GPU. On laptops, this is integrated GPU.

However, you can hint the driver which GPU you want by exporting special variables from your executable (Unity does this. You can find the code at <EDITOR_INSTALL_DIR>\Data\PlaybackEngines\WindowsStandaloneSupport\Source\WindowsPlayer\WindowsPlayer\Main.cpp):

// Hint that the discrete gpu should be enabled on optimus/enduro systems
// NVIDIA docs: http://developer.download.nvidia.com/devzone/devcenter/gamegraphics/files/OptimusRenderingPolicies.pdf
// AMD forum post: http://devgurus.amd.com/thread/169965
extern "C"
{
    __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
    __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
}

In this case, the driver will insert AMD/Nvidia GPU to the beginning of the list.

To complicate matters even further, this can be overridden in graphics driver settings (like Nvidia control panel) to force dedicated or integrated GPU to be added to the beginning of that list.

1 Like

Thanks! With this information I can come up with a solution.

Does this apply to linux as well? Will a global variable of NvOptimusEnablement =1 have the same effect?