What *exactly* does "Launch using dedicated graphics card" do?

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


I'm not sure it's the only effect, but from what I can find on my laptop it sets the DRI_PRIME environment variable for the process that is started.

In my case to DRI_PRIME=pci-0000_01_00_0

I couldn't really find much info on how exactly this has an effect, but some info can be found here.