9

这是一个非常简单的测试程序。当 vsync 被禁用时,该程序以 100FPS 运行,几乎占用了 0% 的 CPU。当我启用 vsync 时,我得到 60FPS 和 25%(100% 的一个核心在 4 核系统上)的 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);
}
4

2 回答 2

7

我犹豫要不要给出这个答案,因为我真的不知道“答案”,但希望我能对此有所了解。

我也有一个 nVidia GPU,我也注意到了同样的事情。我的猜测是驱动程序本质上是在旋转等待:

while(NotTimeToSwapYet()){}

(或任何花哨的驱动程序版本看起来像)。

使用进程黑客nvoglv32.dll的线程中采样一些堆栈跟踪,大约 99% 的时间位于列表顶部的是

KeAcquireSpinLockAtDpcLevel()

这通常是下游的事情

KiCheckForKernelApcDelivery()EngUnlockDirectDrawSurface()

我在 Windows 驱动程序编程方面不够精通,无法将其称为结论性的,但它当然也不能告诉我我错了。

而且看起来你也没有做任何明显错误的事情。根据我的经验,非独占 Windows 应用程序中的交换时间非常痛苦:涉及大量的试验和错误,以及不同系统之间的大量可变性。据我所知,没有一种“正确”的方法可以一直很好地工作(请有人告诉我我错了!)。

过去,我一直能够依靠 vsync 来保持较低的 CPU 使用率(即使它确实使事情的响应速度降低了一些),但现在情况似乎不再如此。我最近从 DirectX 切换到了 OpenGL,所以我无法告诉你这是否是 nVidia 驱动程序的最新变化,或者他们是否只是在 vsync 方面对 DX 和 OpenGL 进行了不同的处理。

于 2014-02-21T08:23:29.017 回答
0

after swap buffers, call DwmFlush(); and it will no longer use 100% cpu!

于 2022-02-14T09:14:19.337 回答