问题背景
为什么直接一条流水线会有性能瓶颈?
在IMR里,GPU流水线是:
提交三角形——>VS——>Raster——>FS——>输出合并
没有全局信息、没有延迟、完全按照顺序执行。
GPU在执行FS的时候,并不知道像素最终是否可见,深度测试太晚,FS已经执行完了。
带宽/计算,谁更贵?
GPU硬件关注点不同,诞生的背景。
IMR(Nvidia、AMD)主要用于PC、主机:主要是低延迟、流水线简单、吃计算(浪费一些没事),多算+多访问带宽换取简单和低延迟。
  1.带宽没那么贵
     GDDR6 / HBM 带宽可以100GB/s
  2.功耗不是第一优先级
TBDR(Arm Mail、PowerVR、高通Adreno、Apple自研)主要用于手机、平板:设计哲学是尽可能避免访问外存VRAM
   1.带宽非常贵
     LPDDR5 速度大概 几十GB/s,一次Vram访问 = 几十倍Alu成本
   2.散热限制
     带宽高——>发热——>降频
   3.电池限制
     带宽高——>电量消耗大

IMR

TBR
Binning阶段和TBDR一样。
TileRendering阶段
没有HSR。
没做延迟FS。
总结:做了Tile化,优化了带宽。但是没有像素的可见性剔除,overdraw没解决。所以进化成为TBDR。
TBDR

为什么做TBDR?
主要为了带宽优化 + 减少Overdraw。
IMR,每个像素反复读写显存。
TBDR,只在最后一次写显存。
一句话总结就是:TBDR通过tile内计算,把多次显存读写变成一次,节省带宽。
GEME(片上内存)
1.Load/Store
load : 从显存到Tile
store : 写回显存
2.Tile Flush(性能杀手)
发生在:
RenderTarget切换,Pass切换,MSAA resolve
这些都是GEME被迫写回了显存,导致带宽问题。
TBDR的执行流程
第一阶段:Binning分桶
     1.执行VS。得到ClipPos
     2.三角形组装。把顶点拼接成三角形。
     3.裁剪。裁剪视锥外的三角形。
     4.转换到屏幕空间Clip——>NDC——>ScreenSpace
     5.计算屏幕空间BoundingBox包围盒。对每个三角形算出包围盒。
     6.Tile覆盖测试。判断三角形属于哪个Tile。
     7.构建Tile Primitive List。每个Tile有个三角形的list。之后上传到TileBuffer。
第二阶段:TileRendering(片上内存处理OnChip-Memory)
     1.每个Tile有了三角形列表,以及每个三角形的插值数据(uv,normal,color…)
     2.Tile并行处理
     3.先加载Tile到片上内存,GPU在SRAM里创建TileColor[16x16],TileDepth[16x16],初始化depth和color
     4.一个Tile为例子,取出Tile的三角形列表,做光栅化。
     5.然后和TileDepth做深度测试(EarlyZ,就是TBDR的HSR),通过后进行FS
     6.更新TileBuffer的Depth和Color
     7.Tile处理完,写回显存。TileColor——>FrameColor,TileDepth——>FrameDepth。
TBDR的EarlyZ和传统的EarlyZ的区别?
IMR(Nvidia、AMD):
VS——Raster——EarlyZ——FS——LateZTest
EarlyZ是可选优化。有LateZ兜底。
失效情况:Discard、AlphaTest、修改深度、Blend
性能点:EarlyZ不稳定,FS可能重复执行导致OverDraw。
TBDR(ARM Mali/PowerVR)
VS——Binning——Tile(Raster、HSR、FS)
EarlyZ(HSR)是固定流程,必须走。没有LateZ兜底。
失效情况:几乎不会失效。但是AlphaClip会影响优化程度。
AlphaClip并不会打断HSR,为什么还会影响TBDR性能?
正常情况:在tile内,先ZTest,确定遮挡可以直接丢弃不跑FS
AlphaClip情况:不知道遮挡关系了,不知道像素的深度需不需要写入(因为不知道当前情况是不是走Clip),需要把FS跑完才知道。
结果:HSR效果下降,不确定像素是否Clip,不能丢弃当前TileBuffer上的值。多跑FS,增加了OverDraw。
SinglePassFetch
底层机制FrameBuferrFetch:移动端mali和PowerVR里,允许Tile内FS直接读取当前像素的Color结果(Depth一般不允许)。
SPF优化的是:RenderTarget读写带宽、多Pass合并为单Pass多步
比如后处理合并RenderPass,多个效果叠加一起,只执行一次Pass。
但是只能优化处理一个像素的算法,需要邻边像素结果的都不行(同Tile的邻边像素也不行)。
因为FrameBufferFetch带过来的是当前像素的上一个FS的结果,无法获取其他像素的结果。
SinglePassFetch的条件
1.必须同一个RenderPass内连续执行。
打断的情况:
RenderFeature分开执行。
Blit到RT。
CopyColor/CopyDepth。
2.RenderTarget不能变(colorAttachment和depthAttachment)
3.不能依赖邻边像素(无法利用FrameBufferFetch获取)。SSAO、TAA、半分辨率算法,这些都不行。
TBDR核心总结
TBDR优化的核心是尽量让渲染过程停留在On-Chip的GMEM中,避免和外部显存交互。
Tile Flush是其中最典型的性能开销,因为它会导致GMEM数据写回显存并可能再次加载。
但本质上从减少Load/Store、降低带宽、以及控制Tile内工作量三个角度来优化。
SubPass、SinglePassFetch这些合并Pass的方式,也是减少Load/Store的次数。