本节配合3.4作业参考链接使用更佳
移动端硬件概述
CPU
从手机CPU(SoC)厂商来看,高通占比最大,相比于其他厂商有较大的优势
碎碎念:SOC近几年变化有点大,麒麟被制裁,发哥崛起,骁龙经历几代三星工艺后终于在2022换台积电工艺后有超苹果趋势
性能相关可以看极客湾的评测:https://www.socpk.com/
GPU
高通的Adreno与Mali的GPU市场占比大,PowerVR-GPU在安卓机器上使用较少
与桌面端功耗对比
-
桌面端
- 主流性能平台,功耗一般300w
- 游戏主机,功耗一般150-200w
-
移动端
- 入门和旗舰笔记本,功耗一般100w
- 主流笔记本为50-60w,超极本为15-25w
- 旗舰平板为8-15w
- 旗舰手机为5-8w
- 主流手机为3-5w
-
令移动端羡慕的功耗,100倍的差距,几乎可以看做无限功耗和带宽(移动端视角)
与桌面端带宽对比
- 桌面端是将近100起步,最多可到400左右
- 移动端相比之下就少的可怜(骁龙888的移动带宽是32)
- 近几年在老黄核弹带领下,又有所突破,家用电源都1000w了(还是三星工艺这个罪魁祸首)
名词解释
SOC(System on Chip)
-
SOC是把cpu、gpu、内存、通信基带、GPS模块等整合到一起的芯片
-
常见的
- 苹果:A系SOC、M系SOC(Apple Silicon)
- 骁龙SOC(高通)
- 麒麟SOC(华为)
- 联发科SOC
- 猎户座SOC(三星)
-
M系SOC的出现,说明手机、笔记本、pc的通用SOC已经出现了。(目前就差手机没用上,但功耗还是不容小觑的)
System Memory
-
System Memory
- 就是手机内存
- 是Soc中cpu和gpu共用的一片LPDDR物理内存(桌面端是分开的,内存和显存)
- 一般为几个G(如今12/16G都有了,就很离谱)
-
On-Chip Memory
- 除了系统内存外,cpu和gpu还分别有自己的高速SRAM的Cache缓存,叫作On-Chip Memory
- 一般为几百K~几百M
- 类似CPU的一缓二缓三缓
-
访问不同距离的内存需要消耗的时间不同
- 距离越近的时间消耗越低
- 读取System Memory 的时间消耗大约是 读取On-Chip Memory的几倍~几十倍
- 尽量避免cache miss
On-Chip Memory
- 在TBDR架构下,会存储Tile的颜色、深度和模板缓冲
- 其读写、修改速度都非常快
Stall
- 当一个GPU核心的两次计算之间有依赖关系而必须串行时,等待的过程就是Stall
FillRate
- 像素填充率 = ROP运行的时钟频率 × ROP的个数 × 每个时钟的ROP可以处理的像素个数
- 衡量GPU性能的有效工具
- 补充资料
桌面端GPU架构:立即渲染(IMR)
- 先经过vertex shader的处理
- 再经过一个类似管道(先进先出)的顺序,最终提交给Fragment Shader(收到三角形就开始渲染)
- Fragment Shader最终将结果刷新到FrameBuffer
- 每个renderpass中有各种DrawCall
- 每个DrawCall里有很多图元
- 我们首先要对每个图元中的顶vertex shader进行处理
- 如果这个图元没被剔除,就对它里面的fragment进行Fragment shader的处理
- 用户数据经过:顶点处理 → 剔除,投影 → 光栅化 → Early Visibility Test → Alpha Test → Late Visibility Test → Alpha Blend 最终将结果刷到FrameBuffer里
- 整个过程直接和系统内存进行交互
移动端GPU架构:基于块元的渲染(TBDR)
简述
- TB(D)R(Tile-Based(Deferred)Rendering),是目前主流移动GPU的渲染架构,对应一般PC上的GPU架构则为IMR
- 个人理解
- 屏幕被分块(16*16 or 32*32)渲染,先决定每块内有哪些图元,所以需要等所有顶点着色器完毕,由于on chip memery比较小,所以一个块一个块渲染,渲染完毕后再记录回系统内存。这样做不能提高帧率,但可以降低功耗和带宽使用
TBR和TBDR的区别
- TBR:VS - Defer - RS(光栅化) - PS
- TBDR:VS - Defer1 - RS - Defer2 - PS
- 通过这第二个Defer,PowerVR的渲染架构真正最大程度上实现了“延后(Defer)PS的执行”,以避免执行不必要的PS计算与相关资源调用的带宽开销,以达到最少的性能消耗和最高的渲染效率
- 有些文章会将TBR叫作TBDR,所以看资料的时候,要搞清楚它说的"D"是指第一个Defer还是第二个
- 现在的手机基本都是TBDR架构了,但是受到提出TBDR的PowerVR公司的产权保护限制,大家都不敢说是TBDR架构
Defer的理解
- 字面上是:延迟
- 渲染数据角度来看,Defer就是“阻塞+批处理”(GPU累积一帧的多个数据,最后一起处理)
- 下面会介绍两个Defer做了什么
TBDR的渲染顺序
TBDR详细的渲染流程
-
第一阶段
- 执行所有与几何相关的处理,并生成Primitive List(图元列表)
- 并且确定每个Tile(块)上有哪些Primitve(图元)
- 这里形成了Defer,要等第一阶段处理完,而且这一阶段还会将数据写入系统内存和第二阶段交互,所以顶点数据过大会成为瓶颈
-
第二阶段
- 执行光栅化及后续处理
- 并在完成后,将FrameBuffe从Tile Buffe写会到System Memory中(相比于传统的立即渲染架构,不是直接写回系统内存,而是写到片上内存(On-chip Memory)里)
- TBDR架构中,多了一步Tiling的过程,这一步是:将顶点处理经过剔除、投影的几何数据刷到系统内存(System Memory)上
- HSR:目的是筛选出Tile里所有片段中最终实际渲染的那一部分,这个过程本质上来说就是改进版Early Depth Test,用处也是用来减少overdraw
- Tiling:将顶点处理形成的各种几何数据刷到系统内存上
- 把结果刷到片上内存,最终片上内存才会把内容刷到Frame Buffer里,也就是系统内存
伪代码
-
第一阶段(Pass one)
- 对每个renderpass里的DrawCall,每个DrawCall里的图元,先进行Vertex shader处理
- 找到每个块元(Tile)上有哪些图元(Primitve)
-
第二阶段(Pass two)
- 对每个块元执行每个renderpass
- 对每个块元上的图元进行Fragment Shader处理
总结
- 核心目的
- 为了降低带宽,减少功耗,但渲染帧率上并不比IMR快
-
优点
-
给消除OverDraw提供了机会:
- PowerVR有HSR技术,Mali有Forward Pixel Killing技术,都有为了最大限度减少被遮挡的pixel的texturing和shading
-
缓存友好(Cache friendly),在cache的读写速度要比全局内存中快得多(以降低帧率为代价,降低带宽、功耗)
-
-
缺点
- binning过程是在vertex阶段之后,将输出的数据写到系统内存(DDR)上,然后才能被fragment shader读取,这样一来几何数据过多的管线,容易在此处有性能瓶颈
- 如果某些三角形叠加在数个tile(块)上,会被绘制数次,这样就意味着:总渲染时间多于IMR
IMR 和 TBR对比
TBR简易图
- 几何处理数据形成了FrameData(放在System Memory上)
- 这些Frame Data经过片段处理,结果放在了Tile Buffer上(片的内存上)
- 最后的结果会刷到FrameBuffer中(System Memory)
IMR简易图
- 几何处理数据直接到片段处理,没有中间数据(Frame Data)
- 直接刷到System Memory上了,没有经过片内存(On-Chip Memory)
渲染流程图对比
可以看到TBR是分块渲染,而IMR是按三角形提交的顺序渲染
实际中GPU硬件中的乱序执行
从蓝到黄表示执行时序(蓝->黄->蓝->黄)
- IMR架构(IMR-NVIDIA Quadro 600)
- 从左到右,再从右到左的渲染顺序
- 蓝黄交界的地方会有很多犬牙交错的地方,这些地方是因为GPU乱序执行,具有一定的随机性
- TBR架构(TBR-Qualcomm Adreno 430)
- 顺序是按照块状的渲染顺序执行的
- 黄色跟蓝色的过渡的地方有一些犬牙交错的现象
第一个Defer:Binning过程
- 目的:确定哪些图元属于哪些块元渲染
- 过程:
- 第二幅图里的红色三角形,只用一个块元就能渲染,所以它只会被分配到一个块元中
- 第四幅图里的棕色三角形,需要多个块元才能渲染,所以它需要分配到9个块元中一起渲染
- 帧调试软件
- 一款老的骁龙gpu调试器下的binning参数(红线代表tile的范围)可以显示每个块元的性能参数
- binning过程的耗时占比参考,如果你的项目中binning过程相比其他耗时长的话,就要考虑一下是不是几何数据过多了
- 一款老的骁龙gpu调试器下的binning参数(红线代表tile的范围)可以显示每个块元的性能参数
第二个Defer:不同GPU 的 Early-Depth-Test
和EarlyZ的本质区别:https://www.zhihu.com/question/425740956
Adreno的LRZ模块
- 采用外置模块LRZ
- 在正常渲染管线之前,先多执行一次vs生成低精度depth texture,来提前剔除不可见的三角形(实现细节不知)
- 用硬件实现occlusion culling(遮挡剔除),功能类似软光栅中的遮挡剔除
Mail的FPK
-
采用Forward Pixel Kill技术
-
位于管线的位置:发生在Early-z之后
-
数据模型:先进先出的队列
-
简单概括一下:
- 队列中有4个Quad(可以理解为2×2像素的平面),每个Quad有屏幕上位置的数据和Z数据
- Z越大代表离摄像机越远
- 根据屏幕上相同位置(pos)的不同z,对不透明的像素进行替换(有近的就不渲染远的),这个过程叫作killed
PVR的HSR
- Hide Surface Removal隐形面剔除
- 大体实现原理:
- 虚拟出一个射线,当它遇到第一个不透明的物体时就会停下来,这样就会打断后面三角形的后续ps处理
优化建议
- 记得在不使用FrameBuffer的时候clear或discard
- 这样做主要是为了清空积存在tile buffer上的中间数据
- 所以对Unity里的rt(render texture)的使用也特别说明一下,当我们不再使用这个rt的时候,尽量调用一次Discard
- 在OpenGl ES上,要善用glclear,glInvalidateFrameBuffer,避免不必要的Resolve(tile buff刷新到system memory)行为
- 不要在一帧里频繁的切换FrameBuffer的绑定
- 本质:减少tile buffer和system memory之间的stall(同步)操作
- 对于移动平台,建议使用Alpha混合,而非Alpha测试
- 是一个经验性的结论
- 在实际使用的过程中应该使用比较两者的表现
- 通常情况下,移动端应该避免使用Alpha混合来实现透明,如果确实要用,尝试缩小混合区域的覆盖范围
- 手机上必须用Alpha Test时,先做一遍Depth Prepass(参考Alpha Test 的双pass优化思路)
- 图片尽量压缩,例如ASTC 、ETC2
- 图片尽量走mipmap
- 尽量使用从vertex shader传来的Varying变量uv值采样贴图(连续的),不要在Fragment shader里动态计算贴图的uv值(非连续的),否则CacheMiss
- 在延迟渲染中,尽量利用Tile Buffer(参考传统延迟渲染和TBDR)
- 如果在Unity中调整ProjectSetting—Quality—Rendering—Texture Quality的不同设置,或者不同分辨率下,帧率有很大的变化,大概率是带宽出问题了
- MASS在TBDR下反而是非常快速的
- MSAA是硬件上的,发生在片上的
- 相比FSAA,MSAA在手机上是非常快的
- 少在Fragment shader中使用discard函数,调用gl_FragDepth从而打断Early-DT的过程(hlsl中为Clip,glsl中为discard)
- 在shader使用浮点数精度值时,有目的的区分使用float,half
- 优点
- 带宽减少
- GPU中用的周期数减少,因为着色器编译器可以优化你的代码来提高并行化程度
- 要求的统一变量寄存器的数量减少,这样反而又降低了寄存器数量溢出风险
- 具体参考:熊大的优化建议、shader数学计算优化技巧
- 在移动端的TBDR架构中,顶点处理部分(Binning过程)容易成为瓶颈
- 避免使用曲面细分shader,置换贴图等负操作
- 提倡使用模型LOD,(本质上减少Frame Data的压力)
- Unity中尽早的在应用阶段做umbra(Unity内置)遮挡剔除、gpu的occlusion cull
参考链接
- [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教学文章]
- [苹果OpenGL程序开发指南]
- [OpenGL Insights]
https://www.seas.upenn.edu/~pcozzi/OpenGLInsights/OpenGLInsights-TileBasedArchitectures.pdf
- [知乎文章:Tile-based 和 Full-screen 方式的 Rasterization 相比有什么优劣]
https://www.zhihu.com/question/49141824
- [移动设备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/49141824
- [当我们谈优化时,我们谈些什么]
https://zhuanlan.zhihu.com/p/68158277
https://edu.uwa4d.com/course-intro/1/179
- [Alpha Test的双pass 优化思路]
https://zhuanlan.zhihu.com/p/58017068
- [个人收藏]
https://github.com/killop/anything_about_game#gpu-architecture
- [Adreno Hardware Tutorial 3: Tile Based Rendering]
https://www.youtube.com/watch?v=SeySx0TkluE&pbjreload=101
- [Mali GPU的独有特性]
https://www.cnblogs.com/hamwj1991/p/12404551.html
- [Mali-T880]
http://grmanet.sogang.ac.kr/ihm/cs170/20/HC27.25.531-Mali-T880-Bratt-ARM-2015_08_23.pdf
- [熊大的优化建议]
http://www.xionggf.com/post/unity3d/shader/u3d_shader_optimization/
- [GPU画像素的顺序是什么]
https://zhuanlan.zhihu.com/p/22232448
- [Tile-based Rasterization in Nvidia GPUs with David Kanter of Real World Tech]
https://www.youtube.com/watch?v=Nc6R1hwXhL8&t=973s&pbjreload=101