闲话

在从事图形优化工作之前,一直对显存(Video Memory)充满了好奇,很想了解其管理方式、基本原理、与内存的区别等,但一直没有时间和机会去研究,现在工作需要,逐渐开始接触和了解,这里也顺便记录,以免后续忘记。

什么显存?

显存,即Video Memory,简单来说,就是位于显卡的内存,其主要用途当然是用作图形显示了,现在的家用pc中基本都配置了独立显卡,即使是集成显卡,也有一定的显存,否则一些游戏玩起来可能就费劲了。

为什么需要显存?

随着计算机硬件的飞速发展,现代的CPU、内存能力已经超过了从前的想象,按理说,目前计算机中的主要瓶颈应该还在IO上,内存应该不至于成为瓶颈,那为什么需要显存呢?

这个问题就如“为什么需要显卡”一样,之前的文章中应该做了解释,所谓术业有专攻,显卡专注于图形显示,更擅长于图形显示,而显卡进行图形显示时是需要内存资源的,如果其所需的内存资源都从内存(CPU主存,后面简称内存)分配,那相对于使用显卡自带的内存,性能肯定有损耗。 这就跟NUMA节点中远程访问类似,虽然内存硬件本身的能力并不比显存弱,但“距离”、“亲疏关系”、“使用方式”等对其影响很大。

显存管理

在Linux X11环境中,显存通常是通过内核的DRM模块进行管理,用户态和内核程序都可以使用DRM提供的接口分配和释放显存。 用户态程序通过Libdrm提供的用户态接口(本质上为ioctl调用)来分配和释放显存。

DRM模块中,最终使用TTM模块在管理显存(或内存)。 TTM模块中,自己实现了一个内存pool,分配和释放显存(或内存)时,会先放到pool中,如此可以提高内存管理的效率,具体的原理和代码就不深入讨论了。

GTT VS. VRam

做过图形研究的TX应该都了解GTT和VRam,GTT表示显卡可以访问的CPU主存,VRam表示显存。 为什么要将这两者进行比较呢? 因为对于软件来说,GTT和VRam的地位是对等的,当软件中(比如mesa驱动中)需要分配内存时,其可以选择在内存上分配(分配标志设置为GTT相关的标记),也可以选择在显存上分配(分配标志设置为VRam相关的标记), 对于软件来说,使用GTT或VRam并没有功能上的影响,通常情况下,任意选哪种都没有问题。 有影响的只是:

  • 性能。 对于显卡,通常来说,显示需要的内存在VRam上分配,性能可能会更好,因为相关内存上的内容最终可能都会拷贝到framebuffer中去,而在显存内存区域之间的拷贝,显然比内存到显存之间的拷贝性能更好。
  • Cache一致性等问题。 对于部分硬件,Cache一致性问题可能是很多问题的根源,特别在涉及到CPU和GPU之间的同步和并发访问时。 CPU和GPU对于GTT和VRam的访问,可能会涉及到一些硬件的细节和特性,比如WC(Write Commbined)和UC(Uncached)特性,这些细节的处理,在非X86架构上尤其重要,特别是在驱动中,需要时刻考虑这些问题。

Framebuffer

再简单聊下Framebuffer(后面有时间可单独再聊),Framebuffer本质上就是一段缓存,通常就是显存上的一段内存,其直接与最终显示到终端上的内容对应,所有需要显示到终端上的图形内容都必须拷贝到Framebuffer中。

Framebuffer其实由多个buffer组成,这里不详述。 但需要说明,通常Framebuffer中有前端和后端两类buffer,就是我们平常见到的double buffer技术,目的是为了解决屏幕撕裂问题。 前端buffer直接对应于欲显示的内容,需要显示的数据先拷贝到后端buffer,再在一定的时机(比如vblank)将后端buffer的数据swap到前端,从而显示出来。