概要
オンボードグラフィックスとディスクリート GPU を両方積んでいるような状況、たとえば典型的にはグラボを積んだラップトップなどにおいて、通常はオンボードのグラフィックスを利用し、ゲーム等の特別に重い処理のみディスクリート GPU に任せる、 GPU オフロードという技術がある。
従来、 nvidia の GPU をプロプライエタリのドライバで利用する場合、 GPU オフロードには bumblebee や primus などを使う必要があった。
また、 bumblebee や primus は OpenGL 用のものであり、 Vulkan で GPU オフロードするにはまた別の実装が必要であった。
しかし、 nvidia-drivers 435 あたりからはプロプライエタリドライバに PRIME render offload の対応が入り、 bumblebee なしで OpenGL や Vulkan の GPU オフロードができるようになった。
以下では、この新機能を gentoo で利用する手順を説明する。
この情報は 2019-10-17 時点のものであり、現時点または将来に渡る安定した動作は保証しないことに留意せよ。
(まあそもそも nvidia-drivers 自体が安定していないという話はある🙄)
追記 2019-12-06: libglvnd
USE flag と media-libs/libglvnd-1.3.0 の mask が解除されたため、以下の手順の大半は不要になった。
現時点で (これからも) 必要な手順は以下の通り:
-
libglvnd
USE flag を通常の手順で有効化する (と同時に x11-drivers/nvidia-drivers の関連するフラグも設定する)- もはや profile/package.use.mask の編集は不要
-
>=x11-base/xorg-server-1.20.6
と>=media-libs/libglvnd-1.3.0
と>=x11-drivers/nvidia-drivers-435.21
を emerge する- もはや package.unmask の編集は不要
- パッチ適用も不要
(追記終わり)
環境
- Gentoo Linux (amd64)
-
x11-base/xorg-server-1.20.5
- 今のところ入手できるパッチが 1.20.5 用なので、 1.20.6 などが出たときはまた手を加える必要があるかもしれない (たぶん次は 1.21 だと思うけど)。
-
x11-drivers/nvidia-drivers-435.21
- 430.50 だとたぶん無理。試してないけど。
- 435.21 だと bumblebee や primus が (少なくとも私の環境では) 正常に動作しないようなので、 bumblebee を使うつもりならしばらくは 430.50 を使い続けた方がよさそう。
未リリースのソフトウェアやパッチが必要になりそうなので、 gentoo amd64 以外の環境でどうなるか (いつごろ利用可能になるか、あるいは既に可能か) は知らない。
手順
1. 関連機能を unmask し有効化する
portage の設定を編集
まず libglvnd
USE flag が mask されているため、これを unmask し、かつ有効化する。
>=media-libs/mesa-19.2.1 -libglvnd
>=x11-base/xorg-server-1.20.5 -libglvnd
>=x11-drivers/nvidia-drivers-435.21 -libglvnd
また、 PRIME render offload には kernel modesetting を使うため、 kms
フラグも同時に有効化する。
compat
フラグを有効化してしまうと non-GLVND の libGL がインストールされてしまうため、これは無効化すること。
# Proprietary nvidia-drivers require glvnd for PRIME render offloading.
# See <http://us.download.nvidia.com/XFree86/Linux-x86_64/435.21/README/primerenderoffload.html>
# and <https://bugs.gentoo.org/692206>.
>=media-libs/mesa-19.2.1 libglvnd
>=x11-base/xorg-server-1.20.5 libglvnd
>=x11-drivers/nvidia-drivers-435.21 libglvnd -compat
>=x11-drivers/nvidia-drivers-435.21 kms
また、 media-libs/libglvnd も mask されているため、これも unmask する。
# See <https://bugs.gentoo.org/692206>.
# 将来的に標準で unmask されたら、この行は削除すべし
<media-libs/libglvnd-9999
2. X サーバにパッチを当ててリビルド
更新 (2019-11-23): x11-base/xorg-server-1.20.6 がリリースされ、これに以下で必要なコードは全て入っている。
そのため、 1.20.6 以上をインストールするならパッチを導入する工程は不要。
パッチを当てる
https://bugs.gentoo.org/692206#c30 の人が必要な変更を抽出してくれているので、これを xorg-server-1.20.5 に当てる。
https://github.com/LuoJinghua/gentoo-overlay/tree/master/x11-base/xorg-server/files にある xorg-server-1.21-*.patch
のような名前のパッチ計6つを /etc/portage/patches/x11-base/xorg-server-1.20.5
に配置する。
$ ls /etc/portage/patches/x11-base/xorg-server-1.20.5/ | cat
xorg-server-1.21-autobind-gpu.patch
xorg-server-1.21-multigpu-00-7f962c70.patch
xorg-server-1.21-multigpu-01-37a36a6b.patch
xorg-server-1.21-multigpu-02-8b67ec7c.patch
xorg-server-1.21-multigpu-03-56c0a71f.patch
xorg-server-1.21-multigpu-04-b4231d69.patch
emerge
ビルドする。
xorg-server だけでなく、 USE flag を変更した他のパッケージもリビルドを忘れないこと。
$ sudo emerge -1uv mesa xorg-server nvidia-drivers
この手順はうどんワールドでも何でもいい。
とにかく更新した use flag が反映されていればおk。
また、ビルド時にパッチが当たっていることも念のため確認しておいた方がいい。
$ sudo emerge -1v xorg-server
These are the packages that would be merged, in order:
Calculating dependencies... done!
[ebuild R ] x11-base/xorg-server-1.20.5:0/1.20.5::gentoo USE="glamor ipv6 libglvnd suid systemd udev wayland xorg -debug -dmx -doc (-elogind
) -kdrive -libressl -minimal (-selinux) -static-libs -unwind -xcsecurity -xephyr -xnest -xvfb" 0 KiB
Total: 1 package (1 reinstall), Size of downloads: 0 KiB
>>> Verifying ebuild manifests
>>> Emerging (1 of 1) x11-base/xorg-server-1.20.5::gentoo
* xorg-server-1.20.5.tar.bz2 BLAKE2B SHA512 size ;-) ... [ ok ]
>>> Unpacking source...
>>> Unpacking xorg-server-1.20.5.tar.bz2 to /var/tmp/portage_tmpfs/portage/x11-base/xorg-server-1.20.5/work
>>> Source unpacked in /var/tmp/portage_tmpfs/portage/x11-base/xorg-server-1.20.5/work
>>> Preparing source in /var/tmp/portage_tmpfs/portage/x11-base/xorg-server-1.20.5/work/xorg-server-1.20.5 ...
* Applying xorg-server-1.20.4-shm-reindent-shm_tmpfile-to-follow-our-standards.patch ... [ ok ]
* Applying xorg-server-1.20.4-shm-Pick-the-shm-dir-at-run-time-not-build-time.patch ... [ ok ]
* Applying xorg-server-1.20.4-shm-Use-memfd_create-when-possible.patch ... [ ok ]
* Applying xorg-server-1.12-unloadsubmodule.patch ... [ ok ]
* Applying xorg-server-1.18-support-multiple-Files-sections.patch ... [ ok ]
* Applying xorg-server-1.21-autobind-gpu.patch ... [ ok ]
* Applying xorg-server-1.21-multigpu-00-7f962c70.patch ... [ ok ]
* Applying xorg-server-1.21-multigpu-01-37a36a6b.patch ... [ ok ]
* Applying xorg-server-1.21-multigpu-02-8b67ec7c.patch ... [ ok ]
* Applying xorg-server-1.21-multigpu-03-56c0a71f.patch ... [ ok ]
* Applying xorg-server-1.21-multigpu-04-b4231d69.patch ... [ ok ]
* User patches applied.
(後略)
3. Xorg の設定
# See <http://us.download.nvidia.com/XFree86/Linux-x86_64/435.21/README/primerenderoffload.html>.
Section "ServerLayout"
Identifier "layout"
Option "AllowNVIDIAGPUScreens"
EndSection
4. 再起動と確認
再起動したのち X を起動し、以下のことを確認する。
全てで問題がなければ、 PRIME render offload が利用可能のはずである。
glxinfo
$ __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia glxinfo | grep vendor
server glx vendor string: NVIDIA Corporation
client glx vendor string: NVIDIA Corporation
OpenGL vendor string: NVIDIA Corporation
ベンダーが NVIDIA Corporation
になっていればおk。
$ __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia glxinfo | grep vendor
X Error of failed request: BadValue (integer parameter out of range for operation)
(後略)
BadValue (integer parameter out of range for operation)
などと言われた場合、おそらく x11-drivers/nvidia-drivers
の kms
USE flag が有効化されていない。
xrandr
$ xrandr --listproviders | grep NVIDIA
Provider 1: id: 0x1b8 cap: 0x0 crtcs: 0 outputs: 0 associated providers: 0 name:NVIDIA-G0
name:NVIDIA-G0
のような provider が含まれていればおk。
X のログ
$ grep 'NVIDIA(G0)' /var/log/Xorg.0.log | head -1
[ 23.123] (==) NVIDIA(G0): Depth 24, (==) framebuffer bpp 32
NVIDIA(G0)
のような行が含まれていればおk。
$ grep PRIME /var/log/Xorg.0.log
[ 23.161] (II) NVIDIA: The X server supports PRIME Render Offload.
The X server supports PRIME Render Offload.
という行が含まれていればおk。
もし "The X server does not supports ..." (強調は筆者) となっていたら、 X サーバ側に必要なパッチが当たっていない。
(参考: PRIME offload not working - NVIDIA Developer Forums)
利用方法
基本的には Chapter 35. PRIME Render Offload で紹介されている通り。
OpenGL (GLX) のアプリケーションなら、環境変数2つを __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia
のように設定する。
$ glxinfo | grep vendor
server glx vendor string: SGI
client glx vendor string: Mesa Project and SGI
OpenGL vendor string: Intel Open Source Technology Center
$ __NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia glxinfo | grep vendor
server glx vendor string: NVIDIA Corporation
client glx vendor string: NVIDIA Corporation
OpenGL vendor string: NVIDIA Corporation
$
EGL や Vulkan なら、環境変数は __NV_PRIME_RENDER_OFFLOAD=1
だけで良い。
$ __NV_PRIME_RENDER_OFFLOAD=1 vkcube
(キューブが回転する)
(vkcube は dev-util/vulkan-tools
で cube
USE フラグを有効化するとインストールできる。)
Vulkan アプリケーションで __GLX_VENDOR_LIBRARY_NAME=nvidia
を付けていても特に問題は見られないので、必要かわからない場合はとりあえず両方とも付けておけばよさそう。
もし上のようなコマンドが失敗したり vkcube がクラッシュするようなら、 x11-drivers/nvidia-drivers
の compat
USE フラグがちゃんと無効化されているか確認すること。
これが有効のままだと、 libpthread あたりでクラッシュして coredump する。
他の話題
EGL
OpenGL は GLX のみの対応で、 EGL は今のところ (435.21) 未対応っぽい。
NVIDIA's EGL implementation does not yet support PRIME render offload.
―― http://us.download.nvidia.com/XFree86/Linux-x86_64/435.21/README/primerenderoffload.html
更新 2019-11-22: EGL 対応
440.31 のドキュメントを確認したところ、 EGL にも対応した模様。
EGL を使う場合にも、 __NV_PRIME_RENDER_OFFLOAD=1
のみの設定でオフロードできるらしい。
To configure a graphics application to be offloaded to the NVIDIA GPU screen, set the environment variable
__NV_PRIME_RENDER_OFFLOAD
to1
. If the graphics application uses Vulkan or EGL, that should be all that is needed.
確認してみよう。
$ __NV_PRIME_RENDER_OFFLOAD=1 eglinfo | grep -A 2 'platform:'
GBM platform:
EGL API version: 1.4
EGL vendor string: Mesa Project
--
Wayland platform:
eglinfo: eglInitialize failed
X11 platform:
EGL API version: 1.5
EGL vendor string: NVIDIA
--
Device platform:
EGL API version: 1.5
EGL vendor string: NVIDIA
$ eglinfo | grep -A 2 'platform:'
GBM platform:
EGL API version: 1.4
EGL vendor string: Mesa Project
--
Wayland platform:
eglinfo: eglInitialize failed
X11 platform:
EGL API version: 1.4
EGL vendor string: Mesa Project
--
Device platform:
EGL API version: 1.5
EGL vendor string: NVIDIA
DRI_PRIME
PRIME は本来、環境変数 DRI_PRIME=1
で有効化できるはずなのだが、どうもこれが (現状の私の環境だと) 動かないっぽい。
$ DRI_PRIME=1 glxinfo | grep vendor
libGL error: MESA-LOADER: failed to open nouveau (search paths /usr/lib64/dri)
libGL error: failed to load driver: nouveau
server glx vendor string: SGI
client glx vendor string: Mesa Project and SGI
OpenGL vendor string: Intel Open Source Technology Center
$
どこに原因があるのかはわからないが、とにかく動かない。
これが問題になるのは、たとえば lutris のランチャーの "System options" で "Use discrete graphics" などを有効化すると DRI_PRIME=1
でゲームを起動してくれるなどの機能があり、これが意図した通りにディスクリート GPU を使ってくれないということである。
仕方ないので、この場合は同じく "System options" の "Environment variables" から2つの環境変数を手動で設定してやるなどする必要がある。
参考
- Bumblebee (optirun, primusrun) doesn't work with Flatpak · Issue #869 · flatpak/flatpak
- Chapter 35. PRIME Render Offload
- 692206 – [Tracker] Unmasking libglvnd USE flag
- PRIME offload not working - NVIDIA Developer Forums
あとがき: --my-next-gpu-wont-be-nvidia
If the nvidia module is loaded on your system, you are not permitted to file bugs of any sort.
―― https://github.com/swaywm/sway/issues/3039#issuecomment-434663746