Graphics Stack总结(三) Mesa中Driver的加载和查询

回顾

在之前的文章中,我们解释了Mesa是一个OpenGL driver的开发框架。正如此,Mesa提供的代码可以在多种driver的实现中被重用。当然这部分code是跨硬件的,使得驱动开发者不用做这部分工作。这个框架也为开发者提供了hook,用来增加于与实际硬件的交互的代码。这种设计允许多种driver共存,并且共享很多代码。

我也解释了在Mesa提供的这么多种的drivers中,我们可以找到纯粹用软件实现的software drivers(它们在CPU上工作,不依赖于GPU)和利用特定GPU优势的hardware drivers。software drivers更慢,但是就如我们讨论的那样,某些情况下它们会派上用场(比如检查某个issue是否与GPU hardware driver有关)。

Driver selection

所以,Mesa提供了多种driver,但是它如何在一个特定的系统里选择合适的driver呢?

你可能注意到mesa被部署在多个packages里。在我的Ubuntu系统中,部署DRI drivres的package是libgl1-mesa-dri:amd64,如果你检查它的内容,会看到这个package会为不同的GPUs安装OpenGL drivers。

# dpkg -L libgl1-mesa-dri:amd64 
(...)
/usr/lib/x86_64-linux-gnu/gallium-pipe/pipe_radeonsi.so
/usr/lib/x86_64-linux-gnu/gallium-pipe/pipe_r600.so
/usr/lib/x86_64-linux-gnu/gallium-pipe/pipe_nouveau.so
/usr/lib/x86_64-linux-gnu/gallium-pipe/pipe_vmwgfx.so
/usr/lib/x86_64-linux-gnu/gallium-pipe/pipe_r300.so
/usr/lib/x86_64-linux-gnu/gallium-pipe/pipe_swrast.so
/usr/lib/x86_64-linux-gnu/dri/i915_dri.so
/usr/lib/x86_64-linux-gnu/dri/i965_dri.so
/usr/lib/x86_64-linux-gnu/dri/r200_dri.so
/usr/lib/x86_64-linux-gnu/dri/r600_dri.so
/usr/lib/x86_64-linux-gnu/dri/radeon_dri.so
/usr/lib/x86_64-linux-gnu/dri/r300_dri.so
/usr/lib/x86_64-linux-gnu/dri/vmwgfx_dri.so
/usr/lib/x86_64-linux-gnu/dri/swrast_dri.so
/usr/lib/x86_64-linux-gnu/dri/nouveau_vieux_dri.so
/usr/lib/x86_64-linux-gnu/dri/nouveau_dri.so
/usr/lib/x86_64-linux-gnu/dri/radeonsi_dri.so
(...)

因为我用的是近期的Intel GPU,所以我需要的driver是i965_dri.so。所以我们该如何告诉Mesa那个就是我们需要的driver呢?然而答案是不需要,Mesa足够智能,它会知道对我们的GPU来说,哪个driver是正确的,并且在你load libGL.so时自动选择它。Mesa中处理这个环节的部分我们称之为"loader"。

然而你也可以让Mesa在指定的文件夹中寻找适配的driver,而不是在默认设置下,或者通过指定不同的环境变量(using various environment variables.)来强制Mesa选择一个software driver。

What driver is Mesa actually loading?

如果你想确切的知道Mesa正在loading的时什么,你可以指示它通过环境变量 LIBGL_DEBUG 把这个信息(或者其他信息)输出到stderr中。

# LIBGL_DEBUG=verbose glxgears 
libGL: screen 0 does not appear to be DRI3 capable
libGL: pci id for fd 4: 8086:0126, driver i965
libGL: OpenDriver: trying /usr/lib/x86_64-linux-gnu/dri/tls/i965_dri.so
libGL: OpenDriver: trying /usr/lib/x86_64-linux-gnu/dri/i965_dri.so

所以我们看到Mesa检查了现存的driver并且意识到i965 driver是要用的driver,然后它首先尝试加载i965 driver的TLS版本,由于我没有TLS版本,所以会fall back到我所有的i965 driver的normal版本。

src/loader/loader.c (loader_get_driver_for_fd) 里的代码负责检测出哪个是正确的driver来使用(我的例子中是i965)。它收到输入参数device fd,而device fd是之前作为DRI bring up过程的一部分,调用DRI2Connect() 时调用所需要的输入参数。然后实际的driver文件被加载到glx/dri_common.c (driOpenDriver)中。

通过使用mesa-utils包附带的glxinfo程序,我们还可以获得正在加载的驱动程序的更具描述性的指示

# glxinfo | grep -i "opengl renderer"
OpenGL renderer string: Mesa DRI Intel(R) Sandybridge Mobile 

这里告诉我,我正在使用Intel hardware driver,而且提供了我所用的Intel的特定GPU的信息 (SandyBridge)。

Forcing a software driver

我已经提到过,software drivers有时会派上用场,但是我们如何让load去使用它呢?Mesa提供了一个我们可以设置的环境变量,所以在hardware driver和software driver之间切换变得非常简单:

# LIBGL_DEBUG=verbose LIBGL_ALWAYS_SOFTWARE=1 glxgears 
libGL: OpenDriver: trying /usr/lib/x86_64-linux-gnu/dri/tls/swrast_dri.so
libGL: OpenDriver: trying /usr/lib/x86_64-linux-gnu/dri/swrast_dri.so

正如你看到的,设置环境变量LIBGL_ALWAYS_SOFTWARE 可以让loader选择一个software driver (swrast).

如果我强制使用software driver,然后调用之间的glxinfo,那么会得到:

# LIBGL_ALWAYS_SOFTWARE=1 glxinfo | grep -i "opengl renderer"
OpenGL renderer string: Software Rasterizer

所以在这个例子中,很清楚的看到我正在调用software driver.

Querying the driver for OpenGL features

glxinfo程序还可以方便地获取有关driver实现的特定OpenGL feature的信息。如果要检查硬件的Mesa驱动程序是否实现了特定的OpenGL extension,可以检查glxinfo的输出并查找该扩展(extension):

# glxinfo | grep GL_ARB_texture_multisample

You can also ask glxinfo to include hardware limits for certain OpenGL features including the -l switch. For example:

你还可以要求glxinfo为包括-l switch在内的某些OpenGL feature添加硬件限制

# glxinfo -l | grep GL_MAX_TEXTURE_SIZE
GL_MAX_TEXTURE_SIZE = 8192

Coming up next

我的下篇文章将会包含Mesa repo的文件夹结构以及介绍主要的modules,这会给Mesa的初学者一些指导,这样他们就根据需求找到想要看的那部分代码。我们接下来将会讨论现代3D hardware是如何改变了GPU drivers开发的方式,并且解释一个现在3D graphics pipeline是如何工作的,这将为开始研究Mesa的真正内核铺平道路:着色器(shader)的实现。

posted @ 2022-10-31 15:35  青山牧云人  阅读(2111)  评论(0编辑  收藏  举报