Files
2026-07-23 13:41:30 +08:00

2.8 KiB
Raw Permalink Blame History

startRender(int fps) 作用流程 FAQ

startRender(int fps) 做了什么

startRender(int refreshTimesPreSecond) 只做两件事:

保存 mRefreshTimesPreSecond
调用 startRender()

对应代码流程:

Plot::startRender(int fps)
    ↓
d->mRefreshTimesPreSecond = fps
    ↓
Plot::startRender()

startRender() 做了什么

startRender() 的作用是启动 Plot 的渲染调度。

流程:

检查 Plot 是否正在析构
    ↓
mRenderEnabled = true
    ↓
投递任务到 asio scheduler
    ↓
取消旧 mRenderTimer
    ↓
scheduleRenderTimer()
    ↓
submitRender()

它会立即触发一次 submitRender(),不是等下一个 timer 周期。

fps 参数现在是不是严格帧率上限

不是。

当前 fps 只决定 asio timer 的周期:

interval = round(1000.0 / fps)

timer 到期后:

submitRender()
scheduleRenderTimer()

所以它的真实语义是周期性 heartbeat / 兜底触发,不是硬性 FPS cap。

为什么不是严格限帧

因为当前渲染是事件驱动为主。

除了 timer 会触发 submitRender(),下面这些路径也会立即触发:

RenderAble::markStateDirty()
    ↓
Plot::markRenderStateDirty()
    ↓
requestRender()
    ↓
submitRender()
RenderData::markInputDirty()
    ↓
RenderAble::markRenderDirty()
    ↓
requestRender()
    ↓
submitRender()
finishRender()
    ↓
pipeline.hasNewState()
    ↓
submitRender()

只要 State/Input 有新版本,系统可以绕过 timer 周期继续推进下一帧。

asio 里面还有没有定时器

有。

相关成员和函数:

PlotPrivate::mRenderTimer
PlotPrivate::mRefreshTimesPreSecond
Plot::scheduleRenderTimer()
RenderScheduler::initializePlotOnScheduler()

RenderScheduler::initializePlotOnScheduler() 为每个 Plot 创建 asio::steady_timer

scheduleRenderTimer() 使用 mRefreshTimesPreSecond 计算间隔并注册 async_wait

timer 在当前架构里还有没有必要

当前仍然有必要保留。

原因:

保持 startRender(int) 旧调用语义
保证没有显式 dirty 事件时仍有周期性检查
作为异常丢事件后的兜底触发
给性能测试框提供一个稳定的周期参考

但它不是渲染正确性的唯一入口。

当前正确性主要依赖:

State dirty
Input dirty
finishRender 后续版本检查

如果以后要严格限帧应该怎么做

应该新增独立调度策略,而不是继续复用 startRender(int) 的现有语义。

建议拆成:

Immediate
    dirty 后立即 requestRender()

FixedRate
    dirty 后只标记 pending,由 timer 周期统一 submitRender()

Throttle
    dirty 后允许立即渲染,但两帧之间必须满足最小间隔

这样 startRender(int) 才能变成明确的帧率策略参数。