第九章 APO管道
缘起缘落尽流水;
五行变换皆色空。
色即是空,空即是色;色异于空,空异于色。好了,好了;好就是了,了就是好。假为真来真亦假,无为有处有还无。我们世界上的事与物都离不开阴阳、五行变化的规律!空间几何变换与着色是不同的2个计算过程,但统一于“都是运算”;也即是所谓的统一渲染。一眼一世界,念起无尽眼;硬件惜有限;SP需规划。所以,我们必须仔细规划好流处理器SP。
60帧/S意味着,每个帧的一个流水阶段要小于16.7mS。我们假设一条管道有32条管线吧;每根管线的输入/输出存储寄存器深度是1K个顶点数据。那么一条管道需32*1K*4W = 128KW = 512KB,即是128K个32位寄存器或16K个行寄存器。APO做矩阵变换,一个管道的速度是4G个顶点/S。如果物体剔除后还有1M个顶点,使用1条管道;管道的流水存储深度是32K个顶点(即寄存器AB区可存放32K个顶点数据);需要1M/32K= 32次。每次所花的时间 = 32K/4G = 8uS。内存到寄存器的读写速度是1GH/S,所需时间(读和写各一次) = 2*16KH/1G = 32 uS。所以,处理1M个顶点CPU要做32次循环;所需时间为32*43us = 1.376 ms。另外,转换矩阵需要16W的常数寄存器,即寄存器C区。还有,AB区可交叉对半划分为A区和B区,或直接对半的A、B区。流处理器SP有不到10条功能指令,SP受CPU编程操控。以下就是顶点矩阵变换方法:
JVBH: // 矩阵变换。 需循环次数在R3寄存器。
// R1指向经剔除后的、R2指向变换后的、顶点数组起始地址行
MOV R4, #UJJV; // R4指向世界矩阵数组起始地址行
MOV R0, #SP_C; // R0指向SP的C区起始地址行
COPY (R0), (R4), #2; // 世界矩阵装入SP的C区行寄存器。
JV0: // COPY指令后,R0、R1、R2+ -> R0、R1、R2
MOV R0, #SP_AB; // R0指向SP的AB区起始地址行
COPY (R0), (R1), #16K; // 顶点数组装入SP的AB区行寄存器。
JVBHV; // SP的矩阵变换指令。
MOV R0, #SP_AB; // R0指向SP的AB区起始地址行
COPY (R2), (R0), #16K; // 保存变换后的顶点数组。
DJNZ R3, JV0; // R3-1 -> R3, 非0跳、继续。
RET; // 完成,返回。
一、 剔除
物体剔除是第一个流水级。从中央数据库返回的不到64K个物体模型的文件WTMXWJ;以不同的视眼分别作物体剔除后,生成多个新的物体模型文件WTMXWJx。通常,物体模型应给出类似包围盒的最少2个边点(上下或左右的2个最远点)。这样,通过计算眼睛到边点的向量 与视向量的夹角是否大于45度来判断物体是否与是视锥体相交或在外;从而剔除物体。假设视眼的位置向量是U = (x,y,z),视眼的单位视向量是U2
= (x2,y2,z2),边点的位置向量是P1 = (x1,y1,z1)。那么,视眼到边点的向量是 P1 – U =(x1-x,y1-y,z1-z)。其与单位视向量的夹角是:
cos a = [x2(x1-x) + y2(y1-y) + z2(z1-z)] / |P1 - U|
对于同一个视眼的所有物体,其单位视向量是相同的。所以,单位视向量U2及视眼的位置向量U放在常数寄存器C区。这是一个3D运算过程:
1、 每个物体有2个边点位置向量分别放入寄存器AB区的顶点数据区的前三个位置。
2、 P1 – U的3个分量之计算结果放入AB区的对应的顶点数据区的前三个位置;之后,该3个分量的平方和及再开方后放入AB区的顶点数据区的第四个位置。
3、 P1 – U的3个分量与常数寄存器C区的U2之3个分量分别相乘,其乘法结果之和放入AB区的顶点数据区的第三个位置。
4、 除法运算,计算cos a;并判断cos a > cos pi/2 ? 是置标志。
5、 如果物体的2个边点标志都被置1,则物体被剔除。
6、 P1 – U为8个时钟周期;|P1 – U|为12个时钟周期;3个分量的点乘和是8个时钟周期;除法及标志为4个时钟周期;总共需32个时钟周期。
7、 一个管道32条管线一次可计算32个边点位置向量,速度也是4G/S。
8、 最多128K个边点,CPU需4次循环。每次所花的时间 = 32K/4G = 8uS。总共所需时间为4*43us = 0.172 ms。
9、 CPU生成新的经物体剔除后的文件。 接着,对新文件的物体的三角形数组进行背面剔除。重复上面的1—8,剔除背面三角形;形成新的有效三角形索引数组。而这一个过程,如果有1M个三角形;就需要1.376ms? 不,应该能快很多;使用的是三角形单位法向量,只需3个分量的点乘和是8个时钟周期。所以,要快4倍,即最终不到0.4ms。那么下一步,CPU就根据新的物体有效三角形索引数组生成新的物体有效顶点数组。新的顶点数组与原来的大小一样,只是新的顶点数组中无效的顶点数据为0。因为存在多个三角形共用顶点,为了高效率;三角形的顶点数据只是顶点数组的索引。这部分工作是CPU进行而非GPU。在做4D顶点变换过程中,顶点数据的任一项为零;GPU会跳过该顶点;而计算下一个顶点数据。经过1.376
ms的顶点变换(包括把顶点从视锥体中变换到裁剪空间的 CVV 中)后,下一步就是在 CVV 进行三角形裁剪。也就是,对在[(-1,1),(-1,1),(-1,1)]空间外的顶点进行剔除,这些顶点在顶点数组中被清0。如果一个三角形有一个或二个顶点被剔除,那么应该形成新的三角形和新的相交顶点;这个工作,我考虑在CPU中进行;GPU做硬件比较复杂。所有的裁剪剔除计算都是为了减少需要绘制的顶点个数。到目前位置,我们得到了一堆在裁剪空间CVV中的三角形面片;下一步就是做Z buffer又称为depth buffer,即深度缓冲区测试;同时也做光栅化。得到对应屏幕像素的图元,在APO中的图元是指对应像素坐标的Z有效的三角形索引。图元着色后才成为像素。这样,我们得到新的Z有效的三角形索引数组;我们只需对该Z有效的三角形索引数组对应的顶点数据进行各种着色渲染(纹理贴图、几何着色、光照、光线跟踪等)。这样,光栅化也是可编程的。对于,透明性质的物体是另外的光栅流水线进行;在最后的着色时要进行混色。光栅化需另文说明,这里就不多介绍了。
小结:
如果剔除、顶点变换是一个流水级;那么,一个管道大约可处理8个视眼文件。32条管道理论上就可处理256个视眼文件。另外的32条管道是处理光栅化、着色等计算过程。最终,流水循环无穷。目前的规划还是在“粗”过程,任何事情过程都是由粗到细的。
二、 APO管道结构
如下图,基本的功能指令有1D、2D、3D、4D运算;向量点积;向量叉乘等。