SDL + OpenGL,具有周期性尖峰的不规则帧时间
Posted
技术标签:
【中文标题】SDL + OpenGL,具有周期性尖峰的不规则帧时间【英文标题】:SDL + OpenGL, irregular frame times with periodic spikes 【发布时间】:2017-08-25 16:12:05 【问题描述】:我正在使用 SDL 开发一个应用程序,我很高兴。我注意到动画中有一些小的冻结。我已经编写了一个功能最少的单独项目,我发现即使使用非常基本的设置也会出现问题。
这是代码:
#include <iostream>
#include <vector>
#include <fstream>
#include <SDL.h>
#include <glad/glad.h>
using namespace std;
// the application will close after this amount of time
const float MILISECONDS_TO_CLOSE = 10 * 1000;
int main(int argc, char** argv)
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_Window* window =
SDL_CreateWindow(
"tracer",
100, 100,
800, 600,
SDL_WINDOW_OPENGL
);
SDL_GLContext context = SDL_GL_CreateContext(window);
// SDL_GL_SetSwapInterval(1); // this line mitigates the problem but just slightly
if (!gladLoadGL())
cout << "gladLoadGL failed" << endl;
const GLubyte *oglVersion = glGetString(GL_VERSION);
std::cout << "This system supports OpenGL Version: " << oglVersion << std::endl;
const GLubyte *gpuVendor = glGetString(GL_VENDOR);
std::cout << "Graphics card: " << gpuVendor << std::endl;
glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
vector<unsigned> deltas;
deltas.reserve(10 * MILISECONDS_TO_CLOSE);
static unsigned firstTime, prevTime, curTime;
firstTime = prevTime = curTime = SDL_GetTicks();
while (true)
// compute delta time
curTime = SDL_GetTicks();
unsigned dt = curTime - prevTime;
prevTime = curTime;
deltas.push_back(dt);
// close the application after some time
if (curTime - firstTime > MILISECONDS_TO_CLOSE) break;
// handle closing events
SDL_Event event;
if (SDL_PollEvent(&event))
if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE || event.type == SDL_QUIT) break;
glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapWindow(window);
// save recorded deltas to a file
fstream f("out.txt", ios::out | ios::trunc);
for (unsigned dt : deltas) f << dt << endl;
f << flush;
f.close();
return 0;
程序在 10 秒内记录帧之间的时间并将结果保存在文本文件中。
我使用 python 绘制了数据我得到了这个:
水平轴以毫秒为单位表示帧时间。纵轴表示自上一帧以来经过的时间。也以毫秒为单位。
如您所见,帧之间的时间非常不规则,并且存在周期性尖峰(尖峰之间大约 1 秒)。
我已将 CMake 项目上传到 github repository,因此您可以根据需要对其进行测试。
我已使用集成 GPU 和专用 GPU(Intel 530HD 和 NVIDIA GTX 960M)进行了测试。
SDL 版本是 2.0.5。
我在 Windows 10 和 Ubuntu 16.04 LTS 上对其进行了测试。
编辑: 我已经将应用程序移植到 GLFW 并且发生了同样的情况。因此,SDL 中不太可能存在错误。我已经相应地更新了 git repo,现在有两个 CMake 项目。
EDIT2: 我已经在另一台计算机上对其进行了测试,并且工作正常。 我不知道发生了什么。会不会是硬件问题?那为什么我运行其他应用程序时没有发生呢?
驱动问题?不太可能,因为它同时使用 Intel 和 NVIDIA GPU。此外,它发生在 Ubuntu 和 Windows 上。
【问题讨论】:
似乎每秒都是尖峰。也许您的计算机上正在运行另一个进程,该进程每秒唤醒并占用所有 CPU 时间。您是否在另一台计算机上尝试过您的程序? 对不起,我忘了提到操作系统和版本。我会更新问题 @BrunoLevy 我没有在其他计算机上尝试过,但我尝试在同一台计算机上安装了两个不同的操作系统。我会试着找另一台电脑测试一下。 这是在笔记本电脑上吗? 切换到while(SDL_PollEvent(&event))
有帮助吗?现在,您正在每帧出列一个事件。
【参考方案1】:
由于 CPU 过热,我也遇到过类似的行为(尽管有更长和更低的平台期,而不是尖峰),因此决定暂时降低时钟频率。如果您的 PC 发生这种情况,您可以尝试升级内部冷却器或添加外部冷却器。或者只是降低房间空调的温度设置。
当然,这在夏天总是更成问题。
Here's where I've posted about it.
【讨论】:
这很有趣。在我提供的代码中,循环完全不受限制,因此它确实会导致过热。我尝试添加“SDL_Delay(10)”(最多 100 fps),所以过热应该不是问题。尖峰仍然存在 (img)。感谢您的建议。 @user1754322:当我过热时,我开启了垂直同步,所以最多 60fps。 我也尝试过启用垂直同步,结果也是一样。我相信它并没有过热,毕竟我用过其他交互式应用程序没有问题。一个根本不做任何工作的循环(99% 的时间是中间的)过热而其他应用程序没有,这是没有意义的。除此之外,这是一台游戏笔记本电脑。谢谢以上是关于SDL + OpenGL,具有周期性尖峰的不规则帧时间的主要内容,如果未能解决你的问题,请参考以下文章