2.8 KiB
2.8 KiB
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) 才能变成明确的帧率策略参数。