NVIDIA Optimus

NVIDIA Optimus is a technology that allows an Intel integrated GPU (iGPU) and discrete NVIDIA GPU (dGPU) to be built into and accessed by a laptop. It is also oftenly called as "hybrid graphics", and the main feature is that the iGPU controls all aspects of displaying the video output, while the dGPU is mainly used for computing 3D-intensive sceneries but is not able to perform output on its own.

For many years the only way to get these to work is by using only open source driver. You can choose to use only the iGPU using either "i915" or "modesetting" driver, or you can using both using DRI PRIME, but only if the NVIDIA dGPU is driven by the open source nouveau driver. The nouveau driver however has left a lot of things to be desired, the main problem being its lack of features, lack of performance, and its on-going multi-threading bugs.

NVIDIA proprietary driver would offer a much better performance and experience, however, setting it up was extremely complicated and hacky. Two of the most prominent methods is "Bumblebee" and "vga switcheroo".

All this has changed since 2016. NVIDIA finally found a way to integrate their proprietary driver with the same PRIME method that is used by the open source driver. (It was never a technical problem to do that, the problem was legal: how to do it in a way that satisfy both NVIDIA proprietariness and Linux kernel GPL license). However, back then it was still too early because it required a version of Xorg server which wasn't released yet.

Time has passed and things are a lot more stable now. This documentation will show you how to use proprietary NVIDIA driver with PRIME so you can get maximum performance from you NVIDIA card in an Optimus-equipped laptop.

Before we begin, it is important that with this method, the NVIDIA GPU will be active at all times. It is not possible at this time to dynamically switch the dGPU on or off. This may cause some concern for battery life, so it you do, then you'd better stick with the usual iGPU-only method (or the older and more complicated method like Bumblebee).

This note is meant for Fatdog64 801 onwards. It is possible to do this with Fatdog64 800 but the steps needs to be changed because Fatdog64 800 graphic subsystem does not have the necessary hook to make it work, but you can do that yourself.



Basically there are two steps that you need to do.

First, you need to create an Xorg configuration that will configure NVIDIA with PRIME support.
Then, on the second step, you need to add the scripts that will activate this configuration just before the graphic subsystem starts.



Step 0 - get the NVIDIA driver

The very first thing you have to check is to confirm that your laptop supports Optimus. Older laptops with dual graphics may not support this (they use a configuration where both iGPU and dGPU are capable of displaying the output, and they use a "mux" instead). The method listed here can only work on true Optimus-based laptops, not the older mux-based technologies. Laptops from 2015 onwards usually comes with Optimus instead of mux.

The next thing, is obviously you need to obtain a copy of the NVIDIA driver, either as an installable package, or as an SFS package. The final version of Fatdog64 usually ships with suitable NVIDIA driver, however there are so many variants of NVIDIA graphics card that NVIDIA itself has decided to publish different drivers for each card. You need to review NVIDIA website to verify that your card is indeed supported by the version of the driver that you have on hand. If your card is not supported, then you need to obtain the version that does, or you need to make it yourself (or ask someone else in the forum to make it for you).

If you are adventurous enough, here is one way of doing it.



Step 1 - creating Xorg configuration for Optimus

Traditionally the Xorg configuration is created in /etc/X11/xorg.conf.d/20-gpudriver.conf

You will need to create this file yourself, because xorgwizard does not support it. If you have an existing 20-gpudrive.conf file, you may want to back it up before proceeding.

First, you need to know the Bus ID of your NVIDIA card. You can do this by opening a terminal and then running the command:

lspci | egrep "NVIDIA"

The notice the output you see. For example, in my system it will show:


04:00.0 3D controller: NVIDIA Corporation GK208M [GeForce GT 740M] (rev a1)

The Bus ID is the number 04:00.0. This needs to  be translated into 4:0:0, which is what Xorg wants.

Once done, create the file /etc/X11/xorg.conf.d/20-gpudriver.conf with the following contents:

  Section "Module"
      Load "modesetting"
  EndSection

 Section "Device"     Identifier "nvidia"     Driver "nvidia"     BusID "PCI:4:0:0"     Option "AllowEmptyInitialConfiguration" EndSection

Obviously replace the BusID parameter with your own Bus ID that you found previously.
Congratulations, this step is done!


Update Jan 2020: An alternate  /etc/X11/xorg.conf.d/20-gpudriver.conf which does not require you to find BusID is the following.
Please use this, or the above - but not both!

Section "OutputClass"
    Identifier "intel"
    MatchDriver "i915"
    Driver "modesetting"
EndSection

Section "OutputClass"
    Identifier "nvidia"
    MatchDriver "nvidia-drm"
    Driver "nvidia"
    Option "AllowEmptyInitialConfiguration"
    Option "PrimaryGPU" "yes"
EndSection


Step 2 - creating activation scripts

You will now need to create two files, /etc/X11/xsetup and /etc/X11/xsetup-slim. The contents of these two files are going to be identical, so if you know enough about symlinks, you can even create one file only and symlink the other one to it. But in case you don't know what a symlink is, just create two files with the same content.

You need to put the following contents to both files:

#!/bin/dash
xrandr --setprovideroutputsource modesetting NVIDIA-0
xrandr --auto

After you make these two files, make sure that both of them are executable, by running "chmod +x /etc/X11/xsetup-slim /etc/X11/xsetup".


Fatdog64 800 does not support /etc/X11/xsetup so you will need to edit /etc/X11/xinitrc directly and add this to it.

That's it!





Update Jan 2020: Switchable Hybrid Graphics


Apparently it is now possible to use PRIME offload with the proprietary NVIDIA driver if you have the driver from version 435 onwards.
"modesetting" driver is always supported as the integrated GPU driver, "amdgpu" is supported since 450.57, and "intel" is supported since 455.38

Unfortunately, my hardware only supports drivers up to 418, so I am not able to test and confirm this this.

That being said, the process to do this one is quite simple: basically the same as when setting up PRIME configuration for nouveau driver (or any other open-source Xorg drivers).

Step 1:

Create the following /etc/X11/xorg.conf.d/20-gpudriver.conf snippet:

Section "Device"
  Identifier "iGPU"
  Driver "modesetting"
  #BusID "PCI:0:2:0" # maybe necessary
EndSection

Section "Screen"
  Identifier "iGPU"
  Device "iGPU"
EndSection

Section "Device"
  Identifier "dGPU"
  Driver "nvidia"
  #BusID "PCI:4:0:0" # maybe necessary
  Options "AllowEmptyInitialConfiguration"
EndSection

Step 2:

Run the command

xrandr --setprovideroffloadsink nvidia Intel


Step 3:

Then, for program that you want to use the NVIDIA GPU, export DRI_PRIME=1 before lauching it, like the following:

DRI_PRIME=1 glxinfo | grep "OpenGL renderer"





References:

1. NVIDIA PRIME and PRIME synchronization

2. Arch Linux wiki entry for NVIDIA Optimus

3. NVIDIA Driver README: PRIME render offload