在我自己构建的mfc程序中,我在CPU使用方面遇到了一些奇怪的问题。
我加载了一个大约360k点的点云,一切都很好(我使用VBO缓冲区,这是我所理解的方法?)。我可以随心所欲地移动它,并且注意到没有任何不利影响(CPU使用率非常低,GPU完成了所有工作)。但是,在某些角度和缩放值下,我看到我的一个处理器上的CPU峰值!然后我可以改变角度或者放大一点,然后它又会降到0左右。这在大窗口中比在小窗口中更容易发生。
我测量程序的FPS,它一直在65,但是当CPU峰值到来时,它通常会下降大约10个单位到55。我还测量了SwapBuffers所花费的时间,在正常操作期间大约为0-1 ms。一旦CPU达到峰值,它就会上升到20毫秒左右,所以很明显,在这个函数中,某些东西突然变得非常难以计算(我猜对于GPU ?)这个东西不在DrawScene函数中(这是一个在糟糕的实现中会消耗CPU的函数),所以我有点失落。
我知道这不是由于可见点的数量,因为这很容易发生在数据的一小部分,也可能发生在整个云上。我试着移动它,看看它是否与深度缓冲,剪切或类似,但它似乎完全随机的角度产生的问题。这似乎是可以重复的;将模型移动到一个曾经滞后的位置,当再次移动到那里时,将会出现滞后。
我是OpenGL的新手,所以这不是不可能的,我犯了一些非常明显的错误。
这就是渲染循环的样子(它通过一个周期为1毫秒的计时器事件在MFC应用程序中运行):
// Clear color and depth buffer bits
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw OpenGL scene
OGLDrawScene();
unsigned int time1 = timeGetTime();
// Swap buffers
SwapBuffers(hdc);
// Calculate execution time for SwapBuffers
m_time = timeGetTime() - time1;
// Calculate FPS
++m_cnt;
if (timeGetTime() - m_lastTime > 1000)
{
m_fps = m_cnt;
m_cnt = 0;
m_lastTime = timeGetTime();
}
我注意到(至少在一段时间之前),ATI驱动程序倾向于过于积极地进行旋转等待,而NVidia驱动程序倾向于中断驱动。从技术上讲,如果你没有更好的事情可做,等待旋转会更快。不幸的是,今天你可能在另一个线程上有更好的事情要做。
我认为OP的显示驱动程序可能确实是旋转等待。
好了,我想我知道这是怎么发生的了。
首先,即使在使用timeBeginPeriod(1)时,至少在我的计算机上,WM_TIMER消息似乎最多每15毫秒生成一次。这导致了我看到的标准65fps。
一旦场景渲染时间超过15毫秒,SwapBuffers就会成为限制因素。SwapBuffers似乎在忙等待,当这种情况发生时,导致一个核心上的CPU使用率达到100%。这不是发生在特定摄像机角度的事情,而是取决于当时屏幕上显示的点数的fps流畅变化的结果。每当渲染时间超过15毫秒时,它就会出现峰值,并开始在SwapBuffers等待。
在一个类似的说明,有没有人知道一个函数像"glReadyToSwap"或类似的东西?指示缓冲区是否准备交换的函数?这样我就可以选择另一种更高分辨率的渲染方法(例如1毫秒),然后每毫秒检查缓冲区是否准备好交换,如果它们不只是等待另一个毫秒,这样就不会忙着等待。