关注公众号

关注公众号

手机扫码查看

手机查看

喜欢作者

打赏方式

微信支付微信支付
支付宝支付支付宝支付
×

【技术解析】GPU如何实现三维渲染及非图形计算?(三)

2020.10.26

  通常和色彩一起存放于色彩缓存的阿尔法通道(Alpha Channel)包含了每个像素的相对不透明值,开发人员可以在进行深度测试之前对到来的片元先执行名为阿尔法测试(Alpha Test)的操作。如果片元的 alpha 值测试(一般是等于、大于等简单的操作)为“假”,那么这个像素的后续处理操作就会被省略掉。这个操作通常用于确保完全透明的片元不会对 Z-buffer 构成影响。

  此外,还可能会涉及到名为蜡板缓存(Stencil Buffer)的技术。Stencil Buffer 作为一个离屏缓存一般用于存放已渲染图元的位置,它通常用于进行一些特殊效果的处理,例如将一个“实心”圆存放到蜡板缓存中,之后配合其他操作,就可以将被覆盖图元的色彩值控制为只有在位于这个实心圆中的时候才被呈现,相当于一个遮罩的作用。

  

  以上这些缓存都被统称为帧缓存,但是在一般情况下,帧缓存特指色彩缓存和深度缓存。由于画面渲染是需要时间的,为了保证出到显示器或者显示屏的时候图元都是已经完成渲染的,人们引入了双缓存技术,渲染中的被称为后台缓存(back buffer),完成渲染的称作前台缓存(front buffer),在后台缓存完成渲染后,马上变成前台缓存,而前台缓存就切换为后台缓存,以此类推。

  片元(fragmet)和像素(pixel)的区别?

  上文中我们提到了片元和像素,像素是相对容易理解的,严格来说,像素就是对应屏幕上的一个点,它有表示屏幕位置的 x、y 坐标以及颜色的红绿蓝(RGB)值(像素是没有 Alpha 通道值的),图形流水线所作的所有事情都是为了给输入的图元计算在屏幕上像素的颜色。

  那么,片元又是怎么一回事呢?

  在三角形遍历和输出合并之间计算的栅格数据就是片元,它们是像素的前身,在遍历的时候由顶点内插而成。片元除了具备像素的 x、y 坐标外,还有表示深度的 z 坐标以及顶点的属性信息(颜色、片元法线、纹理坐标)。

  

  正如前面所说的,深度坐标记录的是图元的相对距离,在深度测试的时候被遮蔽(或者阿尔法测试中为透明)的图元会在输出合并阶段被抛弃掉,。

  片元这个说法是 OpenGL 或者大多数实时图形渲染文献中的概念,而 D3D 则没有这么严格的区分,片元和像素都统称为像素。

  我们这里讨论的都是以实时三角形渲染为例,除此以外还有其他三维渲染流水线形式,例如 micropolygon(微型多边形)、Voxel(体素) 渲染。

  现在的GPU流水线也是遵照这样的图形流水线来设计,在一段时间里,出于成本效益的考虑,GPU 的各个功能单元都是有专门的电路来实现的。

  不过在新式的GPU中,可编程部分(例如顶点程序、片元程序)由于指令集得以统一,所以都采用了同样的计算单元来跑。

  公认必须采用固定功能硬件单元来实现的主要是三角形设置、遍历以及输出合并单元,英特尔曾经试图在名为 Larrabee 的GPU项目里将这些工位采用通用单元来执行,但是最终结果是不了了之,至少说明现阶段或者在未来可见的较长时期里,三角形设置/遍历以及输出合并的最合理实现方式还是使用固定功能硬件单元。

  

  (Intel Larrabee)

  在现实中GPU并不仅仅是上面讨论的三维处理、计算单元,广义的GPU还应该包括视频编解码单元、扫描输出单元、总线单元、存储单元,手机GPU现在都和 CPU、基带、周边等单元集成到同一个芯片里,这样的芯片被称作 SoC(片上系统),SoC 并非是手机独有的,在此之前的单片机(例如洗衣机等里就有,一般几块钱一颗)其实就是 SoC 的一种实现方式。

  GPU 在移动应用中能发挥的作用

  GPU 最初是为三维游戏加速设计的,所以它最拿手的自然是三维游戏加速,现在无论是安卓、iOS 都有不少三维游戏大作,例如:劳拉 Go、FIFA 系列、真人快打 X、Hitman Sniper、Marvel Future Fight、Godfire: Rise of Promotheus、Over Kill、Implosion、Battle supremacy 等等。

  

  除了游戏渲染加速外,智能手机的操作系统界面也是采用了GPU硬件加速的,例如选单的弹出、桌面平移等。和桌面操作系统使用三维加速相比,移动操作系统由于受到屏幕空间小的约束,因此三维加速体验带来的空间感拓展是更加不可或缺的。从安卓4.0系统开始,不少用户就感觉到系统流畅性大幅度提高正是因为从系统层面上线了GPU硬件加速。

  通用计算加速原本也是在非移动应用上的技术,不过随着智能手机的高速发展,已经有了不少开发人员利用GPU的通用计算能力来进行一些有意义的加速。

  例如在苹果机上有一款名为极拍的 APP,利用苹果手机的GPU对摄像头拍摄的视频进行实时降噪处理,可以将苹果手机的夜间视频达到单反摄像机的夜间视频拍摄效果,这是非常具有实用意义的。

  另一个典型是高通骁龙处理器,ATI是最早提倡通用计算加速的GPU制造商,而Adreno 200 GPU正源自ATI Imageon项目。发展至今,在高通骁龙820上的Adreno 530已经能实现辅助全景照片合成、帮助“认知计算平台”Zeroth识别物体。

  

  (“认知计算平台”Zeroth演示)

  GPU 在这三方面的作用对我们手机的日常应用产生了直接的影响,许多手机媒体口头整天挂着的使用体验,其实都离不开 GPU。

  浅析GPU的常见术语

  在下篇文章中SIMD、Core、GPU 中的线程、统一着色器、纹理单元这些GPU常见术语对一般读者来说都是相当陌生或者容易产生困扰,在此先进行浅析。

  SIMD:

  Single Instruction Multiple Data,单指令多数据流,目前所有的GPU在基本功能单元层面都属于SIMD(业界也接受NVIDIA提出的SIMT——单指令多线程),一般是16路SIMD或者32路 SIMD。

  “内核”或者core:

  目前在GPU行业或者GPU行销上被严重滥用的名词,它被用作指代SIMD一条Lane(计算通道)上的单元集合,里面可能有一个单周期 32位FMA(积和熔加运算)运算器、一个双周期64位FMA运算器等等,GPU厂商把GPU里的SIMD Lane数加起来就对外宣称有多少个内核。

  这样的说法是否属于错误宣传还真不好说,因为目前并没有什么法律文件规定怎样的集合才算是一个内核。

  不过对于计算机科学来说,微架构里对内核约定俗成的看法是它必须有一个PC(程序计算器,它是一个寄存器,其中存放的一般是指向该内核要执行的下一条指令的地址)。

  这样的话,一个GPU内核显然不能是SIMD单元中的一个Lane,它的层级至少应该高一级。

  所以,GPU上相对严格的“内核”概念单元对应的应该是类似与AMD GCN的Compute Unite、NVIDIA Maxwell中的SMM、PowerVR Series 6/7的USC等名词命名的单元集合,在OpenCL中,这个层级的单元集合被称作Compute Unit(计算单元,简称CU,AMD的GCN微架构也采用Compute Unit这个术语,完全对应OpenCL的Compute Unit),而GPU厂商的行销术语 “内核” 或者“core” 在OpenCL中被称作Process Element,简称PE。

  GPU中的线程:

  现在的GPU都采用了多层次线程技术,按照硬件开发商提供的文档,对应SIMD Lane的被称作thread(OpenCL中称作work-item,在图形渲染的时候你可以将其看作是屏幕上的一个像素),是最小的线程单位;

  往上的一层线程单位在新的OpenCL被称作sub-group,NVIDIA称作warp 或者thread warp,AMD称作wavefront,属于GPU执行调度的最小硬件线程单位。再往上就是workgroup(NVIDIA 称之为thread block)和NDRange(NVIDIA称之为Grid,由若干个workgroup或者thread block组成)。

  Workgroup的对应GPU硬件关系是Compute Unit,同一时间里Compute Unit跑的都是一个workgroup,而Grid则对应GPU的一个partition(分区,在设备或者说加速器允许的情况下,OpenCL可以把一个设备分成若干个分区来使用)。

  你可以把饭粒比作是work-item,而每一口饭则算是一个sub-group,一碗饭看作是一个 workgroup,饭煲看作是NDRange(sorry,我的比喻未必很恰当)。

  统一着色器

  在 DX10以后,由于几何、像素的指令格式一样,使得几何和像素处理可以在同样的单元上执行,自此以后台式GPU都采用了统一着色器设计,以确保着色器的利用率提高。

  纹理单元

  纹理单元或者说纹理映射单元是GPU中计算纹理坐标和获得纹理样本的单元。在绘制某个对象的时候,每个纹理单元进行一个纹理取样动作,不同的绘制对象每次的取样动作都可以更改使用的纹理。纹理单元的性能指标一般用 TexOps/s 来表示,表示每秒的纹理操作数,不同的纹理格式和不同的纹理过滤算法以及硬件实现、内存带宽都会对这个指标产生影响。纹理单元一般和若干个着色器绑定在一起。


推荐
关闭