9.1 性能瓶颈分析:先找到慢在哪一环


9.1 性能瓶颈分析:先找到慢在哪一环

本节摘要:优化之前先定位。GPU 渲染的瓶颈落在三桶里:顶点处理、片元处理、内存带宽——每一桶都有特征症状与十几秒就能做完的验证实验。本节建立这套定位方法,并讲清过度绘制与绘制顺序这对性能搭档。

学习目标

读完本节,你应当能够:区分 CPU 受限与 GPU 受限;用改分辨率、换着色器两类实验把瓶颈归入正确的桶;解释过度绘制的成因与 early-z 的防护机制;说明为什么不透明物体要按由近到远排序。

慢要先慢得明白:三类瓶颈

帧率掉下来的第一件事不是改代码,是分类。GPU 侧的耗时几乎总能归进三个桶:

顶点受限——每帧要处理的顶点太多,或顶点着色器太重。症状:画面越复杂越卡(多边形数量直接相关),与分辨率关系不大。典型场景:高模角色成群、细分过猛、几何着色器滥用。

片元受限——填充率不够用了。屏幕上有太多像素要着色,或片元着色器太重,或同一像素被反复着色(过度绘制)。症状:全屏特效一开就掉帧、分辨率一降帧率回升。

带宽受限——数据搬运跟不上。纹理太大、格式太奢侈、渲染目标来回切换。症状:降画质档位(贴图精度)后显著回升,而改几何或着色逻辑都无效。

动手验证只靠两个实验就能覆盖大多数场景。降分辨率实验:把渲染分辨率砍到一半,帧率明显回升说明片元或带宽是主犯,纹丝不动则嫌疑集中在顶点或 CPU。换轻着色器实验:临时把片元着色器替换成输出纯色,回升明显说明片元逻辑太重;依旧卡,再往顶点数与带宽方向查。

别忽略 CPU 这一侧。draw call 提交本身有开销,几千次小绘制能把 CPU 先拖垮——此时 GPU 再闲也没用。判别方法:图形 API 的调用统计里看 CPU 耗时占比,或故意减少绘制数量看帧率反应。CPU 受限的解法在"合"(合批、实例化),GPU 受限的解法在"省",药方不同,所以分类必须先行。

片元受限的主角:过度绘制

片元受限的日常元凶是过度绘制(overdraw):同一个像素被多个三角形先后着色,前面算的又被盖掉。半透明物体、粒子系统、UI 叠层是重灾区——透明物没法提前淘汰(每个都真要看),只能按序混合、层层买单。

不透明几何则有一道防线:early-z。第 4 章提过,深度测试可以在片元着色器执行之前进行——如果这个像素已经被更近的几何体占据,当前片元直接淘汰,整段着色计算一分钱不花。这道防线要生效,绘制顺序必须配合:不透明物体由近到远排序。先画近的,深度缓冲里立起"墙",后面远处物体的片元大批死在着色器门口;反过来先画远的,每个片元都白算一遍再被覆盖,early-z 形同虚设。

由近到远绘制:近处角色先写深度 → 背后建筑物的片元在片元着色器之前被批量淘汰 省下整段着色 由远到近绘制:每片元都完整执行着色 → 写完深度才发现被遮挡,白算 全额付费

这个优化的迷人之处在于零代码——它只是引擎里一个排序开关,收益却经常以毫秒计。检查清单里它永远是第一行。

带宽账本:像素搬家也要钱

带宽的账本容易被忽略:一张 1080p 的 HDR 渲染目标,每帧读写往来几次就是几十 MB 的流量;4K 下翻四倍。移动端带宽还直接联动功耗——发热降频,帧率雪上加霜。

对着色器工程师,账本上最常动的三笔:其一,渲染目标与贴图格式,能用 16 位浮点就不用 32 位,能压缩贴图(GPU 压缩格式)就不存裸 RGBA——压缩格式不仅省显存,采样时的带宽开销也按压缩后算;其二,mipmap 与各向异性(第 5 章)本质是带宽优化,缓存命中率上去了,显存流量就下来了;其三,多 pass 链的分辨率,后处理的中间目标按需降采样,7.1 章的泛光正是这么做的。

移动端还要加一笔特殊的账:现代手机 GPU 多为分块渲染架构(tile-based),把屏幕切成小块在片上高速缓存里处理,带宽天生友好。但这个架构对"中途读回结果"的操作极度敏感——在块内处理完成前读渲染目标,会强制硬件反复往返显存,性能断崖。所以移动端要格外克制"渲染到纹理再读回来"的 pass 数量,能合并的后处理 pass 坚决合并。

症状 首要嫌疑 验证实验
分辨率降半,帧率翻倍 片元或带宽 换纯色着色器区分两者
多边形多的场景独卡 顶点受限 简化网格或减实例数
开全屏特效才卡 片元受限 逐个关特效定位元凶
降贴图档位后回升 带宽受限 查大贴图与渲染目标格式
GPU 闲着仍掉帧 CPU 受限 减 draw call 数量看反应
场景越乱越卡且与分辨率无关 CPU 或顶点 结合前两行二次定位

⚠️ 常见坑:凭"感觉这段代码重"去优化,十有八九打偏。现代 GPU 的深水管线会让"看起来贵"的指令被并行掩盖,而"看起来便宜"的纹理采样反而可能因缓存缺失变成大头。一切以测得的帧时间变化为准——优化前后各测一次,没有数字就没有发言权。

实战演示:一次完整的定位流程

把方法串成一个具体场景。假设某关卡帧率从 60 掉到 35,操作如下。

第一步,分侧:在引擎统计里看到 GPU 帧时间 27 毫秒、CPU 提交 8 毫秒——GPU 是主犯,CPU 侧无恙。

第二步,分桶:把渲染分辨率从 1080p 降到 720p,帧时间从 27 降到 26 毫秒——几乎没变化,排除片元与带宽,嫌疑集中到顶点侧。转身验证:把场景里成群的装饰物临时隐藏,帧时间立刻回到 14 毫秒——实锤顶点与几何数量相关。

第三步,定位元凶:帧捕获工具按开销排序,发现顶点负载集中在一个高模雕像的两次绘制,顶点着色器里还挂着一个昂贵的程序化风动画。

第四步,对症下药:雕像换成 LOD 版本(远处低模),顶点数砍掉八成;风动画里把三角函数改为查表采样;再把雕像与装饰物的绘制按材质排序合批。帧时间回到 15 毫秒,留出充足余量。

第五步,回归验证:分辨率恢复 1080p 确认帧率稳定,隐藏的物体逐批放回,确认每一批的代价都在预算内。

整套流程没有一步靠猜:每一刀之前都有数据,每一刀之后都有复测。这套"分侧、分桶、定位、处理、复测"的五步节奏,值得作为团队里性能问题的标准作业程序。

本节要点回顾

  • 三桶定位法:顶点、片元、带宽,各配特征症状;降分辨率与换轻着色器是通用验证手段;
  • 先分 CPU 与 GPU:CPU 受限靠合批,GPU 受限靠省算省带宽,药方不可混用;
  • 过度绘制与 early-z:不透明物体由近到远排序,让深度墙替你淘汰片元,零代码高收益;
  • 带宽三笔账:格式压缩、mip 与各向异性、后处理降采样,移动端尤其致命;
  • 测量先于优化:帧时间前后对比是唯一裁判,感觉不算数。

瓶颈会定位了,下一节给出具体的优化招法与黑屏排查的调试纪律。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U