问题缘由:
在WSL2 Ubuntu20.04中使用
sudo add-apt-repository ppa:kisak/kisak-mesa
和
sudo apt update && sudo apt upgrade
更新OpenGL,更新前后OpenGL依然是1.4版本:
OpenGL version string: 1.4 (2.1 Mesa 10.5.4)
,而最新版的OpenGL实际可以达到4.2版本:
OpenGL version string: 4.2 (Compatibility Profile) Mesa 22.1.1 - kisak-mesa PPA
最原始的问题是在ROS2中运行rviz出现下面的错误:
[ERROR] [1654302833.739499814] [rviz2]: rviz::RenderSystem: error creating render window: InvalidParametersException: Window with name 'OgreWindow(0)' already exists in GLRenderSystem::_createRenderWindow at /tmp/binarydeb/ros-foxy-rviz-ogre-vendor-8.2.6/obj-x86_64-linux-gnu/ogre-v1.12.1-prefix/src/ogre-v1.12.1/RenderSystems/GL/src/OgreGLRenderSystem.cpp (line 1061)
[ERROR] [1654302833.739520104] [rviz2]: Unable to create the rendering window after 100 tries
经了解,这个问题产生的原因是OpenGL版本太低,使用
glxinfo -B
查看显示OpenGL版本为1.4
问题梳理及解决:
OpenGL有四种不同的渲染方式,分别是直接软件渲染、直接硬件渲染、间接软件渲染、间接硬件渲染。其中直接硬件渲染方式的效率最高,其次是间接硬件渲染,这部分的内容可以参阅
How to tell whether your setup is good
,里面简要的介绍了这四种方式的好坏。
现在打开WSL2 Ubuntu终端,输入
glxinfo -B
,这条命令会告诉你关于OpenGL的相关信息,我电脑上最初的输出如下:
name of display: localhost:10.0
display: localhost:10 screen: 0
direct rendering: No (LIBGL_ALWAYS_INDIRECT set)
OpenGL vendor string: Mesa Project
OpenGL renderer string: Software Rasterizer
OpenGL version string: 1.4 (2.1 Mesa 10.5.4)
direct rendering: No
表示采用的是间接渲染,
OpenGL renderer string: Software Rasterizer
表示OpenGL的渲染方式是软件渲染。这种方式效率最低。
这和我们的问题有什么关系呢?你可以运行
LIBGL_ALWAYS_INDIRECT=0
将渲染方式由间接改为直接,再运行
glxinfo -B
,你会发现输出结果和之前完全不一样:
$ LIBGL_ALWAYS_INDIRECT=0
$ glxinfo -B
name of display: localhost:12.0
display: localhost:12 screen: 0
direct rendering: Yes
Extended renderer info (GLX_MESA_query_renderer):
Vendor: Microsoft Corporation (0xffffffff)
Device: D3D12 (NVIDIA GeForce MX450) (0xffffffff)
Version: 22.0.1
Accelerated: yes
Video memory: 10011MB
Unified memory: no
Preferred profile: core (0x1)
Max core profile version: 3.3
Max compat profile version: 3.3
Max GLES1 profile version: 1.1
Max GLES[23] profile version: 3.1
OpenGL vendor string: Microsoft Corporation
OpenGL renderer string: D3D12 (NVIDIA GeForce MX450)
OpenGL core profile version string: 3.3 (Core Profile) Mesa 22.0.1
OpenGL core profile shading language version string: 3.30
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL version string: 3.3 (Compatibility Profile) Mesa 22.0.1
OpenGL shading language version string: 3.30
OpenGL context flags: (none)
OpenGL profile mask: compatibility profile
OpenGL ES profile version string: OpenGL ES 3.1 Mesa 22.0.1
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.10
这时
direct rendering: Yes
表示采用直接渲染,同时
OpenGL renderer string: D3D12 (NVIDIA GeForce MX450)
表示采用硬件渲染。更重要的是,OpenGL的版本
OpenGL version string: 3.3 (Compatibility Profile) Mesa 22.0.1
,在这个过程中我只修改了OpenGL的渲染方式:由间接到直接。
我猜测这个结果的原因是OpenGL采用不同的渲染方式时,会采用不同的软件库。
如果你需要进一步的升级OpenGL,比如升级到4.2版本,则可以尝试如下命令:
sudo add-apt-repository ppa:kisak/kisak-mesa
sudo apt update && sudo apt upgrade
更新后再次使用
glxinfo -B
,输出结果如下:
name of display: localhost:10.0
display: localhost:10 screen: 0
direct rendering: Yes
Extended renderer info (GLX_MESA_query_renderer):
Vendor: Microsoft Corporation (0xffffffff)
Device: D3D12 (NVIDIA GeForce MX450) (0xffffffff)
Version: 22.1.1
Accelerated: yes
Video memory: 10011MB
Unified memory: no
Preferred profile: core (0x1)
Max core profile version: 4.2
Max compat profile version: 4.2
Max GLES1 profile version: 1.1
Max GLES[23] profile version: 3.1
OpenGL vendor string: Microsoft Corporation
OpenGL renderer string: D3D12 (NVIDIA GeForce MX450)
OpenGL core profile version string: 4.2 (Core Profile) Mesa 22.1.1 - kisak-mesa PPA
OpenGL core profile shading language version string: 4.20
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL version string: 4.2 (Compatibility Profile) Mesa 22.1.1 - kisak-mesa PPA
OpenGL shading language version string: 4.20
OpenGL context flags: (none)
OpenGL profile mask: compatibility profile
OpenGL ES profile version string: OpenGL ES 3.1 Mesa 22.1.1 - kisak-mesa PPA
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.10
在这个过程中我有一个地方没有搞懂,
LIBGL_ALWAYS_SOFTWARE
变量是用来干嘛的,我将其设置为0或1后再执行
glxinfo -B
,输出结果没什么变化。
参考链接:
Github上相关的issue