Ubuntu – What *exactly* does “Launch using dedicated graphics card” do

driversgraphics

There are a number of questions regarding the "Launch using dedicated graphics card" option in Ubuntu: this one, this one, or this one, for example. But none of them are asking the question I really want to know.

I want to understand what this option does, especially in the context of my system: the motherboard has integrated Intel graphics and an Nvidia Graphics card. I have three monitors attached to the ports on the Nvidia card and nothing attached to the onboard graphics.

When I see "Launch using dedicated graphics card", I imagine something like this: the desktop is running on (using the hardware of and being rendered in the memory of) the integrated graphics and the contents of this window I've just opened with this option are running on the other graphics card and somehow the output is piped through the integrated graphics (kind of like "picture-in-picture"?).

But given that I'm not using the onboard graphics at all, aren't my applications already running on the dedicated graphics card?

I suspect that my understanding of this option is wrong. Can anyone clarify what this option does?

Best Answer

I had the exact same question, none of the valiables like __GLX_VENDOR_LIBRARY_NAME=nvidia, __NV_PRIME_RENDER_OFFLOAD=1, __VK_LAYER_NV_optimus=NVIDIA_only, DRI_PRIME=1 produced the same result.

I even tried to search in gnome-shell source code but the functions aren't in gnome-shell repo.

I finally ACCIDENTALLY stumbled upon switechroo-controls package,

I tried switcherooctl launch <command> which replicates the gnome shell behaviour. Then I had an epiphany to search for switcheroo in gnome-shell repo.

❯ grep -ri 'switcheroo' 
Binary file .git/index matches
data/dbus-interfaces/net.hadess.SwitcherooControl.xml:      net.hadess.SwitcherooControl:
data/dbus-interfaces/net.hadess.SwitcherooControl.xml:      check the value of net.hadess.SwitcherooControl.HasDualGpu to see
data/dbus-interfaces/net.hadess.SwitcherooControl.xml:      The object path will be "/net/hadess/SwitcherooControl".
data/dbus-interfaces/net.hadess.SwitcherooControl.xml:  <interface name="net.hadess.SwitcherooControl">
js/ui/appDisplay.js:        this._switcherooNotifyId = global.connect('notify::switcheroo-control',
js/ui/appDisplay.js:        this._switcherooProxy = global.get_switcheroo_control();
js/ui/appDisplay.js:        if (this._switcherooProxy) {
js/ui/appDisplay.js:            let prop = this._switcherooProxy.get_cached_property('HasDualGpu');
src/meson.build:dbus_generated += gnome.gdbus_codegen('switcheroo-control',
src/meson.build:  '../data/dbus-interfaces/net.hadess.SwitcherooControl.xml',
src/shell-app.c:#include "switcheroo-control.h"
src/shell-app.c:  proxy = shell_global_get_switcheroo_control (global);
src/shell-app.c:      g_warning ("Could not apply discrete GPU environment, switcheroo-control not available");
src/shell-app.c:  variant = shell_net_hadess_switcheroo_control_get_gpus (SHELL_NET_HADESS_SWITCHEROO_CONTROL (proxy));
src/shell-app.c:  g_debug ("Could not find discrete GPU in switcheroo-control, not applying environment");
src/shell-global.c:#include "switcheroo-control.h"
src/shell-global.c:  GDBusProxy *switcheroo_control;
src/shell-global.c:  GCancellable *switcheroo_cancellable;
src/shell-global.c:  PROP_SWITCHEROO_CONTROL,
src/shell-global.c:got_switcheroo_control_gpus_property_cb (GObject      *source_object,
src/shell-global.c:        g_debug ("Could not get GPUs property from switcheroo-control: %s", error->message);
src/shell-global.c:  g_dbus_proxy_set_cached_property (global->switcheroo_control, "GPUs", gpus);
src/shell-global.c:  g_object_notify (G_OBJECT (global), "switcheroo-control");
src/shell-global.c:switcheroo_control_ready_cb (GObject      *source_object,
src/shell-global.c:  ShellNetHadessSwitcherooControl *control;
src/shell-global.c:  control = shell_net_hadess_switcheroo_control_proxy_new_for_bus_finish (res, &error);
src/shell-global.c:        g_debug ("Could not get switcheroo-control GDBusProxy: %s", error->message);
src/shell-global.c:  global->switcheroo_control = G_DBUS_PROXY (control);
src/shell-global.c:  g_debug ("Got switcheroo-control proxy successfully");
src/shell-global.c:  cached_props = g_dbus_proxy_get_cached_property_names (global->switcheroo_control);
src/shell-global.c:      g_object_notify (G_OBJECT (global), "switcheroo-control");
src/shell-global.c:  g_dbus_connection_call (g_dbus_proxy_get_connection (global->switcheroo_control),
src/shell-global.c:                          g_dbus_proxy_get_name (global->switcheroo_control),
src/shell-global.c:                          g_dbus_proxy_get_object_path (global->switcheroo_control),
src/shell-global.c:                                         g_dbus_proxy_get_interface_name (global->switcheroo_control),
src/shell-global.c:                          global->switcheroo_cancellable,
src/shell-global.c:                          got_switcheroo_control_gpus_property_cb,
src/shell-global.c:    case PROP_SWITCHEROO_CONTROL:
src/shell-global.c:      g_value_set_object (value, global->switcheroo_control);
src/shell-global.c:switcheroo_appeared_cb (GDBusConnection *connection,
src/shell-global.c:  g_debug ("switcheroo-control appeared");
src/shell-global.c:  shell_net_hadess_switcheroo_control_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
src/shell-global.c:                                                         "net.hadess.SwitcherooControl",
src/shell-global.c:                                                         "/net/hadess/SwitcherooControl",
src/shell-global.c:                                                         global->switcheroo_cancellable,
src/shell-global.c:                                                         switcheroo_control_ready_cb,
src/shell-global.c:switcheroo_vanished_cb (GDBusConnection *connection,
src/shell-global.c:  g_debug ("switcheroo-control vanished");
src/shell-global.c:  g_clear_object (&global->switcheroo_control);
src/shell-global.c:  g_object_notify (G_OBJECT (global), "switcheroo-control");
src/shell-global.c:  global->switcheroo_cancellable = g_cancellable_new ();
src/shell-global.c:                    "net.hadess.SwitcherooControl",
src/shell-global.c:                    switcheroo_appeared_cb,
src/shell-global.c:                    switcheroo_vanished_cb,
src/shell-global.c:  g_cancellable_cancel (global->switcheroo_cancellable);
src/shell-global.c:  g_clear_object (&global->switcheroo_cancellable);
src/shell-global.c:                                   PROP_SWITCHEROO_CONTROL,
src/shell-global.c:                                   g_param_spec_object ("switcheroo-control",
src/shell-global.c:                                                        "switcheroo-control",
src/shell-global.c:                                                        "D-Bus Proxy for switcheroo-control daemon",
src/shell-global.c: * shell_global_get_switcheroo_control:
src/shell-global.c: * Get the global #GDBusProxy instance for the switcheroo-control
src/shell-global.c:shell_global_get_switcheroo_control (ShellGlobal  *global)
src/shell-global.c:  return global->switcheroo_control;
src/shell-global.h:         shell_global_get_switcheroo_control    (ShellGlobal  *global);

Which confirms it, more intuitive proof (I am a fedora user): screenshot of terminal


TLDR

In answer to your exact question: Gnome does it by using a library switcheroo-control.

Practical answer: you can do the same thing with switcherooctl launch <command>


EDIT: I am not sure if the command works on ubuntu, but debian and ubuntu repositories have the package switcheroo-control.

This is the tree of extracted switcheroo-control package (deb).

.
├── etc
│   └── dbus-1
│       └── system.d
│           └── net.hadess.SwitcherooControl.conf
├── lib
│   ├── systemd
│   │   └── system
│   │       └── switcheroo-control.service
│   └── udev
│       └── hwdb.d
│           └── 30-pci-intel-gpu.hwdb
└── usr
    ├── libexec
    │   └── switcheroo-control
    └── share
        └── doc
            └── switcheroo-control
                ├── changelog.Debian.gz
                ├── copyright
                ├── NEWS.gz
                └── README.md

Edit: Ok I found the problem, when setting the variable if you set like VAR=value, this is a regular variable, while export VAR=value makes it accessible to subprocesses (REF)

after this,any one of the variables work for me,export __GLX_VENDOR_LIBRARY_NAME=nvidia,export __NV_PRIME_RENDER_OFFLOAD=1,export __VK_LAYER_NV_optimus=NVIDIA_only,export DRI_PRIME=1 (they have their own different functions)

so use switchrootctl launch <command> or, export above variables and launch the process. you can even create a alias

Ex:

alias dgpu="export __GLX_VENDOR_LIBRARY_NAME=nvidia && export __NV_PRIME_RENDER_OFFLOAD=1 &&"

and then dgpu <command>

this is the environment variables set by switchroot-control (in my case). enter image description here

Related Question