经典的GPU架构都是Immediate mode GPU.主要的流程就是vertex shader 和 pixel shader顺序执行。其数据流如下图所示:

image-20210925124105052

执行流程可以用伪代码表示如下。

foreach(triangle)
	foreach(fragment)
		load FBO data (color, depth, ...)
		call fragment shader
		store new FBO data

Immediate mode是Full Screen的,所以对于每个primitive都直接提交渲染。这样Pipeline在执行中是没有中断的,每个Raster core只要负责render分给它的primitive,这样Raster就是并行执行的。只需在pixel shader后对Raster出的pixel做个排序。

但是Frame Buffer本来就比较大,对于整个屏幕的颜色渲染或者深度渲染就会消耗很多存储资源,显然Cahce的大小是不可能这么大的,这就导致要频繁的Flush/Invalidate Cache,这样带宽的压力就变得很大,而且频繁的GDDR访问也非常耗功耗。对于移动设备来说,这种方式很不利于设备的续航。

最初的Tile-Based的想法就是将执行流程伪代码中的循环优化一下:

foreach(fragment)
	load FBO data (color, depth, ...)
	foreach(triangle)
		call fragment shader
		store new FBO data

对于上面的优化,memory一下子就炸了,要为每个pixel保存三角形,这memory的消耗也忒大了点!那么在这个的基础上有啥可以修改的呢?

当然!既然为每个pixel保存三角形太废了,那么就分成一个个的小块呀!这个小块就叫做tile, 一个tile可以设计成16*16这么大,或者其他的size。

foreach(tile)
	load tile FBO data (color, depth, ...)
	foreach(triangle in tile)
		foreach(fragment in triangle in tile)
			call fragment shader
	store new tile FBO data

这样就有了Tile-based Rendering:

image-20211024134119943