帧率与刷新率:屏幕刷新率 vs 应用帧率

做嵌入式 GUI 开发,帧率和刷新率这两个概念,我见过太多人搞混了。说白了,屏幕刷新率是硬件的能力,应用帧率是软件的表现。它们俩不是一回事,但必须配合好。

屏幕刷新率是什么?

屏幕刷新率,就是显示器每秒重绘画面的次数。单位是 Hz。比如 60Hz 的屏幕,每秒刷新 60 次。这个值由硬件决定,你改不了。

我遇到过不少工程师,拿着 60Hz 的屏,非要把帧率跑到 120fps。结果呢?画面撕裂,功耗还高。你想想看,屏幕每秒只能显示 60 帧,你多出来的 60 帧去哪了?

刷新率 每帧时间 常见场景
30 Hz 33.3 ms 低端电子纸、工控屏
60 Hz 16.7 ms 主流嵌入式屏
120 Hz 8.3 ms 高端消费电子

应用帧率又是什么?

应用帧率,是 GUI 系统实际渲染画面的速度。单位是 fps。它取决于你的 CPU 算力、GPU 性能、渲染管线效率。

举个例子。你写了个动画,每 10ms 渲染一帧,那就是 100fps。但屏幕只有 60Hz。这时候就出问题了。

核心原则:应用帧率最好等于屏幕刷新率的整数倍。60Hz 的屏,跑 60fps 或 30fps 都行。跑 45fps 反而难受。

垂直同步(V-Sync)的影响

垂直同步,说白了就是让应用帧率跟屏幕刷新率对齐。GPU 渲染完一帧,等屏幕刷新信号来了再送显。

我早期做智能手表项目时,没开 V-Sync。结果呢?屏幕上半部分显示的是第 N 帧,下半部分已经是第 N+1 帧了。用户滑动列表时,画面像被撕开了一样。这就是撕裂(tearing)。

开了 V-Sync 后,撕裂没了。但新问题来了:如果渲染一帧超过 16.7ms(60Hz 下),GPU 就得等下一个刷新周期。帧率直接掉到 30fps。用户会觉得卡顿。

注意:V-Sync 不是万能的。它解决了撕裂,但引入了输入延迟。游戏里按一下按钮,画面要等一帧才反应。嵌入式触控交互也一样。

双缓冲与三缓冲机制

为什么需要缓冲?因为 GPU 在渲染时,屏幕同时在读取显存。如果只有一个缓冲区,两边抢着读写,画面就乱了。

双缓冲:两个缓冲区,一个 front buffer(显示用),一个 back buffer(渲染用)。渲染完交换指针。简单高效。

但双缓冲有个坑。如果渲染速度跟不上刷新率,front buffer 一直没更新,用户看到的就是上一帧。这就是卡顿感。

三缓冲:再加一个中间缓冲区。GPU 可以提前渲染下一帧,不用等屏幕刷新。渲染速度波动时,画面更平滑。

机制 内存占用 延迟 平滑度
单缓冲 低 低 差(撕裂严重)
双缓冲 中 中 好(无撕裂)
三缓冲 高 高 最好(抗波动)

我记得有个车载仪表盘项目,用的双缓冲。但动画复杂,偶尔一帧渲染超时,仪表指针就跳一下。换成三缓冲后,指针平滑多了。代价是多了几百 KB 的显存开销。嵌入式设备里,这个取舍得算清楚。

我的建议:内存够用就上三缓冲。内存紧张就优化渲染管线,保证每帧在 16.7ms 内完成。双缓冲 + 稳定的帧率,效果也不差。

帧率与刷新率的协同工作流

下面这张图,是我自己总结的帧率与刷新率协同流程。每次做新项目,我都会对着它检查一遍。

帧率与刷新率协同工作流 应用渲染 CPU/GPU 生成帧 帧率控制 V-Sync / 定时器 缓冲机制 双缓冲 / 三缓冲 屏幕刷新 60Hz / 120Hz 画面输出 用户可见 常见问题 • 帧率 > 刷新率:撕裂 • 帧率 < 刷新率:卡顿 • 帧率波动:画面抖动

实际项目中的避坑指南

我曾经在一个智能家居面板项目里,遇到过一个诡异的 bug。屏幕偶尔闪一下,但频率不固定。查了两天,最后发现是帧率在 58-62fps 之间波动,跟 60Hz 的刷新率不同步。每次不同步,V-Sync 就强制等一帧,画面就闪一下。

解决办法?把帧率锁定在 60fps,或者直接关掉 V-Sync 用三缓冲。我选了后者,因为三缓冲能吸收波动。

另一个坑是双缓冲时的内存对齐。有些 MCU 的 DMA 传输要求缓冲区地址对齐到 4 字节或 8 字节。不对齐的话,传输速度慢一半,帧率直接腰斩。我建议你在初始化时检查缓冲区地址,加个断言。

经验总结:

  • 先确认屏幕刷新率,再定目标帧率
  • 帧率波动比低帧率更可怕,优先用三缓冲
  • V-Sync 不是必须的,低延迟场景可以关掉
  • 缓冲区地址对齐,能省一半 DMA 时间

嗯,帧率和刷新率这块,说白了就是让软件和硬件步调一致。你跑得快,屏幕跟不上,没用。你跑得稳,屏幕才能给你好脸色。