先理解TBDR GPU 的工作方式
TBDR
Tile-Based Deferred Rendering
T 表示 分块渲染
D 表示 延迟写回外部显存
简化流程:
CPU 提交 DrawCall
↓
GPU 先 Bin/Tiling
↓
把三角形分到 Tile
↓
每个 Tile 在片上缓存中渲染
↓
最后一次性写回显存例如:
- 屏幕 2048×2048
- 分成很多 32×32 / 64×64 tiles
GPU:
- 不会立刻写 framebuffer
- 而是在 GMEM/tile memory 里做
- 最后统一 resolve
这就是为什么:
“避免中途打断 Tile”
极其重要。
移动端最重要的优化目标
优先级基本是
- 减少 Fragment Cost
- 减少 Overdraw
- 减少带宽
- 减少 Tile Flush
- 减少 Shader ALU
- 减少 Vertex Cost
移动端和 PC 最大区别:
Fragment/Bandwidth >>> Vertex
PC:
- 往往 vertex 更贵
移动:
- fragment + bandwidth 才是真正瓶颈
不透明物体渲染原则
尽量保持Shader可 Early-z
不透明物体避免:
clip()
discard
alpha test透明物体渲染原则
因为透明物体 = 无 Early-Z
少用透明物体
少用大面积透明
少用Alpha Blend
优先:
AlphaClip Dither粒子减少屏幕覆盖
粒子数量不是最大问题,屏幕覆盖率才是,1000小粒子可能比1个全屏Smoke便宜.
避免 TileFlush
Shader优化重点
half 优先于 float
减少 texture sample
避免动态分支
hlslif(x > 0)移动 GPU SIMD divergence 成本高。
变体数量控制
VR特有优化
Single Pass Instanced
Fixed Foveated Rendering
降低 Fragment Density
这是一个不得已的操作,为了保证玩家的实际体验,不建议开发者降低渲染分辨率,因为在VR中,分辨率的降低导致的锯齿与不真实感更容易被感知.
渲染路径的选择
Forward 或 Forward+ 渲染路径
如果场景实时灯光数量在2个或以下,使用Forward
如果场景实时灯光数量在2个以上,使用 Forward+
减少外部显存带宽
避免Grab Pass
在URP中 Grab Pass 就是
_CameraOpaqueTexture本质上就是读取当前已经渲染好的屏幕颜色
正常TBDR的理想情况
GPU :
Tile A
↓
在GMEM里完成所有绘制
↓
最后一次性写显存GrabPass 会发生什么
假设:
你渲染到一半:
现在需要读取屏幕颜色但是当前颜色还在 Tile Memory 里
还没写回显存.
于是 GPU 被迫:
GMEM
↓ resolve/store
外部显存然后:
shader 才能:
sample screen texture这就是:
强制 Tile Resolve
避免Camera Stack
什么是 Camera Stack
URP :
Base Camera + Overlay CameraOverlay Camera常用于
- UI
- 武器
- Protal
- 小地图
在 TBDR 上的问题
理想情况:
一次完整 RenderPassGPU 可以:
Tile 保持在 GMEM直到结束。
Camera Stack 会导致:
Camera A 结束
↓
Store Tile
↓
Camera B 开始
↓
Reload Tile为什么?
因为:
第二个 Camera:
需要:
读取前一个 Camera 结果避免 Fullscreen RT 切换
示例
Render Scene → RT_A
↓
Bloom → RT_B
↓
Color Grade → RT_C
↓
Final Blit在 TBDR 上的问题
每次:
切 RenderTarget都可能:
Store 当前 Tile
+
Load 新 Tile为什么?
因为:
GPU Tile Memory:
一次只能工作在:
当前 RenderPass实际代价
例如:
1080p:
1920×1080×4 bytes一次 fullscreen RT:
就可能:
几十MB带宽避免多MRT
MRT 是什么
Multiple Render Targets:
SV_Target0
SV_Target1
SV_Target2一次 fragment:
输出多个 buffer.
为什么伤带宽
例如:
RGBA8 × 4 MRT一次 pixel:
16 bytes+MSAA 更糟
4x MSAA:
16 × 4
= 64 bytes/pixel非常恐怖。
术语解释
**Tile Flush : **GPU 被迫把原本暂存在片上缓存里的 Tile 数据,提前写回显存.
GMEM : GPU块缓存