gpt4 book ai didi

c++ - 修复了 VSync 打开时的时间步长卡顿

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:45:38 27 4
gpt4 key购买 nike

在我实现的 2D OpenGL 引擎中,我有一个固定的时间步长,如著名的 fix your timestep 中所述。文章,以及混合。

我有一个垂直移动的测试对象(y 轴)。运动中存在卡顿(预编程运动,而不是来自用户输入)。这意味着对象不会在屏幕上平滑移动。

请查看我链接的未压缩视频:LINK

游戏帧率保持在 60fps(Vsync 从 Nvidia 驱动程序打开)

游戏逻辑以每秒 20 次更新/滴答的固定速度更新,由我设置。这个是正常的。对象每次更新移动 50 个像素。

但是屏幕上的 Action 严重卡顿。

编辑:我通过逐帧进入上面录制的视频注意到卡顿是由一个帧显示两次引起的。

EDIT2:在任务管理器中将应用程序优先级设置为实时完全消除了卡顿!然而,这显然不是解决方案。

下面是物体在不同时间的 y 运动增量,垂直同步关闭第一列是自上一帧以来耗时,以微秒为单位(例如 4403 )第二列是自上一帧以来对象在 y 轴上的移动。实际上,对象每秒移动 1000 像素,下面的日志证实了这一点。

time since last frame: 4403    ypos delta since last frame: 4.403015
time since last frame: 3807 ypos delta since last frame: 3.806976
time since last frame: 3716 ypos delta since last frame: 3.716003
time since last frame: 3859 ypos delta since last frame: 3.859009
time since last frame: 4398 ypos delta since last frame: 4.398010
time since last frame: 8961 ypos delta since last frame: 8.960999
time since last frame: 7871 ypos delta since last frame: 7.871002
time since last frame: 3985 ypos delta since last frame: 3.984985
time since last frame: 3684 ypos delta since last frame: 3.684021

现在打开 VSync

time since last frame: 17629     ypos delta since last frame: 17.628906
time since last frame: 15688 ypos delta since last frame: 15.687988
time since last frame: 16641 ypos delta since last frame: 16.641113
time since last frame: 16657 ypos delta since last frame: 16.656738
time since last frame: 16715 ypos delta since last frame: 16.715332
time since last frame: 16663 ypos delta since last frame: 16.663086
time since last frame: 16666 ypos delta since last frame: 16.665771
time since last frame: 16704 ypos delta since last frame: 16.704102
time since last frame: 16626 ypos delta since last frame: 16.625732

我会说它们看起来还不错。

这几天一直让我发疯,我错过了什么?

下面是我在循环中调用的 Frame 函数:

void Frame()
{
static sf::Time t;
static const double ticksPerSecond = 20;
static uint64_t stepSizeMicro = 1000000 / ticksPerSecond; // microseconds
static sf::Time accumulator = sf::seconds(0);

gElapsedTotal = gClock.getElapsedTime();

sf::Time elapsedSinceLastFrame = gElapsedTotal - gLastFrameTime;
gLastFrameTime = gElapsedTotal;


if (elapsedSinceLastFrame.asMicroseconds() > 250000 )
elapsedSinceLastFrame = sf::microseconds(250000);

accumulator += elapsedSinceLastFrame;

while (accumulator.asMicroseconds() >= stepSizeMicro)
{
Update(stepSizeMicro / 1000000.f);
gGameTime += sf::microseconds(stepSizeMicro);
accumulator -= sf::microseconds(stepSizeMicro);
}
uint64_t blendMicro = accumulator.asMicroseconds() / stepSizeMicro;
float blend = accumulator.asMicroseconds() / (float) stepSizeMicro;
if (rand() % 200 == 0) Trace("blend: %f", blend);
CWorld::GetInstance()->Draw(blend);
}

评论中要求的更多信息:

  • 在全屏 1920x1080 和窗口模式 1600x900 下都会出现卡顿现象

  • 设置是一个简单的 SFML 项目。我不知道它在渲染带纹理的矩形时是否在内部使用 VBO/VAO

  • 没有在我的电脑上做任何其他事情。请记住,此问题也发生在其他计算机上,不仅仅是我的设备

  • 我在主显示器上运行。显示器并没有真正发挥作用。在全屏和窗口模式下都会出现此问题。

最佳答案

我已经分析了我自己的代码。问题是我的代码中有一个区域偶尔会由于缓存未命中而出现性能峰值。这导致我的循环花费的时间超过 16.6666 毫秒,这是在 60Hz 下平滑显示所需的最长时间。这只是一帧,偶尔出现一次。那个框架引起了口吃。代码逻辑本身是正确的,这被证明是一个性能问题。

为了将来引用,希望这能帮助其他人,我是如何调试它的,我放了一个

if ( timeSinceLastFrame > 16000 ) // microseconds
{
Trace("Slow frame detected");
DisplayProfilingInformation();
}

在我的框架代码中。当 if 被触发时,它会显示最后一帧中函数的分析统计信息,以查看哪个函数在前一帧中花费的时间最长。因此,我能够将性能错误查明到不适合其使用的结构。一张大而讨厌的 map ,会产生大量缓存未命中,偶尔会导致性能飙升。

我希望这对 future 不幸的灵魂有所帮助。

关于c++ - 修复了 VSync 打开时的时间步长卡顿,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26218785/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com