在OSX上,我有一个非常简单的游戏循环,它运行一些OpenGL代码,这些代码只是一些矩阵变换(几乎所有矩阵变换都在GPU上计算),并且一个纹理的绑定被智能地管理,这样它就不会受到每一帧的约束。纹理只是以适度的速度旋转。就这些。我每秒钟60滴。窗口的大小是1300乘650(由于某种原因,它实际上在全屏中表现更好,但我在窗口测试)。我得到大约350-400 fps。 CPU使用率总是在200%左右(约占所有内容的50%;是四核i5处理器)。另外,奇怪的是,打开垂直同步根本不会做任何事情。它只是按预期将FPS锁定在60,并且CPU使用率保持在200%左右。
以下是计算机的统计数据(如果有必要):
这是游戏循环:
DATEDIFF()
在阅读了一些其他类似的问题后,似乎循环工作得太快,完全无拘无束,因此消耗的CPU远远超过必要的CPU。为了测试这个假设,我将float time = 0.0f;
float currentTime = 0.0f;
float tickTimer = 0.0f;
float frameTimer = 0.0f;
int frames = 0;
float rate = 1.0f / 60.0f;
float deltaTime = rate;
const milliseconds sleepDuration(1);
glfwMakeContextCurrent(nullptr);
thread tickThread([&](){
while(!glfwWindowShouldClose(window)) {
while(tickTimer >= rate) {
tickTimer -= rate;
time += rate;
mtx.lock();
tickCallback(deltaTime);
mtx.unlock();
}
}
});
thread renderThread([&](){
glfwMakeContextCurrent(window);
while(!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
mtx.lock();
renderCallback();
mtx.unlock();
this_thread::sleep_for(sleepDuration);
frames++;
if (frameTimer >= 1) {
frameTimer = 0;
fps = frames;
frames = 0;
}
glfwSwapBuffers(window);
}
});
while(!glfwWindowShouldClose(window)) {
const float newTime = static_cast<float>(glfwGetTime());
deltaTime = newTime - currentTime;
currentTime = newTime;
tickTimer += deltaTime;
frameTimer += deltaTime;
glfwPollEvents();
}
设置为大约100毫秒,这应该足以让CPU自行冷却下来。它没有。使用率仅降至平均约180%。我尝试在循环的滴答部分放置一个sleepDuration
,它将使用率降低到大约100%,这很重要,但对于如此少量的代码仍然有很多。 Re-Logic的Terraria在这台电脑上的运行速度最高可达40%。我已经尝试过切断多线程,所以一切都只是一个大循环,我尝试过异步,我甚至尝试过以最高级别的优化运行GCC,但我什么都没得到。
我不知道这是否对任何人都有帮助,但我也经历了频繁但相当短暂的滞后峰值。它们似乎没有出现在FPS中,所以它必须是滴答作响。我希望我的程序与几乎所有的计算机资源有关,而其他程序必须争取获得他们的份额,但这只是我的理论。我真的不太了解这一点。那么,有谁知道我做错了什么?
编辑:我忘记添加的东西;在类似的问题中,我读到this_thread::sleep_for(sleepDuration)
似乎是罪魁祸首。事实并非如此。当我删除它时,CPU使用率下降到~140%(仍然是一个荒谬的数字),并且FPS猛增至约6200,这是有道理的,但我只是不知道为什么CPU如此之高。它必须在滴答声中(这只是计算旋转矩阵,仅此而已)。