想象你是一家餐厅的主厨。客人一波接一波进门,你不能像工厂那样只做一批菜就下班——你必须一轮接一轮地重复同一个工作节拍:抬头看新客人(接收输入)、备菜烹饪(更新游戏逻辑)、摆盘上菜(渲染画面),然后立刻开始下一轮。这一轮完整的工作,就是游戏世界里的一「帧」。游戏引擎的本质,就是把这个厨房节拍无限循环下去的程序骨架。而帧管理要解决的,和餐厅管理如出一辙:每道菜该多久出一次(帧率)、忙时怎么不让厨房挤爆(掉帧)、如何让流水线不互相撞车(同步)。本文用这场永不散席的「厨房节奏」贯穿始终,从零讲透游戏循环的结构、时间步长、帧率指标、渲染同步、卡顿诊断与优化实战。

岗位关联

对 AI 从业者而言,游戏循环是引擎暴露给外部世界的「心跳」——无论是强化学习代理采集状态、自动化测试注入操作,还是数据驱动调参,都先要读懂这记心跳。

目录
  1. 可视化演示
  2. 游戏循环原理
  3. 时间步长策略
  4. 帧率性能指标
  5. 渲染同步机制
  6. 掉帧卡顿诊断
  7. 帧管理优化实践
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示游戏循环四阶段流程、固定与可变步长对比及帧预算优化策略,交互切换理解游戏引擎核心机制。

本节配有交互动效(进入视口后自动加载,约 3KB)。

'+modeData.loop.caption+'

游戏循环原理

想象你是一家餐厅的主厨。客人一波接一波进门,你不能像工厂那样只做一批菜就下班,必须一轮接一轮地重复同一种节拍:抬头看新客人、备菜烹饪、摆盘上菜,然后立刻开始下一轮。游戏引擎也一样——它的心脏是一个永不停歇的循环,这个循环统率着整个程序从启动到退出的全部生命。

游戏循环中的「一帧」不是一张图片,而是一次完整的「输入采样 → 逻辑更新 → 画面渲染」周期。输入采样好比扫一眼门口有没有新客人;逻辑更新好比根据菜单改变食材状态,比如角色掉血、子弹飞行;画面渲染好比把这锅菜摆盘端出去。引擎每完成一轮周期,屏幕就多一帧画面。

主流引擎的驱动核心都遵循同样的骨架:while (running) { 处理输入; 更新世界; 渲染; }。Unity 把它拆成 Update 与 FixedUpdate 两层,Unreal 用 Tick 驱动 Actor 更新,Godot 的 _process 也是同一角色。无论名字怎么变,循环的每一轮耗时都可以清晰地拆解:

四种耗时的总和决定一帧花多久。好领班不会让任何一环拖后腿:输入不能长时间阻塞,逻辑更新不能塞进重活,渲染更不能独自吃掉全部预算。只要一个环节超时,整轮出菜就会顺延,玩家的感受立刻是「卡」。

Tframe=Tinput+Tupdate+Trender+Tidle\displaystyle T_{\text{frame}}=T_{\text{input}}+T_{\text{update}}+T_{\text{render}}+T_{\text{idle}}
一帧的总耗时等于输入、更新、渲染三部分实际用时,再加上引擎主动让出的空闲等待时间。
  1. 总帧时间T_frame 是本轮循环从开始到结束的总耗时,也是决定帧率的唯一分母。
    TframeT_{\text{frame}}
  2. 输入采样耗时T_input 是读取键盘、鼠标、触摸、网络消息等输入事件所花的时间,对应后厨抬头看新客人的动作。
    TinputT_{\text{input}}
  3. 逻辑更新耗时T_update 是物理、AI、动画、脚本等逻辑结算的总耗时,相当于备菜与烹饪。
    TupdateT_{\text{update}}
  4. 渲染提交耗时T_render 是 CPU 向 GPU 提交渲染指令的时间,GPU 真正执行往往异步进行,对应把菜装盘递出。
    TrenderT_{\text{render}}
  5. 空闲等待耗时T_idle 是引擎主动休眠、等待帧节奏的余量时间,它等于 0 说明厨房已经满负荷运转。
    TidleT_{\text{idle}}

时间步长策略

同样是炒一盘青菜,火大时 20 秒出锅,火小时拖到 40 秒。如果厨师每轮都固定翻十下铲子、加一勺盐,全然不管实际过了多久,火候一变味道就全乱了。游戏里也有这个陷阱:如果每帧把角色往前移固定一段距离,帧率高的机器上角色跑得飞快,帧率低的机器上像个蜗牛——同一个游戏,物理世界却各不相同。

解法是让逻辑更新感知真实时间,这个参数就是 delta time(Δ t),记录上一帧到这一帧实际流逝的秒数。移动不再是「每帧走多少」,而是「每秒走多少,再乘以真实耗时」:

可让更新完全跟着帧率走又会惹祸:物理碰撞、网络同步都要求可复现的确定性,帧率一波动结果就漂移。于是有了固定时间步(fixed timestep):逻辑更新固定以 1/60 秒为一步推进,渲染帧照常自由输出。经典实现是累加器算法——把真实流逝的时间攒起来,攒够一个 1/60 秒就执行一次更新,剩余部分用插值补到渲染画面上。这好比餐厅规定备菜必须按 30 秒一格推进,出菜节奏忽快忽慢,但每道菜的火候永远一致。

固定步长给了世界确定性,插值补回了平滑度。两者的配合,就是后厨在「标准火候」与「实际出菜」之间找到的平衡。

pos′=pos+v×Δt\displaystyle \text{pos}'=\text{pos}+v\times\Delta t
新位置 = 旧位置 + 速度 × 时间步长。这是所有游戏物理运动的基石。
  1. 更新后位置pos' 是本轮逻辑更新后的新位置,由上一轮位置与速度共同决定,将成为下一轮的起点。
    pos′\text{pos}'
  2. 前一帧位置pos 是逻辑更新前的位置,也就是上一轮更新计算出的结果。
    pos\text{pos}
  3. 速度向量v 是物体的移动速度,包含大小与方向,是玩家操作或 AI 决策的输出。
    vv
  4. 时间增量Δ t 是更新步长——可变时间步下为两帧真实间隔,固定时间步下为常量 1/60 秒。
    Δt\Delta t
  5. 累加器门槛固定时间步每次循环检查累加器是否攒够一个步长,条件成立才执行一次物理更新。
    accumulator≥step\text{accumulator}\geq\text{step}

帧率性能指标

客人评价一家餐厅常说「平均 30 秒上一道菜」,可如果你偏偏坐在高峰期最忙的那张桌,整整 3 分钟没看到菜,你会认同这个平均分吗?帧率世界的坑一模一样:玩家骂的「卡」,从来不是平均 FPS 太低,而是某一瞬间帧时间突然飙到极限。

FPS(Frames Per Second)是每秒输出的帧数,与帧时间互为倒数:一帧 16.7ms 对应约 60FPS,8.3ms 对应约 120FPS。工程上更爱看帧时间曲线而不是 FPS 均值,因为一次 300ms 的卡顿被 60 帧平均一摊,几乎消失不见,却会让玩家直观地顿一下。

为了量化「最差感受」,行业引入了 1% low 指标:把一帧的帧时间从短到长排序,取最长的那 1% 帧求平均,再换算成帧率。这个数越接近平均 FPS,说明体验越稳定。基准测试也随之升级:光报告平均 60 不够,还要保证 1% low 不低于某条线,比如 50。移动端 Profiler、Steam 性能测试、主机认证都遵循这套逻辑。

评价出菜水平,要看最忙时段菜等了多久,而不是打烊后算的平均时间——帧率指标同理。

FPS=1000 msT‾avg\displaystyle \text{FPS}=\frac{1000\ \text{ms}}{\overline{T}_{\text{avg}}}
FPS = 1000 毫秒 ÷ 平均帧时间(毫秒)。16.7ms 对应 60FPS,这是帧率世界的度量衡。
  1. 平均帧时间T_avg 是统计窗口内所有帧时间的算术平均,单位毫秒。
    T‾avg\overline{T}_{\text{avg}}
  2. 毫秒折算1000 ms 表示 1 秒包含的毫秒数,它把单个周期的耗时换算成每秒的频次。
    1000 ms1000\ \text{ms}
  3. 帧率结果FPS 即每秒渲染帧数——60 为流畅,30 为勉强可玩,120 为电竞级顺滑。
    FPS\text{FPS}

渲染同步机制

后厨与传菜口之间有一扇窄门。厨师要是完全不管传菜窗口的状态,埋头把菜往外递,就会和端着空盘往回走的服务员撞在一起,菜盘打翻——新炒的料和凉掉的底混在同一盘里端上桌。屏幕上这叫画面撕裂(tearing):显示器还没来得及画完上一帧,GPU 已经把下一帧送过来了,一屏里出现一条扭动的「接缝」。

垂直同步(VSync)就是引擎与显示器约定的传菜窗口:显示器的刷新是固定周期的,60Hz 下每 16.7ms 一个窗口。GPU 只在窗口打开时提交画面,错过就等下一轮。这个等待周期,成了所有帧预算的总闸门:

为了让 CPU 和 GPU 不互相空等,引擎普遍引入双缓冲乃至三缓冲:CPU 提前准备下一帧(后厨先备菜),GPU 正在绘制上一帧(菜已上桌),通过交换链交接。代价是缓冲越多,延迟越高。若一帧渲染超过 16.7ms,就会错过窗口,帧率直接砍半到 30FPS。可伸缩刷新率的 VRR 技术(FreeSync、G-Sync)把固定窗口改成弹性窗口,从根上解决这个难题。

同步的本质不是跑得更快,而是让后厨、传菜口、餐桌三条线对齐节奏。

Tvsync=1frefresh,60 Hz⇒16.7 ms\displaystyle T_{\text{vsync}}=\frac{1}{f_{\text{refresh}}},\qquad 60\,\text{Hz}\Rightarrow 16.7\,\text{ms}
垂直同步周期 = 1 ÷ 显示器刷新率。60Hz 对应的 16.7ms 就是每帧的时间总预算。
  1. 刷新周期T_vsync 是显示器两个刷新动作之间的时间间隔,所有帧都必须赶上它的节拍。
    TvsyncT_{\text{vsync}}
  2. 刷新率f_refresh 是显示器每秒刷新次数,60Hz 表示每秒刷新 60 次,它是窗口频率的定义者。
    frefresh=60 Hzf_{\text{refresh}}=60\,\text{Hz}
  3. 周期换算1 除以刷新率得到周期秒数,再换算成毫秒,约等于 16.7ms。
    160 s≈16.7 ms\frac{1}{60}\,\text{s}\approx 16.7\,\text{ms}

掉帧卡顿诊断

领班最怕的不是出菜慢,而是出菜节奏突然断裂——前 10 道菜间隔均匀,第 11 道忽然让人干等 1 秒。玩家对稳定的低帧率反而能适应,对这种「咯噔」却格外敏感。掉帧(frame drop)指某一帧实际耗时远超预算,卡顿(stutter)是掉帧在时间轴上聚集起来的结果。

掉帧的成因通常能分类排查:CPU 侧逻辑超时(一次大规模物理结算、一次垃圾回收、一次资源流式加载);GPU 侧渲染超时(复杂着色器、过度绘制);还有同步阻塞(CPU 等待 GPU 回读、等待垂直同步窗口)。诊断第一步永远是抓帧——用 Profiler 把每一帧内各系统的耗时摊开看,看时间被谁偷走。

量化卡顿最硬核的指标是 1% low:把帧时间排序,取最差 1% 帧求平均再换算成帧率。它的含义就是「最忙时段的平均出菜速度」。配合帧时间曲线,一眼就能看出哪些是孤立的尖峰(瞬时加载),哪些是周期性的毛刺(GC 抖动),哪些是持续的高台(画质超配)。

把帧时间曲线当病人的心电图看——孤立的尖峰、连续的锯齿、抬高的平台,各有各的病根。

1%low=1000 msT‾worst 1%\displaystyle \text{1\%low}=\frac{1000\ \text{ms}}{\overline{T}_{\text{worst }1\%}}
1% low = 1000 毫秒 ÷ 最差 1% 帧的平均帧时间,它代表玩家在卡顿时段真实感受到的帧率。
  1. 最差1%样本把一长段帧时间从短到长排序,取最长的那 1% 帧集合,作为劣化体验的代表。
    T‾worst 1%\overline{T}_{\text{worst }1\%}
  2. 集合求均值对这 1% 帧的时间求算术平均,得到最差时段的典型耗时。
    T‾=1N∑i=1NTi\overline{T}=\frac{1}{N}\sum_{i=1}^{N}T_i
  3. 换算帧率用 1000 毫秒除以平均耗时,得到 1% low 帧率,数值越低说明卡顿越明显。
    1%low=1000T‾worst 1%\text{1\%low}=\frac{1000}{\overline{T}_{\text{worst }1\%}}

帧管理优化实践

高峰期的餐厅如何保住口碑?无非三招:给每道菜定死预算,超时就简化摆盘;让多个厨师各管一摊并行干活;把费火的菜提前炖上。游戏帧管理正是这三招的工程化。

帧预算(frame budget)把 16.7ms 切成 CPU 与 GPU 两块,超支的系统必须当场降级:最常见的是动态分辨率(DRS)——GPU 超时就把渲染分辨率从 1080p 降到 900p,帧率稳住再升回去;此外还有 LOD 切换、阴影降级、体积雾简化。预算纪律写成公式就是:

多线程渲染把「准备指令」与「提交指令」拆开:逻辑线程算完世界状态,渲染线程录制 command list,交给 GPU 并行执行;对应厨房就是切配、改刀、掌勺各司其职。移动端还要多管一件事——功耗:SoC 一过热就降频,帧率会莫名减半,所以移动游戏普遍用动态帧率上限、自适应画质,甚至锁 30/45FPS 换稳定。云游戏则把帧率波动折算进码率与延迟的权衡里。

帧管理的哲学很简单:不求哪道菜惊艳,但求每道菜都准时。守住 16.7ms 那扇门,整条流水线就稳定。

TCPU+TGPU≤Tbudget=16.7 ms\displaystyle T_{\text{CPU}}+T_{\text{GPU}}\leq T_{\text{budget}}=16.7\,\text{ms}
CPU 耗时与 GPU 耗时之和必须小于等于 16.7ms 的整帧预算,超支就触发降级策略。
  1. CPU侧预算T_CPU 是逻辑、物理、脚本在 CPU 上消耗的时间上限,对应切配与备菜环节。
    TCPUT_{\text{CPU}}
  2. GPU侧预算T_GPU 是渲染指令在 GPU 上执行的时间上限,对应掌勺与装盘环节。
    TGPUT_{\text{GPU}}
  3. 总预算约束两者之和不能超过整帧预算 16.7ms,超出的部分必然以掉帧或降质来偿还。
    Tbudget=16.7 msT_{\text{budget}}=16.7\,\text{ms}

AI 应用场景

游戏 AI 代理的观测节拍

阶段:状态观测与决策输入

解决的问题:强化学习代理(如 ML-Agents 训练的 NPC)需要以稳定的节奏读取世界状态并注入动作。传统做法是开独立线程贪心采样,结果经常读到逻辑更新到一半的「半成品」状态,导致训练样本脏、回合不稳定。把 AI 感知挂到固定时间步之后,每轮采样都是一份完整一致的世界快照——帧循环的节拍直接决定了 AI 的决策频率。

具体案例:某车队仿真平台用固定时间步驱动多辆自动驾驶测试车,每 1/60 秒把所有车的位置、速度统一快照对齐,再交给强化学习 batch 训练;插值层负责把 60Hz 逻辑平滑到 144Hz 渲染,保证回放画面不抖。

自动化性能回归测试

阶段:性能分析与异常检测

解决的问题:人工跑图看帧率主观且不可复现。利用帧循环埋点抓取帧时间序列,自动计算平均 FPS、1% low、尖峰次数;AI 检测模型对比历史曲线,自动标记可疑卡顿,让性能问题在 CI 阶段就现形。

具体案例:某 3A 工作室的 nightly 构建在 CI 中自动回放 10 分钟固定路线,1% low 从 48 跌到 33 即触发告警,最终定位到新增的实时阴影改动。

数据驱动的动态分辨率

阶段:自适应渲染负载控制

解决的问题:传统 DRS 是事后反应——帧率已跌才降分辨率。基于帧长历史的轻量预测模型(如线性回归)可提前估计未来一小段时间的 GPU 负载,提前调整分辨率档位,减少肉眼可见的画质抖动。

具体案例:某移动开放世界游戏把过去 30 帧的帧时间喂给一个微型 MLP,预测未来 0.5 秒负载,提前两帧降分辨率,热降频导致的「帧率腰斩」发生率下降 62%。

Python 演示

python45 行
import time  class GameLoopSim:    """固定时间步游戏循环模拟器: 累加器 + 掉帧统计"""     def __init__(self, hz=60):        self.hz = hz        self.step_size = 1.0 / hz        self.accumulator = 0.0        self.frame_count = 0        self.drop_count = 0        self.sim_time = 0.0        self.pos = 0.0        self.velocity = 2.0     def update(self, dt):        # 物理更新: 位置 += 速度 * dt        self.pos += self.velocity * dt        self.sim_time += dt     def render(self):        self.frame_count += 1     def run(self, duration):        last = time.time()        while self.sim_time < duration:            now = time.time()            frame_time = now - last            last = now            if frame_time > self.step_size * 2:                self.drop_count += 1            self.accumulator += frame_time            while self.accumulator >= self.step_size:                self.update(self.step_size)                self.accumulator -= self.step_size            self.render()        return self.frame_count / self.sim_time, self.drop_count  if __name__ == "__main__":    sim = GameLoopSim(hz=60)    fps, drops = sim.run(duration=2.0)    print("模拟结束: 平均FPS=%.1f, 掉帧次数=%d" % (fps, drops))    print("玩家位置=%.2f, 模拟时间=%.2fs" % (sim.pos, sim.sim_time))
目的:用纯 Python 模拟游戏引擎的固定时间步主循环——把真实流逝时间攒进累加器,攒够 1/60 秒就执行一次物理更新,同时统计平均 FPS 与掉帧次数。
  1. self.step_size = 1.0 / hz把 60Hz 换算成单个逻辑步长 1/60 秒,这就是固定时间步的「标准火候」。
  2. self.accumulator += frame_time把真实流逝时间攒进累加器,相当于记录「实际过了多久」。
  3. while self.accumulator >= self.step_size:攒够一个步长就执行一次更新,一帧内可能补跑多次。
  4. self.update(self.step_size)更新永远用固定步长,保证物理结果与帧率无关。
  5. if frame_time > self.step_size * 2:真实帧时间超过两倍步长就记为掉帧,用于卡顿统计。
  6. self.frame_count / self.sim_time渲染帧总数除以模拟时间,得到平均 FPS。

常见误区

误区我的游戏平均 FPS 有 60,跑分软件也显示 60 多,但玩起来一卡一卡的,肯定是显示器刷新率不行。

正解平均 FPS 是几秒内帧时间的平均值,一次 300ms 的卡顿一帧就抵正常 18 帧,平均下来依然接近 60,但人眼感受到的是那次尖峰。正确做法是看帧时间曲线里的尖峰,以及 1% low 指标——它专门捕捉最差 1% 帧的体验。就像餐厅平均出菜 30 秒,不代表你等的那桌没有饿到 3 分钟。

为何常见:厂商和跑分软件都习惯宣传平均帧率,人们也习惯用单个数字概括复杂体验,忽略了时间维度的分布。

误区帧率越高越流畅,所以垂直同步应该永远关掉,把帧率拉到 300 帧就完美了。

正解帧率超过显示器刷新率后,多出的帧几乎不会提升可见流畅度,只会让 GPU 满载、功耗飙升、风扇狂转;更糟的是没有同步时上下缓冲交替输出,会产生撕裂。理性做法是限制帧率到刷新率附近,或使用 VRR 让刷新率跟帧率走。追求的目标是「稳定到达预算线」,不是无限快。

为何常见:大家把跑分高等同于体验好,忽略了显示器刷新率这个物理上限和功耗约束。

误区每帧重新取一次系统时间算 deltaTime 就够了,教程都这么写。

正解基础写法没错,但漏了防护:万一某一帧因为 GC、资源加载耗时 500ms,Δ t 会瞬间巨大,角色直接穿墙、物理炸开,而且逻辑越积越多形成死亡螺旋。工程上必须把 Δ t 钳制在某个上限(如 100ms),超出部分丢弃或分摊,必要时用固定时间步加累加器彻底隔离这种风险。

为何常见:教程为了简洁省略异常处理,读者直接抄到生产环境就埋了雷。

误区开了垂直同步就不会撕裂,帧率也正好等于刷新率,没有任何代价。

正解大部分时间是,但一旦单帧渲染超过 16.7ms 错过刷新窗口,这一帧要等下一个窗口,帧率直接腰斩到 30FPS,反而比不开更卡;同时缓冲排队会引入几十毫秒输入延迟,竞技游戏里很致命。所以电竞玩家常关 VSync 换低延迟,用 G-Sync/FreeSync 居中对齐。

为何常见:把垂直同步当成万能开关,忽略「错过窗口」和「缓冲排队」这两个副作用。

面试题

Q1. 游戏循环中「一帧」最准确的定义是什么?

单选题 · easy

  • A.一次键盘按键的响应过程
  • B.模拟时间推进一个固定步长
  • C.从输入到渲染输出的完整周期← 正确答案
  • D.一次图像资源的加载流程

答案:C。一帧是从输入采样、逻辑更新到渲染输出的完整周期,好比后厨一轮完整的「接单到上菜」。A 只是输入单点,B 只是逻辑中的一次固定更新,D 是资源系统事件,都不是完整帧。

Q2. 60Hz 显示器的一个刷新周期约是多少?

单选题 · easy

  • A.10.0 毫秒
  • B.12.5 毫秒
  • C.16.7 毫秒← 正确答案
  • D.33.3 毫秒

答案:C。1000 ÷ 60 ≈ 16.7ms。33.3ms 对应 30Hz,10ms 对应 100Hz,12.5ms 对应 80Hz。这个周期就是垂直同步和帧预算的总闸门。

Q3. 平均 FPS 接近 60 却频繁感到卡顿,最可能的原因是?

单选题 · easy

  • A.帧时间存在大幅尖峰← 正确答案
  • B.CPU 主频设定过低
  • C.屏幕分辨率设置过高
  • D.显卡显存容量不足

答案:A。平均 FPS 会把一次 300ms 的尖峰摊平。观察帧时间曲线看尖峰,或看 1% low 指标,比平均 FPS 可靠得多。主频、分辨率、显存问题通常表现为持续低帧率而非偶发顿挫。

Q4. 固定时间步相比可变时间步的核心优势是?

单选题 · mid

  • A.渲染画面分辨率更高更清晰
  • B.减少显卡的功耗与发热
  • C.物理模拟结果更稳定一致← 正确答案
  • D.降低网络同步的延迟

答案:C。固定时间步让物理永远以等间隔推进,帧率波动不改变碰撞与积分结果,这对联网同步和自动化测试尤其重要。它并不提升分辨率、降低功耗或网络延迟。

Q5. 1% Low 帧率指标衡量的是?

单选题 · mid

  • A.最低画质档位的平均帧率
  • B.渲染分辨率低于1%的场景
  • C.最慢1%网络包的响应时间
  • D.最差1%帧时段的平均帧率← 正确答案

答案:D。1% low 把帧时间排序,取最差 1% 帧求平均并换算成帧率,回答「最卡时段平均体验如何」这个问题。它不针对画质档位、渲染分辨率或网络。

Q6. 画面撕裂产生的直接原因是?

单选题 · mid

  • A.显示器刷新与GPU输出不同步← 正确答案
  • B.显存不足导致渲染掉帧
  • C.引擎代码存在内存泄漏
  • D.网络延迟过高导致跳帧

答案:A。撕裂是显示器刷新与 GPU 输出失同步,同一屏出现两帧内容,视觉上像一道斜向接缝。显存、内存、网络问题分别表现为掉帧、卡顿、跳帧,不会直接产生撕裂。

Q7. 固定时间步出现死亡螺旋的根源是?

单选题 · hard

  • A.显卡驱动崩溃导致渲染中断
  • B.显示器刷新频率突然变化
  • C.显存占用过高触发自动降频
  • D.追帧导致单帧耗时持续膨胀← 正确答案

答案:D。死亡螺旋指逻辑时间落后越多、每帧要追的更新越多、单帧耗时越长,形成正反馈锁死。钳制最大 Δt(如 100ms)或用固定时间步加累加器是标准解法。驱动崩溃、刷新率变化、降频都不是根源。

Q8. 动态分辨率 DRS 的核心目标是?

单选题 · extreme

  • A.提高场景模型的贴图清晰度
  • B.降低 CPU 端逻辑脚本耗时
  • C.在帧预算内缩放分辨率稳定帧率← 正确答案
  • D.增加后处理特效的画面数量

答案:C。DRS 以帧时间为反馈信号,超预算时降低渲染分辨率,把 GPU 耗时拉回窗口内,帧率稳定后再恢复。它是帧预算纪律在 GPU 侧的落地,不提升贴图、不优化 CPU 逻辑、不增加特效。

Q9. 下列哪些属于帧率管理的常用手段?

多选题 · mid

  • A.限制最大输出帧率← 正确答案
  • B.开启垂直同步等待← 正确答案
  • C.随机改变物理步长
  • D.使用可变刷新率同步← 正确答案

答案:ABD。限帧率、垂直同步、VRR 都是直接管理帧节奏的手段。物理步长必须固定,随机改变会破坏物理世界的确定性,绝不可取。

Q10. 关于垂直同步与输入延迟,下列正确的理解是?

多选题 · hard

  • A.延迟来自等待刷新窗口的排队← 正确答案
  • B.三缓冲延迟通常高于双缓冲← 正确答案
  • C.降低刷新率能彻底消除延迟
  • D.竞技游戏常关闭垂直同步降延迟← 正确答案

答案:ABD。VSync 让帧在刷新窗口排队,排队时间就是附加延迟;缓冲越多排队越深,所以三缓冲延迟通常高于双缓冲。降低刷新率只会拉长周期,不会消除延迟。电竞玩家为抢时间常关闭垂直同步换低延迟。