feat(termux): glibc 构建自动启用自编 Mesa 26 turnip ICD(GPU 打通)
- app/boot/termux_gpu:glibc 构建 + Termux 且随附 ICD 存在时,在探测前设 VK_ICD_FILENAMES/VK_DRIVER_FILES;用户显式设置不覆盖 - 文档:Mesa 26.2.6 + KGSL 的完整构建/安装/验证步骤(含 shebang、 --wrap-mode=nofallback、C++/链接参数三处坑) - 实测:wgpu 选中 Adreno 840(turnip Mesa 26.2.6),截图首帧 61 ms - README.termux:GPU 标 ✅,MC 标 🟡(glibc JRE+AWT 已验证,GLX 待 GL 构建)
This commit is contained in:
1 parent
aaba339499
commit
64fe489a04
4 files changed
+118
-32
No files matched your search
+8
-8
@@ -14,8 +14,8 @@
|
||||
| 横屏适配 | ✅ | 默认窗口按 X 屏幕等比自适应(`source=termux-screen`) |
|
||||
| Java 发现 | ✅ | `JAVA_HOME`/PATH + `$PREFIX/lib/jvm` 扫描 |
|
||||
| Java 自动安装 | ✅ | `ull java install 17` 由内置镜像装完 openjdk-17(约 20 s) |
|
||||
| GPU(wgpu) | ⛔ | glibc 侧 Mesa 24.2.6 不支持 Adreno 840;Arch 26.2.6 缺 KGSL。CPU 渲染可用 |
|
||||
| Minecraft 运行 | ⏳ | 无官方 Android natives;计划走 glibc JVM(见下) |
|
||||
| GPU(wgpu) | ✅ | 自编 Mesa 26.2.6 + KGSL;wgpu 选中 Adreno 840(Vulkan/turnip) |
|
||||
| Minecraft 运行 | 🟡 | glibc JRE(Temurin 21.0.13)可跑,AWT/X11 正常;GLX 待 Mesa 26 GL 构建 |
|
||||
|
||||
## 快速开始
|
||||
|
||||
@@ -34,17 +34,17 @@ DISPLAY=:0 ./unlucky-launcher-iced --software-renderer
|
||||
## 已知边界
|
||||
|
||||
- 仅单机(OnePlus 15 / Android 17)验证,试验级、不在发布矩阵内。
|
||||
- **GPU**:bionic 侧 zink/turnip 可用;glibc 侧被驱动挡住——Termux 的 glibc Mesa 24.2.6
|
||||
不认识 Adreno 840,Arch 的 26.2.6 是 Linux/DRM 构建、缺 KGSL。需要 Mesa 26+ 的
|
||||
glibc+KGSL 构建;在那之前用 CPU(tiny-skia)。GPU 变体会自动降级,不会崩。
|
||||
- **GPU**:已打通,但驱动是自编的(Mesa 26.2.6 + KGSL),装到
|
||||
`$PREFIX/glibc/{lib,share/vulkan/icd.d}` 后应用会自动启用;Termux 官方源里的
|
||||
glibc Mesa 太旧(24.2.6 不认识 Adreno 840)。驱动缺失时自动降级 CPU,不会崩。
|
||||
- **MC**:Android 原生 natives 走不通(LWJGL 没有官方 Android/bionic 产物,且 GLFW 的
|
||||
窗口模型与 termux-x11 的 X11 不兼容)。可行路线是 glibc JVM(Temurin linux-aarch64 +
|
||||
glibc Mesa),让 MC 的 Linux natives 在 glibc 进程里正常加载。
|
||||
glibc Mesa)——JRE 与 AWT/X11 已验证,GLX 还差一份 Mesa 26 的 GL 构建。
|
||||
- Termux 上三条测试失败是环境差异(`/proc/*/children`、长路径脱敏、mtime flaky),
|
||||
PC 的 Linux CI 不受影响。
|
||||
|
||||
## 后续
|
||||
|
||||
1. Mesa 26+ 的 glibc/KGSL 构建(解锁 GPU)
|
||||
2. MC 运行链:glibc JVM(Temurin linux-aarch64 + glibc Mesa);proot 作为备选
|
||||
1. Mesa 26 GLX(zink/softpipe)构建 → MC 的 LWJGL/GLFW 打通
|
||||
2. MC 运行链接线:启动器在 Termux 上改用 glibc JVM(Temurin),bionic java 留给 UI/CLI
|
||||
3. 剪贴板/IME 在 termux-x11 下的行为验证
|
||||
@@ -30,6 +30,7 @@ use super::{MIN_SIZE, WINDOW_SIZE};
|
||||
|
||||
mod diagnostics;
|
||||
mod fallback;
|
||||
mod termux_gpu;
|
||||
mod termux_window;
|
||||
|
||||
use fallback::{on_failure, respawn, OnFailure};
|
||||
@@ -40,6 +41,8 @@ pub(crate) fn run(options: Options) -> iced::Result {
|
||||
let boot_started = Instant::now();
|
||||
|
||||
// ① 探测(判据取在哪、日志在 `report_boot` 里统一打)
|
||||
// Termux + glibc 构建:装了我们自编的 turnip ICD 就先生效,auto 也能选到 GPU。
|
||||
termux_gpu::enable();
|
||||
let boot = boot_probe(&options);
|
||||
let decision = boot.decision;
|
||||
diagnostics::report_boot(&options, &boot.probe, &decision);
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
//! Termux 上自动启用随附的 Vulkan ICD(glibc 侧 turnip,`ull_freedreno.json`)。
|
||||
//!
|
||||
//! 背景:Termux 软件源里的 glibc Mesa(24.2.6)不认识 Adreno 840,硬件 GPU 需要用
|
||||
//! `packaging/docs/termux-glibc-build.md` §5 里自编的 Mesa 26(KGSL)。驱动装在
|
||||
//! `$PREFIX/glibc/share/vulkan/icd.d/ull_freedreno.json` 时,这里在探测之前把它设进
|
||||
//! `VK_ICD_FILENAMES` / `VK_DRIVER_FILES`,让 `auto` 也能选到 GPU。
|
||||
//!
|
||||
//! 只在 **glibc 构建**(`target_os = "linux"`)上生效:Termux 原生(bionic)构建的
|
||||
//! `target_os = "android"`,glibc 驱动对它没有意义。用户显式设了这两个变量时不覆盖。
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use unlucky_core::platform::paths::ProcessEnv;
|
||||
use unlucky_core::platform::termux;
|
||||
|
||||
/// 随附 ICD 的相对路径(相对 `$PREFIX`)。
|
||||
const ICD_REL: &str = "glibc/share/vulkan/icd.d/ull_freedreno.json";
|
||||
|
||||
/// 在 GPU 探测之前调用:装了就启用,没装就什么都不做。
|
||||
pub(super) fn enable() {
|
||||
if !cfg!(target_os = "linux") {
|
||||
return;
|
||||
}
|
||||
if std::env::var_os("VK_ICD_FILENAMES").is_some()
|
||||
|| std::env::var_os("VK_DRIVER_FILES").is_some()
|
||||
{
|
||||
return;
|
||||
}
|
||||
let Some(prefix) = termux::prefix(&ProcessEnv) else {
|
||||
return;
|
||||
};
|
||||
let icd = icd_path(&prefix);
|
||||
if icd.is_file() {
|
||||
std::env::set_var("VK_ICD_FILENAMES", &icd);
|
||||
std::env::set_var("VK_DRIVER_FILES", &icd);
|
||||
}
|
||||
}
|
||||
|
||||
/// `$PREFIX` 下随附 ICD 的路径(纯函数,测试用)。
|
||||
fn icd_path(prefix: &Path) -> PathBuf {
|
||||
prefix.join(ICD_REL)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::icd_path;
|
||||
|
||||
#[test]
|
||||
fn icd_path_is_under_the_glibc_prefix() {
|
||||
let path = icd_path(std::path::Path::new("/data/data/com.termux/files/usr"));
|
||||
assert_eq!(
|
||||
path,
|
||||
std::path::PathBuf::from(
|
||||
"/data/data/com.termux/files/usr/glibc/share/vulkan/icd.d/ull_freedreno.json"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -169,37 +169,62 @@ DISPLAY=:0 .gnu/target/release/unlucky-launcher-iced \
|
||||
- 已实测:`ull java install 17` 从 SAU 镜像装完 `openjdk-17`(含 `openjdk-17-x`),
|
||||
约 20 秒;`ull java list` 随后列出 `[system]` 的 17。
|
||||
|
||||
## 5. GPU(已排查,当前被驱动挡在 glibc 侧)
|
||||
## 5. GPU(已打通:自编 Mesa 26.2.6 + KGSL)
|
||||
|
||||
termux-x11 的 X 客户端**可以**走硬件:本机 bionic 栈实测
|
||||
`glxinfo -B` → `zink Vulkan 1.4 (Adreno 840 (MESA_TURNIP))`、`Accelerated: yes`,
|
||||
`vulkaninfo` 中 Adreno 设备带 `VK_KHR_xcb_surface` / `VK_KHR_xlib_surface`。
|
||||
termux-x11 的 X 客户端可以走硬件;glibc 侧的问题在**驱动**,不在 loader:
|
||||
|
||||
glibc 侧已把链路搭好并实测到具体阻塞点:
|
||||
1. `vulkan-icd-loader-glibc` + ICD JSON 本身正常。
|
||||
2. Termux 软件源的 glibc Mesa 24.2.6 不认识 Adreno 840
|
||||
(`chip_id = 44050A31 is unsupported`)。
|
||||
3. Arch 的 `vulkan-freedreno 26.2.6` 能加载,但它是 Linux/DRM 构建,缺 KGSL
|
||||
(`/dev/dri` 对 `untrusted_app` 被 SELinux 拒绝)。
|
||||
|
||||
1. **loader 正常**:`vulkan-icd-loader-glibc` + 自写 ICD JSON 能加载 ICD。
|
||||
2. **Termux 的 glibc Mesa 太旧**:`mesa-vulkan-icd-freedreno-glibc` 是 24.2.6(2024),
|
||||
`vulkaninfo` 报 `chip_id = 44050A31, gpu_id = 6860 is unsupported`
|
||||
(Adreno 840 不在该版本的支持表里)。
|
||||
3. **Arch 的新驱动也走不通**:`vulkan-freedreno 26.2.6`(Arch Linux ARM)能加载、
|
||||
但它是 Linux/DRM 构建,找不到设备——Android 的 GPU 走 KGSL,而
|
||||
`/dev/dri` 对 `untrusted_app` 被 SELinux 拒绝(`ls /dev/dri` → Permission denied,
|
||||
设备节点本身是 `crw-rw-rw-`)。
|
||||
|
||||
结论:glibc 侧要用硬件 GPU,需要一个 **Mesa 26+ 的 glibc 构建且带 Android/KGSL 后端**;
|
||||
现有包都缺一半。在那之前用 CPU(tiny-skia)。
|
||||
|
||||
GPU 变体仍可构建并验证降级链:
|
||||
**解法:给 glibc 自编一份带 KGSL 的 Mesa 26.2.6。** 本机实测通过:
|
||||
|
||||
```sh
|
||||
cargo ... build --release -p unlucky-app-iced # 默认 feature,带 wgpu
|
||||
VK_ICD_FILENAMES="$PREFIX/glibc/share/vulkan/icd.d/freedreno_icd.aarch64.json" \
|
||||
VK_DRIVER_FILES="$VK_ICD_FILENAMES" \
|
||||
DISPLAY=:0 .gnu/target/release/unlucky-launcher-iced --renderer=gpu
|
||||
# 1) 源码 + 依赖
|
||||
# mesa-26.2.6.tar.xz(archive.mesa3d.org)
|
||||
# Debian libstdc++-14-dev 的头($G/gnu-support/usr/include/c++/14)
|
||||
# meson / ninja(pip 装 meson)
|
||||
# 2) 把源码里 *.py 的 shebang 从 #!/usr/bin/env python3 改成 Termux python3
|
||||
# (Android 没有 /usr/bin/env)
|
||||
# 3) meson setup(cc-glibc 包装器:-c 不带链接参数、C++ 加 -stdlib=libstdc++、
|
||||
# 共享库链接加 -lstdc++;详见 §3)
|
||||
meson setup build3 --native-file="$G/mesa-native.ini" --wrap-mode=nofallback \
|
||||
-Dbuildtype=release -Dstrip=true -Dplatforms=x11 \
|
||||
-Dvulkan-drivers=freedreno -Dfreedreno-kmds=kgsl \
|
||||
-Dgallium-drivers=zink,softpipe -Dglx=dri -Dopengl=true -Degl=enabled \
|
||||
-Dgles1=disabled -Dgles2=enabled -Dllvm=disabled -Dgbm=disabled \
|
||||
-Dvideo-codecs= -Dzstd=enabled -Dbuild-tests=false
|
||||
ninja -C build3
|
||||
```
|
||||
|
||||
没有可用驱动时它会打印具名错误并**自动降级**到 tiny-skia(同一进程不能重建事件循环,
|
||||
降级走 respawn),所以 GPU 变体在只有 CPU 的环境里也能跑。
|
||||
`--wrap-mode=nofallback` 是为了跳过 libarchive 子项目(它只被 freedreno 的 decode 工具需要,
|
||||
且它自带的 `id_t` 兜底宏会和 glibc 头冲突)。
|
||||
|
||||
安装与启用:
|
||||
|
||||
```sh
|
||||
cp build3/src/freedreno/vulkan/libvulkan_freedreno.so \
|
||||
"$PREFIX/glibc/lib/libvulkan_freedreno_ull.so"
|
||||
cat > "$PREFIX/glibc/share/vulkan/icd.d/ull_freedreno.json" <<EOF
|
||||
{"ICD":{"api_version":"1.4.335","library_path":"$PREFIX/glibc/lib/libvulkan_freedreno_ull.so"},"file_format_version":"1.0.0"}
|
||||
EOF
|
||||
```
|
||||
|
||||
应用启动时(glibc 构建 + Termux + 该 JSON 存在)会自动把它设进
|
||||
`VK_ICD_FILENAMES` / `VK_DRIVER_FILES`(`app/boot/termux_gpu.rs`);用户显式设了这两个
|
||||
变量时不覆盖。实测日志:
|
||||
|
||||
```text
|
||||
[probe] adapters=1 [Adreno (TM) 840 [IntegratedGpu]] hardware=true :: request=auto -> ICED_BACKEND=wgpu
|
||||
[gpu] Selected: AdapterInfo { name: "Adreno (TM) 840", driver: "turnip Mesa driver",
|
||||
driver_info: "Mesa 26.2.6", backend: Vulkan }
|
||||
[shot] 1657x1067 renderer=wgpu,首帧 61 ms
|
||||
```
|
||||
|
||||
没装驱动/没有 GPU 时仍会打印具名错误并自动降级 tiny-skia(同一进程不能重建事件循环,
|
||||
降级走 respawn),所以 GPU 变体在纯 CPU 环境也能跑。
|
||||
|
||||
## 6. 已知边界
|
||||
|
||||
|
||||
Reference in new issue
Block a user