gpt4 book ai didi

c++ - 为什么我的渲染线程占用了 100% 的 cpu?

转载 作者:太空宇宙 更新时间:2023-11-04 16:13:04 25 4
gpt4 key购买 nike

所以现在在我的 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%。

我在这里做错了什么?

最佳答案

如果启用了 V-Sync 并且您的程序遵守交换间隔,那么您看到您的程序占用 100% 实际上是 Windows 测量 CPU 时间的一个人工制品。这是一个早已为人所知的问题,但只要您的程序在驱动程序上下文中阻塞(这是 OpenGL 在 V-Sync 上阻塞时发生的情况),Windows 都会将此归因于程序实际消耗 CPU 时间,而它实际上只是空闲。

如果您在交换缓冲区之后立即添加一个Sleep(1),它会欺骗Windows 使其进入更理智的计算;在某些系统上,甚至 Sleep(0) 也能达到目的。

无论如何,大多数时候 100% 只是外观问题。


在过去的几周里,我对低延迟渲染进行了一些详尽的研究(即最大限度地减少用户输入和相应光子从显示器中出来之间的时间),因为我很快就会得到一个 VR 耳机。以下是我发现的有关定时 SwapBuffers 的内容:解决该问题的明智方法实际上是对帧渲染时间进行计时,并在 SwapBuffers 之前添加一个人工 sleep ,这样您就可以在 V 之前几毫秒醒来-同步。然而,这说起来容易做起来难,因为 OpenGL 是高度异步的,显式添加同步会降低吞吐量。

关于c++ - 为什么我的渲染线程占用了 100% 的 cpu?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26031666/

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