


前言
为什么这么设计这节课
讲清楚手机端为什么要用TBR这种框架,让大家了解手机上存在的问题以及优化手段。
布置任务:结合今天的课程,将最近做的Demo安卓平台打包,对比观察优化后前后性能变化
有很多关于架构的内容不懂,学了一部分OpenGL后在补上。
当前移动端GPU概况

中国在TOP300中,从手机CPU(SoC)厂商来看,高通占比49.2%,相比于其他厂商有较大的优势,其次是华为28.6%,联发科21%,三星1.1%,其余CPU厂商并未进入TOP300。

GPU上,高通的Adreno与Mali的GPU市场分别占比49.2%与48.2%,而PowerVR-GPU在安卓机器上使用较少,占比仅有2.6%。
各类电子设备功耗对比
桌面级主流性能平台,功耗一般为300W(R7/I7+X60级别显卡),游戏主机150-200W
入门和旗舰游戏本平台功耗为100W
主流笔记本为50-60W,超极本为15-25W,
旗舰平板为8-15W
旗舰手机为5-8W,主流手机为3-5W。
主流PC的功耗大约是主流手机的100倍。

主流桌面端的带宽也是移动端的10倍左右。
名词解释
System on Chip(Soc)
Soc是把CPU、GPU、内存、通信基带、GPS模块等等整合在一起的芯片的称呼。常见有A系Soc(苹果),骁龙Soc(高通),麒麟Soc(华为),联发科Soc,猎户座Soc(三星),去年苹果推出的M系Soc,暂用于Mac,但这说明手机、笔记本和PC的通用芯片已经出现了
System Memory
Soc中GPU和CPU共用一块片内LPDDR物理内存,就是我们常说的手机内存,也叫System Memory,
大概几个G。此外CPU和GPU还分别有自己的高速SRAM的Cache缓存,也叫On-chip Memory,一般几百K~几M。
不同距离的内存访问存在不同的时间消耗,距离越近消耗越低,读取System Memory的时间消耗大概是On-chip Memory的几倍到几十倍。
On-Chip Buffer
在TB(D)R架构下会存储Tile的颜色、深度和模板缓冲,读写修改都非常快。如果Load/Store指令中缓冲需要被Preserve,将会被写入一份到System Memory中。
Stall
当一个GPU核心的两次计算结果之间有依赖关系而必须串行时,等待的过程便是Stall。
FillRate
像素填充率 = ROP运行的时钟频率 x ROP的个数 x 每个时钟ROP可以处理的像素个数
TBDR
Mobile:TBR(Tile-Based (Deferred) Rendering)是目前主流的移动GPU渲染架构。
PC:对应一般PC上的GPU渲染架构则是IMR(Immediate Mode Rendering)。
TBR:VS - Defer - RS - PS
TBDR:VS - Defer - RS - Defer - PS
其实2016年之后所有的手机端GPU架构都是TBDR了。
Defer就是阻塞+批处理,即等待GPU一帧的数据然后一起处理。
立即渲染

整个流水线是直接和系统内存进行交互。
TBDR

这里需要注意,第一阶段是执行所有与几何相关的信息,并生成图元列表,确定每个Tile需要绘制哪些图元,然么把这些信息提交给系统内存。
第二阶段将逐Tile执行光栅化以及后续处理,并在完成后先将结果写到线上内存(Tile Buffer),再写回系统内存。

我们对比下TBDR和IMR的不同点:
- TBDR Tilling的过程是将Tilling的数据刷到系统内存上,而不是片上内存。
- 在处理完一个Till之后,架构会将数据传输到片上内存,再传输到系统内存。

- IMR的几何处理单元和片段处理单元没有中间数据
- IMR经过片元着色器处理的数据没有存储到片上内存

TBR渲染顺序

理想情况下TBR渲染顺序
实际GPU硬件中则是乱序执行

IMR

TBR

从蓝到黄表示执行时序(蓝->黄->蓝->黄….)
TBR的优缺点
优点
(1):TBR给消除Overdraw提供了机会,PowerVR用了HSR技术,Mali用了Forward Pixel Killing技术,目标一样,就是要最大限度减少被遮挡pixel的texturing和shading。
(2):TBR主要是 cached friendly, 在cache里头的速度要比全局内存的速度快的多,以及有可能降低render rate的代价,降低带宽,省电
缺点
(1)这个操作需要在vertex阶段之后,将输出的几何数据写入到DDR,然后才被fragment shader读取。这之间也就是tile写入DDR的开销和fragment shader渲染读取DDR开销的平衡。另外还有一些操作(比如tessellation)也不适用于TBR;
(2)如果某些三角形叠加在数个图块(Overdraw),则需要绘制数次。这意味着总渲染时间将高于即时渲染模式(不理解)。
Binning过程/第一个Defer

如上图,如果一个三角形的分布横跨多个Till,那么它将会被多个Till一起渲染。

此外,如果Tilling阶段特别耗时,那么说明几何阶段的数据可能太多了。
不同GPU的Early-DT/第二个Defer(个人理解就是Early-Z)

TillList会保存Till上所有的三角形列表,难道这些三角形都要进行渲染么?当然不是,所以移动端也需要进行Early-Z操作,不同的GPU架构有不同的处理方式。而Alpha Test,Alpha Blend,关闭深度测试,手动丢弃片元或者手动修改深度值都会使得early-z失效。
Qualcomm Adreno

Arm Mail采用Forward Pixel Kill技术

Pixel Kill技术发生在Early-Z之后,如上图,在Pixel kill序列中有一个2x2的像素块,当后续提交的片元处于该像素且为不透明物体,那么再进行深度比较,如果新提交的片元深度值小于当前的深度值,那么则会舍弃当前的片元

PowerVR的HSR

针对TBDR的优化
- 记得不使用Framebuffer的时候clear或者discard
主要是清空积存在tile buff上的 frame Data,所以在unity里面对render texture的使用也特别说明了一下,当不再使用这个rt之前,调用一次Discard(就是别往GPU的TextureBuffer里渲染东西了)。在OpenGL ES上善用glClear,gllnvalidateFrameBuffer避免不必要的Resolve(till buffer的数据刷新到system memory)行为,本质上是节省带宽
这里要搞清楚一个问题,RT是什么?
https://blog.csdn.net/qq_34562355/article/details/91881523
https://blog.csdn.net/weixin_39106746/article/details/105044892?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7EHighlightScore-3.queryctrv2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7EHighlightScore-3.queryctrv2&utm_relevant_index=6
- 不要在一帧里面频繁的切换framebuffer的绑定
本质上就是减少tile buffer和system memory之间的stall操作
- 对于移动平台,建议你使用 Alpha 混合,而非 Alpha 测试。
在实际使用中,你应该分析并比较 Alpha 测试和 Alpha 混合的表现,因为这取决于具体内容,因此需要测量,通常在移动平台上应避免使用 Alpha 混合来实现透明。需要进行 Alpha 混合时,尝试缩小混合区域的覆盖范围
- 手机上如果必须要做Alpha Test,先做一遍Depth prepass(因为alpha test会让early-z失效),参考参考目录的[Alpha Test的双pass 优化思路]
- 图片尽量压缩 例如:ASTC ETC2
- 图片尽量走mipmap
- 尽量使用从Vertex Shader传来的Varying变量UV值采样贴图(连续的),不要在FragmentShader里动态计算贴图的UV值(非连续的),否则CacheMiss(因为对纹理采样并不是一次性采样一整张图,而是部分采样,所以在UV不连续的情况下,就需要多次采样)
- 在延迟渲染尽量利用Tile Buffer 存储数据
- 如果你在Unity 里面调整 ProjectSetting/Quality/Rendering/Texture Quality 不同的设置,或者不同的分辨率下,帧率有很多的变化,那么十有八九是带宽出问题啦
- MSAA(增加对framebuffer读取的次数)其实在TBDR上反而是非常快速的
https://www.jianshu.com/p/6bb3a5229a50详情参考这里
- 少在FS 中使用 discard 函数,调用gl_FragDepth从而打断Early-DT( HLSL中为Clip,GLSL中为discard )
- 尽可能的在Shader里使用Half Float,如果Shader中仅有少量FP16的运算,且FP16需和FP32混合计算,则统一使用Float,好处:
(1)带宽用量减少(2)GPU中使用的周期数减少,因为着色器编译器可以优化你的代码以提高并行化程度。(3)要求的统一变量寄存器数量减少,这反过来又降低了寄存器数量溢出风险。具体有哪些数据类型适合用half或者float 或者fix,请查看参考目录的[熊大的优化建议]和[Shader数学计算的优化技巧]
- 在移动端的TB(D)R架构中,顶点处理部分,容易成为瓶颈,避免使用曲面细分shader,置换贴图等负操作,提倡使用模型LOD,本质上减少FrameData的压力
参考文献
[GPU性能指标]
https://www.gpuinsight.com/gpu_performance/
[三星的GPU-FrameBuff指导]
https://developer.samsung.com/galaxy-gamedev/resources/articles/gpu-framebuffer.html
[英伟达的TBR教学文章]
https://www.techpowerup.com/231129/on-nvidias-tile-based-rendering
[ARM的TBR教学文章]
https://developer.arm.com/solutions/graphics-and-gaming/developer-guides/learn-the-basics/tile-based-rendering/single-page
[苹果OpenGL程序开发指南]
https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/Performance/Performance.html
[OpenGL Insights]
https://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-TileBasedArchitectures.pdf
[知乎文章:Tile-based 和 Full-screen 方式的 Rasterization 相比有什么优劣]
https://www.zhihu.com/question/49141824
[移动图形芯片的故事]
https://www.evolife.cn/html/2016/87847_5.html
[移动设备GPU架构知识汇总]
https://zhuanlan.zhihu.com/p/112120206
[再议移动平台的AlphaTest效率问题]
https://zhuanlan.zhihu.com/p/33127345
[移动平台GPU硬件学习与理解]
https://zhuanlan.zhihu.com/p/347001411
[PowerVR开发者指南]
http://cdn.imgtec.com/sdk-documentation/Introduction_to_PowerVR_for_Developers.pdf
[Performance Tunning for Tile-Based Architecture Tile-Based架构下的性能调校]
https://www.cnblogs.com/gameknife/p/3515714.html
[TBDR的HSR流程细节和使用AlphaBlend的效率提升程度]
https://www.zhihu.com/question/29904258