Termux以virglrenderer達成GPU 3D硬體加速

🇺🇸 English version

virglrenderer是給QEMU虛擬機用的顯示技術,可給虛擬機提供3D硬體加速。舉例來說:Linux電腦用QEMU跑Android-x86虛擬機,能透過virglrenderer改善虛擬機的3D圖形性能。

透過Termux執行virglrenderer的伺服器,就能在Android手機達到類似效果,雖然目前的圖形效率沒有很高就是了。

至少這樣就可以在Termux的Proot Linux環境看4K60p影片、玩3D遊戲了。

SuperTuxKart, Glxgears

此方案的好處是Proot和Chroot都能用,並且過程比之前編譯Zink的要簡單許多。

用講的太抽象,不如先看看影片所呈現的效果:

  • 測試手機:Sony Xperia 5 II,系統版本Android 12,處理器Snapdragon 865,GPU為Adreno 650,RAM 8GB。

1. 安裝Termux與Termux X11

安裝Termux,並安裝Termux X11套件與其APK。

理論上XSDL或VNC也可以,我個人偏好用Termux X11來顯示圖形環境。

2. 安裝Proot發行版

安裝一個Proot發行版並設定桌面環境。

個人推薦安裝Debian

3. 安裝virglrenderer

註:Termux現有virglrenderer_android套件可以裝,你可以用這個取代手動編譯的virglrenderer。

方案1:安裝virglrenderer Android

virglrenderer-adroid使用的是Android的GLES,適用於大多數Android手機。

  1. 安裝virglrenderer-android
1
pkg install virglrenderer-android
  1. 執行Virgl伺服器:
1
virgl_test_server_android &

方案2:編譯支援Zink的Virglrenderer

Zink是模擬Vulkan的驅動程式,只支援使用Qualcomm Aderno GPU的Android裝置。

註:以下是在Termux編譯,而非proot內部。

  1. 安裝編譯用的套件
1
2
3
4
5
6
7
8
9
pkg install -y x11-repo

pkg install -y clang lld binutils cmake autoconf automake libtool ndk-sysroot ndk-multilib make python git libandroid-shmem-static ninja llvm bison flex libx11 xorgproto libdrm libpixman libxfixes libjpeg-turbo xtrans libxxf86vm xorg-xrandr xorg-font-util xorg-util-macros libxfont2 libxkbfile libpciaccess xcb-util-renderutil xcb-util-image xcb-util-keysyms xcb-util-wm xorg-xkbcomp xkeyboard-config libxdamage libxinerama

pkg install clvk glfw mesa-vulkan-icd-swrast swiftshader vulkan-extension-layer vulkan-extension-layer-static vulkan-headers vulkan-loader vulkan-loader-generic vulkan-tools

pkg install vulkan-loader-android

pip install meson mako
  1. 複製libxshmfence、mesa、libepoxy、virglrenderer的原始碼
1
2
3
4
5
6
mkdir ~/tmp
cd ~/tmp
LD_PRELOAD='' git clone --depth 1 -b libxshmfence-1.3 https://gitlab.freedesktop.org/xorg/lib/libxshmfence.git
LD_PRELOAD='' git clone --depth 1 -b mesa-22.0.5 https://gitlab.freedesktop.org/mesa/mesa.git
LD_PRELOAD='' git clone --depth 1 -b 1.5.10 https://github.com/anholt/libepoxy.git
LD_PRELOAD='' git clone --shallow-since 2022-06-27 https://gitlab.freedesktop.org/virgl/virglrenderer.git
  1. 編譯libxshmfence
1
2
3
4
cd ~/tmp/libxshmfence
./autogen.sh --prefix=$PREFIX --with-shared-memory-dir=$TMPDIR
sed -i s/values.h/limits.h/ ./src/xshmfence_futex.h
make -j8 install CPPFLAGS=-DMAXINT=INT_MAX
  1. 編譯mesa
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
cd ~/tmp/mesa
sed -i '40s+^$+#include "X11/Xlib.h"+' src/egl/main/egldisplay.h
sed -i 's/^import os$/import os, shutil\ndef link(src, dest):\n shutil.copyfile(src, dest)\ndef unlink(src):\n os.remove(src)\nos.link = link\nos.unlink = unlink/' bin/install_megadrivers.py
mkdir b && cd b
LDFLAGS='-l:libandroid-shmem.a -llog' meson .. -Dprefix=$PREFIX -Dplatforms=x11 -Dgbm=enabled -Ddri-drivers='' -Dgallium-drivers=zink,swrast -Dllvm=disabled -Dvulkan-drivers='' -Dcpp_rtti=false -Dc_args=-Wno-error=incompatible-function-pointer-types -Dbuildtype=release
rm $PREFIX/lib/libglapi.so*
rm $PREFIX/lib/libGL.so*
rm $PREFIX/lib/libGLES*
rm $PREFIX/lib/libEGL*
rm $PREFIX/lib/libgbm*
ninja install
  1. 編譯libepoxy
1
2
3
4
5
cd ~/tmp/libepoxy
mkdir b && cd b
meson -Dprefix=$PREFIX -Dbuildtype=release -Dglx=yes -Degl=yes -Dtests=false -Dc_args=-U__ANDROID__ ..
rm $PREFIX/lib/libepoxy.so*
ninja install
  1. 編譯virglrenderer
1
2
3
4
5
6
cd ~/tmp/virglrenderer
git checkout -f dd301caf7e05ec9c09634fb7872067542aad89b7~2
sed -i 's+"/tmp+"/data/data/com.termux/files/usr/tmp+' vtest/vtest_protocol.h
mkdir b && cd b
meson -Dbuildtype=release -Dprefix=$PREFIX -Dplatforms=egl ..
ninja install
  1. 欲啟動Virgl伺服器,執行以下指令,這裡會輸出圖形相關的除錯資訊。接著再從螢幕左邊滑進來開第二個終端機執行其他指令。
1
MESA_NO_ERROR=1 MESA_GL_VERSION_OVERRIDE=4.0 GALLIUM_DRIVER=zink virgl_test_server --use-egl-surfaceless &

4. 測試GPU加速成效

Termux本身用於執行virglrenderer的伺服器,但是Termux的應用程式無法直接使用virglrenderer,必須使用proot或chroot才行。

virgl server可能會在Termux更新套件後失效(啟動應用程式看到libEGL warning: DRI2: failed to create dri screen之類的訊息)。如果發生了,就得重新編譯第3節提到的所有套件。

4.1. 在Proot裡使用virgl執行程式

  1. 啟動virgl的伺服器。

  2. 啟動Termux X11 APP。回到Termux,執行Termux X11

1
2
export DISPLAY=:0
termux-x11 :0 &
  1. 從螢幕左邊滑進來,按New Session開啟第二個終端機。以一般帳戶user登入proot-distro,掛載Termux的tmp目錄至Proot-distro,
1
proot-distro login debian --user user --shared-tmp
  1. 啟動XFCE4桌面環境。
1
2
export DISPLAY=:0
dbus-launch --exit-with-session startxfce4 &
  1. 在Termux X11的界面開啟終端機。在執行程式前加入GALLIUM_DRIVER啟用virgl硬體加速,如果不加系統會回復使用CPU算繪的llvmpipe。有些程式加MESA_GL_VERSION_OVERRIDE=4.0會開不起來,需要自行測試。

  2. 例如要執行方塊遊戲Minetest:

1
GALLIUM_DRIVER=virpipe MESA_GL_VERSION_OVERRIDE=4.0 minetest

virpipe下glxgears的FPS相比llvimpipe高出一些。

llvmpipe與virpipe比較,Minetest的FPS從10FPS增長到最多20FPS。

VLC啟用virpipe後4K60p影片也播得動了,但基本上是拼盡全力在算繪,一有程式(例如錄影)跟影片播放器搶資源就會畫面撕裂。

賽車遊戲SueprTuxKart成長最明顯:llvmpipe模式下是幻燈片,有了virpipe後就能正常遊玩了。

Firefox在about:config強制啟用WebGL後,WebGL Aquarium的FPS翻倍。

4.2. 在chroot裡使用virgl執行程式

  1. 設定帶有XFCE4桌面的chroot Ubuntu with XFCE4

  2. 將SELinux設定為Permissive

1
sudo setenforce 0
  1. 啟動Termux X11 APP,返回Termxu,執行:
1
XDG_RUNTIME_DIR=${TMPDIR} termux-x11 :0 -ac &
  1. 將Termux的tmp掛載至chroot的tmp
1
2
export CHROOT_DIR=/data/local/tmp/chrootubuntu
sudo busybox mount --bind $PREFIX/tmp $CHROOT_DIR/tmp
  1. 登入chroot,啟動XFCE4
1
2
3
chmod -R 777 /tmp
export DISPLAY=:0 PULSE_SERVER=tcp:127.0.0.1:4713
dbus-launch --exit-with-session startxfce4 &
  1. 以virgl 啟動應用程式
1
GALLIUM_DRIVER=virpipe MESA_GL_VERSION_OVERRIDE=4.0 minetest

4.3. 執行Windows遊戲

請先安裝Box86 + Wine

在Termux啟動virgl伺服器。

並在執行exe前同樣加上GALLIUM_DRIVER參數,例如:

1
GALLIUM_DRIVER=virpipe MESA_GL_VERSION_OVERRIDE=4.0 box86 wine AIR.exe

virgl能讓部份需要硬體加速的Windows遊戲正常執行,例如Tobyfox製作的《Undertale》

以及Key製作的視覺小說《Air》,需另外安裝日文字體。

參考資料


感謝您的閱讀。歡迎分享Ivon的部落格(ivonblog.com)的文章,引用或轉載請註明文章網址,並遵守創用CC-姓名標示-非商業性-禁止改作 4.0 國際授權條款。如需商業使用請來信告之。

written by human, not by AI

如果本網站文章對您有幫助,歡迎請我喝杯珍珠奶茶。

留言板

點選按鈕,選擇您覺得方便的留言系統。要討論程式碼請用Giscus,匿名討論請用Disqus。

這是Giscus留言板,需要登入Github帳號才能留言。支援markdown語法,方便您張貼程式碼,若要上傳圖片請貼Imgur連結。您的留言會在Github Discussions向所有人公開。

這是Disqus留言板,您可能會看到Disqus投放的廣告。無論有無登入皆可留言。此處留言只有本站參與者看得到。若您選擇以訪客身份匿名留言,就不會收到後續回覆通知。