游戏性能优化杂谈(十二)

霸气de小男生 提交于 2020-11-14 12:54:53

GPU的光栅化模块之后,是一个工作量打包模块。这个模块负责将光栅化的结果(fragment)按照一定大小(N卡:warp32,A卡:wavefront64或wavefront32)打包,然后交给下面的处理阶段(PS)

这里需要注意的一个细节是,离散化的粒度虽然最终是像素级,但是在近代GPU当中,离散化模块输出的单位却不是单个像素,而是Quad(2x2像素)。其中的一个原因(可能并不是最根本的那个原因)是单个像素无法计算ddx、ddy,从而在PS当中判断选用贴图的MIPS层级会发生困难。当然,我也怀疑这可能与GPU当中贴图单元与计算单元配比等有关,亦或是和内部带宽有关,但是无从验证。

总之,对于当前主流的GPU来说,一个三角形至少会产生一个Quad。当三角形很小面积无法覆盖一个Quad的时候,未被覆盖的那些像素(准确来说是fragment)会被标志为无效,但是坑并不会让出来。

所以对于上一篇所举的那个dither的例子,一些位置上整个Quad被mask掉,而另外一些地方其实只是Quad里面的部分像素被标志为无效。

什么意思呢?就是其实PS工作量总的来说是减少了,但是并没有减少很多。如果用GPU抓帧工具来看,会发现很多warp/wavefront里面的thread不饱满,有的甚至里面只有几个thread。

就好像公司组织去旅游,包了6辆旅游巴士,结果当天1半人取消。本来呢重新安排一下位置可以取消3辆车,但是人与人之间各种亲疏远近各种嫌弃,或者平级领导不愿同乘还得跟班陪坐什么的,最终可能只能取消2辆甚至1辆都不行。

在这种情况下,很多被抠掉的像素其实依然在管线内参与整个PS计算,只不过计算结果被丢弃而已。

更为不幸的是,这种丢弃,因为GPU和内存之间有cache,也就是有cache line的存在,很多时候对于内存带宽的节省,也是打折扣的。cache line与内存交换一次就是连续64字节,按照32bit/pixel计算,就是16个像素(4x4),也就是4个Quad(2x2)。这些都是定死的,所谓的丢弃,只不过是原样读入原样写出,带宽消耗还是那么多。

即便是Quad单位的丢弃,依然是有限制的。光栅化模块,虽然很快,但是产生Quad的速率是一定的。后续的打包模块,将8个或者16个Quad打一起那个,也不是拥有无限耐心的。什么意思呢?就是好比公共汽车,它是有运营时刻表的。并非是包车,坐满再开。所以如果大量Quad被干掉,要么一个都没有公交有时这个班次也就取消了,否则1个人都开。

为什么?因为司机并不知道后面还有多少人,还要多久来。再说,既然是定线定时运营,错过了就坐下一班,这是基本。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!