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):
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).
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.