[性能] 方案 D:静态几何预烘焙进不变 VBO —— A→C 落地后实测只剩 2.8 µs/帧可省,请先裁决是否还做 #17
Labels
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Blocks
#16 [性能] 渲染主循环掉到 20 tps:零视口剔除(88.6% 白画)+ 图集页切换导致单帧最高 3077 次 draw call
troytt/diablo2-web
Reference: troytt/diablo2-web#17
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
拆自 #16 的方案 D。开这个 issue 主要是为了把它关掉或降级:A→C 落地(
4cc49a0)之后,重新测了一遍,D 的收益空间已经基本不存在了。方案原意
地面/墙/屋顶的顶点在整个关卡生命周期里一个 float 都不会变(相机是 uniform,不进顶点)。所以可以在关卡加载时把它们烘进
STATIC_DRAW的 VBO,每帧只按剔除结果调整drawElements的 offset/count,动态缓冲里只剩角色和少量动画对象,把每帧的 CPU 顶点写入降到接近 0。为什么现在不值了
写 #16 的时候,每帧要写 2 849 个四边形(最差 14 400),顶点写入是实打实的热点。视口剔除之后每帧只剩 204 个(最差 437),把当前渲染器里那段展开后的顶点写入单独拎出来跑基准(Node 22,5 000 帧取平均):
也就是说 D 的理论收益上限是 2.8 µs/帧(最差 5.8 µs),占 16 ms 预算的 0.02%。
代价
不便宜。要维持画家序,静态 VBO 必须按「地面 / 墙+对象归并 / 屋顶」三段各自连续存放,而剔除后留下的是不连续的下标集合,一次
drawElements只能画一段连续区间。要么:drawElements—— 直接把刚压到 1 的 draw call 又打回去;墙和对象还是两路按深度归并出来的,顺序依赖运行时的玩家深度,本身就不是静态的。
建议
关掉,或者标成 P3 挂着。 除非以后实机 profile 里顶点写入重新变成热点(比如取消剔除、或者视口大幅变大),否则不建议花这个复杂度。
请裁决:关闭 / 降级挂起 / 仍然要做。
(复现口径见 #16 的评论;基准脚本是把
SpriteRenderer.quad()展开后的写入循环单独隔离出来跑的。)按实测关闭:视口剔除落地后,顶点写入只剩 2.8 µs/帧(最差 5.8 µs),占 16 ms 预算的 0.02%,而静态 VBO 为了保画家序只能画连续区间、剔除后留下的却是不连续下标,绕开的代价会把刚压到 1 的 draw call 又打回去 —— 收益与复杂度完全不成比例。
如果以后实机 profile 里顶点写入重新成为热点(取消剔除、视口大幅变大、或每帧四边形数量级回升),再重开。