WSL Ubuntu 26.04 下 cc-switch 图形异常与 Mesa D3D12 加速修复记录
文章目录
一、问题背景
之前在 Windows 11 + WSL2 Ubuntu 环境中使用 cc-switch 时,曾遇到过 WSLg / Wayland 下界面异常的问题。
当时采用的方案是通过 alias 强制指定:
1 | SHELL=/bin/sh |
即:
1 | alias cc-switch='env SHELL=/bin/sh GDK_BACKEND=x11 /usr/bin/cc-switch' |
该方案在当时可以有效规避 cc-switch 的部分 GTK / Wayland 兼容性问题。
但在 Ubuntu 26.04 后续升级后,又出现了新的图形环境异常。
这次问题不再单纯是 Wayland / X11 backend 的兼容性问题,而进一步涉及到了 WSLg 下 Mesa OpenGL 的 GPU 加速路径。
最终定位发现:
当前 Ubuntu 26.04 环境中的 Mesa 默认没有正确选择 WSLg 的 D3D12 Gallium Driver,而是回退到了
llvmpipeCPU 软件渲染。
通过显式指定:
1 | GALLIUM_DRIVER=d3d12 |
可以恢复 NVIDIA GPU 的 D3D12 硬件加速,并使 cc-switch 正常启动。
二、环境信息
本次排查环境:
1 | Windows 11 |
开发环境本身长期运行于 WSL2 中,因此不希望为了一个 GUI 程序重装 WSL 或修改大量系统配置。
排查原则是:
先确认 WSLg 基础设施,再检查 GPU 加速链路,最后针对应用做最小范围修复。
三、最初现象
在升级 Ubuntu 软件包后,首先注意到 apt upgrade 尾部出现:
1 | Processing triggers for systemd ... |
同时此前 WSL GUI 应用也存在窗口显示异常,因此首先怀疑:
- systemd 是否异常
- WSLg 是否正常启动
- Wayland socket 是否存在
- GPU 虚拟设备是否正常
- Mesa 是否可以正常使用硬件加速
因此开始逐层排查。
四、首先检查 systemd 和 WSLg
先完整关闭一次 WSL。
在 Windows PowerShell 中执行:
1 | wsl --shutdown |
重新打开 Ubuntu 后检查:
1 | echo "=== PID 1 ===" |
得到:
1 | === PID 1 === |
WSLg 环境:
1 | DISPLAY=:0 |
同时:
1 | /dev/dxg |
正常存在。
Wayland socket 也正常:
1 | /mnt/wslg/runtime-dir/wayland-0 |
因此可以确认:
1 | systemd 正常 |
这时基本可以排除:
“WSLg 根本没有启动”
这一类基础故障。
五、使用 zenity 验证 WSLg GUI
为了进一步排除应用自身的问题,安装一个简单的 GTK GUI 测试程序:
1 | sudo apt install -y zenity |
执行:
1 | zenity --info --text="WSLg test" |
窗口能够正常弹出。
但终端出现:
1 | libEGL warning: failed to get driver name for fd -1 |
这一步非常关键。
因为它说明:
WSLg 的窗口系统本身是正常的,但 Mesa 图形渲染链路存在异常。
也就是说问题开始从:
1 | WSLg / Wayland |
进一步收敛到了:
1 | Mesa / OpenGL / GPU acceleration |
六、检查 Mesa OpenGL 渲染器
安装 Mesa 测试工具:
1 | sudo apt install -y mesa-utils |
首先检查默认状态:
1 | glxinfo -B |
关键输出:
1 | Vendor: Mesa |
问题至此已经非常明显。
虽然:
1 | direct rendering: Yes |
但真正决定是否使用 GPU 的关键字段是:
1 | Accelerated: no |
以及:
1 | OpenGL renderer string: llvmpipe |
llvmpipe 是 Mesa 的 CPU 软件渲染器。
也就是说当前状态实际上是:
1 | Linux GUI |
并没有真正使用 NVIDIA Quadro RTX 4000。
七、强制使用 Mesa D3D12 Gallium Driver
WSLg 的 OpenGL GPU 加速可以通过 Mesa 的 D3D12 Gallium Driver 将 Linux OpenGL 图形调用映射到 Windows Direct3D 12。
因此测试:
1 | GALLIUM_DRIVER=d3d12 glxinfo -B |
结果立刻发生变化:
1 | Vendor: Microsoft Corporation |
OpenGL Renderer:
1 | OpenGL vendor string: Microsoft Corporation |
同时:
1 | Dedicated video memory: 7995 MB |
至此可以确认:
Windows GPU → WSL
/dev/dxg→ D3D12 → Mesa Gallium → OpenGL 的完整硬件加速链路本身是正常的。
真正的问题是:
当前环境下 Mesa 默认没有自动选择
d3d12,而回退到了llvmpipe。
两种状态对比如下:
| 状态 | Renderer | Accelerated |
|---|---|---|
| 默认 | llvmpipe | no |
GALLIUM_DRIVER=d3d12 |
D3D12 (NVIDIA Quadro RTX 4000) | yes |
八、进一步确认 D3D12 相关组件
Mesa D3D12 驱动存在:
1 | ls -l /usr/lib/x86_64-linux-gnu/dri/d3d12_dri.so |
输出:
1 | /usr/lib/x86_64-linux-gnu/dri/d3d12_dri.so |
WSL 提供的 DirectX 相关库也正常存在:
1 | ls -l \ |
均正常。
同时:
1 | ls -l /dev/dxg |
正常存在。
综合这些结果,可以基本排除:
- Windows NVIDIA 驱动完全不可用
- WSL vGPU 不存在
- D3D12 库缺失
- Mesa D3D12 Driver 缺失
九、再次验证 zenity
使用 D3D12 启动:
1 | GALLIUM_DRIVER=d3d12 zenity --info --text="WSLg D3D12 test" |
窗口仍然能够正常显示。
虽然仍然存在:
1 | libEGL warning: failed to get driver name for fd -1 |
但此前最关键的:
1 | MESA: error: ZINK: failed to choose pdev |
已经消失。
结合 glxinfo -B 中:
1 | D3D12 (NVIDIA Quadro RTX 4000) |
可以认为 D3D12 GPU 加速已经正常建立。
剩余的 EGL warning 暂未影响实际 GUI 使用。
十、测试旧版 cc-switch X11 启动方案
之前为了规避 WSLg Wayland 兼容问题,cc-switch 使用:
1 | env GALLIUM_DRIVER=d3d12 SHELL=/bin/sh GDK_BACKEND=x11 cc-switch |
应用可以正常打开,但终端出现:
1 | libEGL warning: DRI3 error: Could not get DRI3 device |
因此当前环境下继续强制:
1 | GDK_BACKEND=x11 |
已经不是最理想的方案。
原来的启动路径大致变成:
1 | cc-switch |
于是进一步尝试:
保留 D3D12 和
/bin/sh,取消强制 X11,让 GTK 自行使用 WSLg 默认图形 backend。
十一、最终 cc-switch 启动方案
执行:
1 | env GALLIUM_DRIVER=d3d12 SHELL=/bin/sh cc-switch |
结果:
cc-switch正常启动- 主窗口正常显示
- 列表、字体和 UI 正常
- 不再出现 X11 下的 DRI3 warning
- 不再出现
ZINK: failed to choose pdev - GPU 可以通过 D3D12 正常工作
程序日志:
1 | === CC Switch v3.20.2 started === |
此时仍然存在少量:
1 | libEGL warning: failed to get driver name for fd -1 |
以及:
1 | Gtk-CRITICAL: |
但均未影响实际启动和使用。
其中 GTK warning 更倾向于应用自身在 Linux / Wayland 环境下的兼容性提示,本次不继续处理。
十二、最终 alias 配置
当然不可能每次启动都手动输入:
1 | env GALLIUM_DRIVER=d3d12 SHELL=/bin/sh cc-switch |
因此最终仍然采用 alias 做运行时包装。
编辑:
1 | nano ~/.bashrc |
将原来的:
1 | alias cc-switch='env SHELL=/bin/sh GDK_BACKEND=x11 /usr/bin/cc-switch' |
修改为:
1 | alias cc-switch='env GALLIUM_DRIVER=d3d12 SHELL=/bin/sh /usr/bin/cc-switch' |
如果希望再短一点,可以额外增加:
1 | alias ccs='env GALLIUM_DRIVER=d3d12 SHELL=/bin/sh /usr/bin/cc-switch' |
保存后:
1 | source ~/.bashrc |
以后正常使用:
1 | cc-switch |
或者:
1 | ccs |
即可。
十三、为什么没有全局 export GALLIUM_DRIVER
理论上可以直接:
1 | export GALLIUM_DRIVER=d3d12 |
并写入:
1 | ~/.bashrc |
这样所有 Mesa Gallium 程序都会默认使用 D3D12。
但本次暂时没有这样处理。
原因是:
当前主要需要解决的是
cc-switch,因此优先将环境变量限制在这个程序自己的启动环境中。
这样做的好处是:
- 不影响其他 Linux GUI 程序
- 不修改整个 WSL 用户环境的 Mesa Driver 选择逻辑
- 出现兼容性问题时容易回滚
- 后续 Ubuntu / Mesa 修复默认行为后,可以直接删除 alias 中的参数
因此当前采用的是:
1 | Application Scoped Environment Override |
而不是:
1 | Global Environment Override |
十四、不再强制 GDK_BACKEND=x11
这也是这次处理相较之前方案最大的变化。
旧方案:
1 | alias cc-switch='env SHELL=/bin/sh GDK_BACKEND=x11 /usr/bin/cc-switch' |
当前方案:
1 | alias cc-switch='env GALLIUM_DRIVER=d3d12 SHELL=/bin/sh /usr/bin/cc-switch' |
即:
1 | - GDK_BACKEND=x11 |
实际思路也发生了变化。
之前主要解决:
1 | Wayland / GTK 兼容性 |
现在主要解决:
1 | Mesa 默认回退 llvmpipe |
而在当前版本的 cc-switch 和 WSLg 环境中,不再强制 X11 后,程序已经能够正常运行。
因此没有必要继续人为指定:
1 | GDK_BACKEND=x11 |
十五、本次完整故障链路
最终整个排查过程可以总结为:
1 | cc-switch GUI 异常 |
最终状态:
1 | WSL2 ✅ |
十六、日后快速检查方法
如果以后再次怀疑 WSLg GPU 加速失效,可以直接:
1 | glxinfo -B | grep -E 'Vendor|Device|Accelerated|OpenGL renderer' |
如果出现:
1 | Device: llvmpipe |
说明目前仍然在使用 CPU 软件渲染。
测试 D3D12:
1 | GALLIUM_DRIVER=d3d12 glxinfo -B | grep -E 'Vendor|Device|Accelerated|OpenGL renderer' |
正常应类似:
1 | Vendor: Microsoft Corporation |
同时可以确认 WSL GPU 设备:
1 | ls -l /dev/dxg |
以及 WSLg 环境:
1 | echo "$DISPLAY" |
十七、最终方案
最终保留的配置非常简单。
~/.bashrc:
1 | alias cc-switch='env GALLIUM_DRIVER=d3d12 SHELL=/bin/sh /usr/bin/cc-switch' |
应用:
1 | source ~/.bashrc |
以后:
1 | ccs |
即可启动。
等价于:
1 | env GALLIUM_DRIVER=d3d12 SHELL=/bin/sh /usr/bin/cc-switch |
十八、结论
这次 cc-switch 在 WSL Ubuntu 26.04 下的 GUI 异常,最终并不是 WSLg 本身损坏。
排查证明:
- systemd 正常
- WSLg 正常
- Wayland 正常
/dev/dxg正常- Windows GPU 通道正常
- Mesa D3D12 Driver 正常
- NVIDIA Quadro RTX 4000 可以被 D3D12 正确调用
真正的问题在于:
当前环境中 Mesa 默认 OpenGL Renderer 回退到了
llvmpipe,没有自动走 WSLg 的 D3D12 GPU 加速路径。
显式指定:
1 | GALLIUM_DRIVER=d3d12 |
后,OpenGL Renderer 从:
1 | llvmpipe |
恢复为:
1 | D3D12 (NVIDIA Quadro RTX 4000) |
同时,相比之前通过:
1 | GDK_BACKEND=x11 |
强制绕到 XWayland 的方案,本次在当前版本环境中直接使用 WSLg 默认 backend 已经可以正常运行,因此最终去掉了 GDK_BACKEND=x11。
最终使用:
1 | alias cc-switch='env GALLIUM_DRIVER=d3d12 SHELL=/bin/sh /usr/bin/cc-switch' |
作为最小侵入的运行时环境修复方案。
这类问题也再次说明:
WSL GUI “窗口能打开”并不代表 GPU 加速一定正常。
遇到 WSLg 图形异常时,除了检查 DISPLAY、Wayland 和 /dev/dxg,还应该进一步通过:
1 | glxinfo -B |
确认实际的 OpenGL Renderer。
看到:
1 | llvmpipe |
和看到:
1 | D3D12 (NVIDIA ...) |
是两种完全不同的运行状态。