早期的显卡仅用于显示,后来显卡中加入了2D加速部件,这些部件用于做拷屏,画点,画线等操作。随着游戏、三维模拟以及科学计算可视化等需要,对3D的需求逐渐增加,早期图形绘制工作由CPU来完成,要达到真实感和实时效果,只能绘制一些简单的线框模型,上世纪80年代,斯坦福大学的Jim Clark教授率先提出用专用集成电路技术实现一个专用的3D图形处理器的设想,于1984年推出了世界上第一个通用图形工作站IRIS1400。
AMD最早的显卡从R100开始,一直到R900(R600以后也使用HD xxxx作为代号),R900(HD 6xxx)之后是HD 7xxx系列,目前最新的显卡使用 Rx 2xx代号,最新的是Radeon R9 2xx系列。这里只描述R600显卡的编程,因此只讨论R600之前和之后不久的显卡。
AMD显卡的演变过程如下(参考wiki页和Plan9操作系统开发人员的PPT):
图1
R100是一款固定功能流水线的显卡,R200为可编程处理器,R300在R200的基础上发生了比较大的变化,此后的R400 和R300差别不大。到R500的时候GPU除了有vbios外,还引入了atombios,atombios是一段比较简单的脚本,和具体平台无关,解释器解释执行(代码集成在内核驱动里面),然而3D核较R300变化不大,寄存器变化也比较少(变化主要变化在pixel shader 部分)。
R600在R500的基础上发生很大的变化,2D部件被废除,3D部件改成了unified shader架构,GPU的寄存器和原来完全不同,由于体系结构的变化,对硬件编程也和原来有了很大变化。R700 GPU是R600的优化版,在驱动层面上,R700的编程和R60的编程基本上是一样的,后续的Evergreen、Southern Island和Northern Island都是这种unified shader架构的延续,因此理解R600的编程后将比较容易理解后续GPU核的编程。
本书的后续部分针对R600核心进行描述,总体来说,R600硬件在R500基础上重要的变化包括(参考Radeon R6xx/R7xx Acceleration):
- 不再包含2D加速部件,所有的加速都使用3D部件完成
- 使用Shader Model 4.0,使用Unified shader架构,vertex shader、fragment shader(以及geometry shader)不再分成单独的部件,而是被统一起来,另外包含Geometry shader
除了以上变化之外,还有一点值得注意的是,R600显卡GPU核的计算都是基于标量的,而不是像以前的那样基于矢量的(参考ATI Radeon HD 2000 programming guide)。
对于软件编程而言寄存器读写方式上也有比较大的变化,过去对R500编程的时候,所有的对硬件的编程都是可以用命令包或者普通的直接写寄存器的方式进行的,但是R600的部分寄存器是不能够通过直接写寄存器的方式进行编程的,必须通过3型命令包的方式进行(看到的代码都是这样的,R600寄存器手册上有很多寄存器地址都是一样的,但是含义不同,这些寄存器偏移都大于等于0x8000,是否正确??)。
Linux系统下的drm、exa、mesa代码也和这种变化相对应,通常来说,以Radeon_开头的函数名针对的是r100显卡或者后续显卡的公共代码,R200_开头的函数仅针对r200核心的显卡,R300_开头的函数针对r300、r400和r500,R600_开头的函数针对r600、r700,Evergreen_开头的的函数针对HD5xxx和HD6xxx系列。
后续的blog将介绍AMD显卡的显存管理机制、命令处理、中断机制,然后介绍3D引擎,3D引擎部分包括显卡的图形流水线和对3D引擎的编程以及R600的指令集。后续的内容是阅读代码和AMD公开的部分资料后对相关内容的理解,这些理解肯定有不少错误,仅供参考。
相关参考资料:
AMD公布的资料可以在这里看到,AMD公布的R500核心的编程资料是最完整和最详细的,这部分资料详细介绍了R500显卡工作的原理和一些编程细节。