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).
Best Answer
There is a known bug to nvidia settings: Bug #1341140.
If you receive the following error message, you are probably affected by it:
There is a workaround to this bug, also contained in the bug report. Execute the following from a root shell, replacing the 340.24 by the actual driver number. (I yet have to find out what they mean...)
Now the problem should be fixed, according to the bug report.
EDIT: The OP mentioned that he had to alter above commands as follows: