【发布时间】:2023-03-06 08:28:01
【问题描述】:
所以现在在我的 OpenGL 游戏引擎中,当我的渲染线程实际上无事可做时,它占用了我的 CPU 所能提供的最大值。 Windows 任务管理器显示我的应用程序占用了 25% 的处理(我有 4 个硬件线程,所以 25% 是一个线程可以占用的最大值)。当我根本不启动渲染线程时,我得到 0-2%(这本身就令人担忧,因为它所做的只是运行一个 SDL 输入循环)。
那么,我的渲染线程到底在做什么?这是一些代码:
Timer timer;
while (gVar.running)
{
timer.frequencyCap(60.0);
beginFrame();
drawFrame();
endFrame();
}
让我们逐一介绍。 Timer 是我使用 SDL_GetPerformanceCounter 制作的自定义计时器类。 timer.frequencyCap(60.0); 旨在确保循环每秒运行的次数不超过 60 次。这是Timer::frequencyCap()的代码:
double Timer::frequencyCap(double maxFrequency)
{
double duration;
update();
duration = _deltaTime;
if (duration < (1.0 / maxFrequency))
{
double dur = ((1.0 / maxFrequency) - duration) * 1000000.0;
this_thread::sleep_for(chrono::microseconds((int64)dur));
update();
}
return duration;
}
void Timer::update(void)
{
if (_freq == 0)
return;
_prevTicks = _currentTicks;
_currentTicks = SDL_GetPerformanceCounter();
// Some sanity checking here. //
// The only way _currentTicks can be less than _prevTicks is if we've wrapped around to 0. //
// So, we need some other way of calculating the difference.
if (_currentTicks < _prevTicks)
{
// If we take difference between UINT64_MAX and _prevTicks, then add that to _currentTicks, we get the proper difference between _currentTicks and _prevTicks. //
uint64 dif = UINT64_MAX - _prevTicks;
// The +1 here prvents an off-by-1 error. In truth, the error would be pretty much indistinguishable, but we might as well be correct. //
_deltaTime = (double)(_currentTicks + dif + 1) / (double)_freq;
}
else
_deltaTime = (double)(_currentTicks - _prevTicks) / (double)_freq;
}
接下来的 3 个函数要简单得多(现阶段):
void Renderer::beginFrame()
{
// Perform a resize if we need to. //
if (_needResize)
{
gWindow.getDrawableSize(&_width, &_height);
glViewport(0, 0, _width, _height);
_needResize = false;
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
void Renderer::endFrame()
{
gWindow.swapBuffers();
}
void Renderer::drawFrame()
{
}
渲染线程是使用 std::thread 创建的。我能想到的唯一解释是 timer.frequencyCap 不知何故不起作用,除了我在我的主线程中使用完全相同的函数并且我空闲在 0-2%。
我在这里做错了什么?
【问题讨论】:
-
添加日志记录,直到您了解发生了什么。
-
强烈建议废弃自己的定时器控件,使用显卡驱动提供的swap interval control。
-
任何 sleep_for 调用都保证低于 100% 的 CPU 负载。检查这个条件
if (duration < (1.0 / maxFrequency)) -
我打开了交换间隔,它提高了 cpu 使用率(我下降到了 10-15%),但是删除了我的计时器使它又回到了 25%。如果我设置
frequencyCap(30)而不是60,我的cpu 使用率下降到0。 -
sleep_for可能正在使用繁忙的循环来创建延迟,本质上是start=now();while(start+delay<now());
标签: c++ multithreading performance opengl sdl