【问题标题】:What is the accepted timing strategy when using Vertical Synchronisation?使用垂直同步时,可接受的时序策略是什么?
【发布时间】:2013-04-12 21:57:30
【问题描述】:

基于对 OpenGL 编程的基本了解,所有必需的绘图操作都按顺序执行,每帧重绘一次。硬件的性能基本上决定了这种情况发生的速度。据我了解,游戏将尝试尽快绘制,因此重绘操作基本上包含在一个 while 循环中。然后将优化图形操作(图形引擎)以确保应用程序可以接受帧速率。

支持垂直同步的图形硬件将帧速率锁定到显示速率。第一个问题是图形引擎应该如何与硬件同步进行交互?这是否可能,或者渲染器是否以最大速度工作并且硬件有选择地调用最新帧,丢弃所有未使用的先前帧..?

提出这个问题的动机不是我打算立即编写图形引擎,而是调试现有系统的问题,其中移动场景的图形在屏幕上出现卡顿。症状上,当 VSync 关闭时,口吃很轻微,当它打开时,要么有明显的周期性口吃,要么完全解决了口吃。对于正在发生的事情或原因,我有些抓不住,想了解更多有关图形系统的背景信息。

总而言之,问题在于人们应该如何与硬件重绘事件进行交互,以及这是否可能。但是,欢迎提供任何其他信息。

【问题讨论】:

    标签: opengl graphics 3d vsync


    【解决方案1】:

    第一个问题是图形引擎应该如何与硬件同步交互?

    为了避免闪烁,现代渲染系统使用双缓冲,即有两个颜色平面缓冲区,在完成绘制到一个后,显示读出指针设置为完成的缓冲区平面。此缓冲区交换可以同步或非同步发生。启用垂直同步后,缓冲区交换将同步,渲染线程会阻塞,直到缓冲区交换发生。

    由于双缓冲要求缓冲区交换,这隐含地引入了同步机制。这就是交互式渲染系统锁定显示刷新的方式。

    在症状上,关闭 VSync 时卡顿是轻微的,打开时会出现明显的周期性卡顿,或者卡顿完全解决。

    这听起来像是一个写得很糟糕的动画循环,它假设恒定帧速率锁定在显示刷新率上,基于帧渲染速度快于显示刷新间隔的假设,并且可以及时发出缓冲区交换以发生下一次回溯.

    处理垂直同步的唯一可靠方法是实际测量帧渲染之间的时间并将渲染循环提前该时间量。

    【讨论】:

    • 只是为这个答案添加一点脚注,这里有一个很好的时间步分析gafferongames.com/game-physics/fix-your-timestep。这个想法是固定时间步长,在可用的时间内执行它的多次迭代(在每个迭代之间线性插值)。
    • 感谢 datenwolf,阻塞渲染线程的描述完美地回答了这个问题。不过要清楚地说,您是说游戏的渲染循环将继续以不受约束的方式运行,但每次更新都会被硬件阻止,从而有效地导致循环与之同步。还有罗宾逊读得很好,之前只假设了帧插值的可能性,这真的很酷。
    • @JCollins:如果你用交换缓冲区结束每个游戏循环迭代,它将阻塞在那里直到缓冲区交换发生,这可以同步以显示刷新。所以这取决于你如何定义“不受约束”。你肯定会观察到循环执行的一些延迟。
    【解决方案2】:

    这是一个猜测,但是:

    问题不在于垂直同步

    我不知道您使用的是什么操作系统,但是有多种方法可以获取有关显示器的信息以及屏幕刷新的速度(为了回答这个问题,我们假设您的显示器有点最近并以 60 Hz 的速率重绘,或每秒 60 次,或每 16.66666... 毫秒一次)。

    渲染器通常与应用程序的“逻辑”端配对:输入、UI 计算、模拟运行等。看起来应用程序的逻辑端运行得足够快,但渲染端 - 即,Draw Call 通常总结为 - 限制了您的应用程序的速度。

    垂直同步可能会加剧这种情况,因为如果您的 Draw Call 每 16.66666 毫秒发生一次 - 但它所花费的时间比 16.666666 毫秒长得多 - 那么您会感觉到帧速率下降(即帧将“口吃”,因为它们需要很长时间才能生成单帧)。 VSync - 以及启用或禁用它 - 不会成为您代码的瓶颈:它只是说“嘿,由于硬件每 16.666666 毫秒只会从我们这里获取 1 帧,为什么要进行比每 16.66666 毫秒更多的绘制调用? ? 只要我们每次经过一次绘制调用,我们的应用程序就会看起​​来尽可能流畅,而且我们不必浪费时间进行更多调用!”

    问题在于,它假设您的代码将运行足够快以使其在这 16.6666 毫秒内完成。否则,卡顿、滞后、视觉伪影、冻结帧和其他问题都会在屏幕上显现出来。

    当您关闭 VSync 时,您是在告诉您的渲染调用尽可能频繁、尽可能快地被调用。这可能会在 Logic 调用旁边给它一些额外的摆动空间来渲染帧,这样当硬件说“我现在要拍照并把它放在屏幕上!”时一切都被美化了,恰到好处地摆好姿势并说cheese!(尽管按照你说的,它勉强做到了)。

    做什么:

    首先分析您的代码。找出哪些功能花费的时间最多。从口吃来看,您的代码中的某些内容花费的时间比预期的要长,并且给您带来了不良的性能。确保首先分析,找出你正在消耗时间的关键部分,并弄清楚如何保持正确 em> 让它一样快。您可能想弄清楚在渲染调用中调用了什么,并具体分析完成一个周期所需的时间。然后为逻辑调用计时,并查看执行这些调用需要多长时间。然后,砍掉。

    祝你好运!

    【讨论】:

    • 感谢博士,我可以访问上一代的代码(我只能假设在逻辑上与当前一代相似。)我们正在编写更新场景的底层逻辑,我可以看到我们的逻辑运行的循环(@~1000Hz)与主循环是异步的。我还没有找到最顶级的绘图程序来评估它是否与刷新同步,并且不知道“正确”的策略是什么。环境是 60Hz 的 Windows 7 渲染。至于帧速率,我能收集到的唯一信息是在关闭垂直同步的情况下,我看到 90-400FPS。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-27
    • 2015-04-12
    • 2018-12-23
    • 2015-07-09
    • 2010-09-26
    相关资源
    最近更新 更多