这是一个非常简单的测试程序。禁用vsync时,该程序以100FPS运行,几乎占用CPU的0%。当我启用vsync时,我获得60FPS和25%(4核系统上一个核心的100%)CPU利用率。这是使用Nvidia GPU。在线搜索引导我建议禁用Nvidia控制面板内的“多线程优化”。这确实会降低CPU利用率,但只会降低10%。此外,如果我在SwapBuffers之后删除了睡眠调用,即使禁用了多线程优化,我也会再次获得25%的利用率。任何人都可以对此有所了解吗?难道我做错了什么? Nvidia的OpenGL实现是否无可救药地存在缺陷?
#include <GLFW/glfw3.h>
#include <thread>
#include <cstdlib>
#include <cstdio>
int main(int argc, char *argv[])
{
if(!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Vsync Test", nullptr, nullptr);
if(!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
#ifdef USE_VSYNC
glfwSwapInterval(1);
#else
glfwSwapInterval(0);
#endif
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
double lastTime = glfwGetTime();
double nbFrames = 0;
while(!glfwWindowShouldClose(window))
{
double currentTime = glfwGetTime();
nbFrames++;
if (currentTime - lastTime >= 1.0)
{
char cbuffer[50];
snprintf(cbuffer, sizeof(cbuffer), "OpenGL Vsync Test [%.1f fps, %.3f ms]", nbFrames, 1000.0 / nbFrames);
glfwSetWindowTitle(window, cbuffer);
nbFrames = 0;
lastTime++;
}
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
//limit to 100FPS for when vsync is disabled
std::chrono::milliseconds dura(10);
std::this_thread::sleep_for(dura);
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
答案 0 :(得分:7)
我毫不犹豫地将此作为答案,因为我真的不知道“答案”,但希望我能对此有所启发。
我也有一个nVidia GPU,我也注意到了同样的事情。我的猜测是驱动程序本质上是等待旋转:
while(NotTimeToSwapYet()){}
(或任何花哨的驱动程序版本)。
使用process hacker从nvoglv32.dll
的线程中抽取一些堆栈跟踪,大约99%的时间位于列表顶部的东西是
KeAcquireSpinLockAtDpcLevel()
通常位于
之类的下游 KiCheckForKernelApcDelivery()
和EngUnlockDirectDrawSurface()
我对Windows驱动程序编程的熟悉程度不足以称之为结论,但它肯定不会告诉我我也错了。
看起来你也没有做任何明显错误的事情。根据我的经验,非独占Windows应用程序中的交换时间非常痛苦:涉及大量的试验和错误,以及不同系统之间的大量可变性。据我所知,没有“正确”的方法可以一直很好地工作(请有人告诉我,我错了!)。
在过去,我已经能够依赖vsync来保持较低的CPU使用率(即使它确实使响应性降低了一些),但似乎不再是这种情况。我最近从DirectX切换到OpenGL,所以我无法告诉你这是否是nVidia驱动程序最近的更改,或者它们是否仅仅针对vsync处理DX和OpenGL。