● 像素到效果的桥梁
尽管恩怨纠葛持续了很久,硬件的结构也越来越复杂,但像素本身其实还是非常单纯的。我们说过,对像素的处理,归根结底是对构成颜色的三原色的处理,而对三原色的RGB值以及透明度Alpha的量化处理,实际上是非常单纯的数学运算。这个单纯的计算过程,为什么会衍生出了如此纷繁复扰的处理过程的呢?像素到效果之间,究竟跨越了怎样的阶段呢?
Grid到Thread所对应的硬件
在前一页中我们已经知道,如果我想将材质中某个原本黄色的像素点揉到光线效果中并令其因此改变颜色,需要将像素原本颜色的数值以及它与光线和其他通过数学的手段处理成一个或一组方程。这就是像素向效果迈进的第一步,从像素变成方程。不同的像素改变对应了不同的方程或者方程组,要处理这些方程/方程组,就必须将它们转化成ALU能够接受的形式,因此方程/方程组就变成了指令。
接下来,硬件流水线如果要执行这些指令,就必须让其拥有符合流水线特征的身份,于是以1个像素为单位,这些指令被转换成了Thread(线程)。要实现某种特效,显然不太可能只改变一个像素,于是一堆像素的改变就变成了若干Thread的集团,为了方便硬件进行吞吐,若干Thread会合并成为CTA(线程块),它对应硬件能够执行的最小粒度,也就是NVIDIA的warp或者AMD的wavefront。若干CTA又可以组合成一个Block,这是方便程序员进行发放管理而设定的最小Thread单位。一个最小GPU执行单元比如SM可以面对若干个Block,当一个Block里的所有CTA都被执行完之后,SM就会寻找其他未被执行的Block,被划分在一起可以由同一个SM完成吞吐的Block,被称作Grid。
最后,很多特效都是基于全屏基础的,换句话说,屏幕内会出现大量需要更改的像素,这些像素更改所对应的全部过程就是一个kernel,这个kernel,就是由所有Grid组合成的集合。
你觉得有些头晕?没关系,我换个可以帮助理解的方式——因为我们要理解的是像素到画面之间的递进关系,所以我们只看像素即可。要实现特效,所要改变的最基本单位首先是像素,一个改变的最终结果对应一个像素任务(Thread);出于提高GPU的像素吞吐效率的考量,若干个像素会被组合成一个整体集团被ALU团簇执行(CTA);既然方便了硬件,程序员也要得到便利,所以我们又设定了一个程序员方便管理的最小单元,里面包含了若干被组合在一起的像素集团(Block);一个ALU团簇一次能够面对若干个这样的像素集团,他们也可以被称作一个更高级的集合体(Grid);最后,当屏幕内所有的这种最高级待改变像素集合体被执行完毕之后(kernel),特效就呈现在我们眼前了。