c++ - 避免等待 SwapBuffers

标签 c++ winapi opengl

我发现 OpenGL 中的 SwapBuffers 将忙于等待,只要显卡未完成渲染或正在等待 V-Sync。

这对我来说是个问题,因为我不想在等待卡完成时浪费 100% 的 CPU 内核。我不是在写游戏,所以我不能将 CPU 周期用于更高效的工作,我只想将它们交给操作系统中的其他进程。

我发现 glutTimerFunc 和 glutIdleFunc 等回调函数对我有用,但我不想使用 glut。不过,glut 必须以某种方式使用正常的 gl 函数来执行此操作,对吗?

有没有“glReadyToSwap”之类的功能?在这种情况下,我可以每毫秒左右检查一次,并确定我应该再等一会儿还是进行交换。我还可以想象也许跳过 SwapBuffers 并编写我自己的类似函数,如果有人能指出我正确的方向,它不会忙着等待。

最佳答案

SwapBuffers 不是忙于等待,它只是在驱动程序上下文中阻塞你的线程,这使得 Windows 错误地计算 CPU 使用率:Windows 通过确定空闲进程获得多少 CPU 时间来计算 CPU 使用率+ 程序不花多少时间在驱动程序上下文中。 SwapBuffers 将在驱动程序上下文中阻塞,您的程序显然会从空闲进程中占用 CPU 时间。但是您的 CPU 在这段时间内实际上什么也没做,调度程序很高兴地等待将时间传递给其他进程。空闲进程 OTOH 除了立即将其时间让给系统的其余部分之外什么都不做,因此调度程序会直接跳回到您的进程中,这会在驱动程序中阻塞 Windows 视为“正在阻塞 CPU”。如果您要测量实际功耗或热量输出,对于一个简单的 OpenGL 程序,这将保持相当低的水平。

这种恼人的行为实际上是一个 OpenGL 常见问题解答!

只需为并行数据处理创建额外的线程。将 OpenGL 保留在一个线程中,数据处理在另一个线程中。如果您想降低报告的 CPU 使用率,添加 Sleep(0) 或 Sleep(1) after SwapBuffers 即可。 Sleep(1) 将使您的进程在用户上下文中花费一点时间,因此空闲进程获得更多时间,这将使数字均匀。如果你不想 sleep ,你可以这样做:

const float time_margin = ... // some margin
float display_refresh_period; // something like 1./60. or so.

void render(){

    float rendertime_start = get_time();

    render_scene();
    glFinish();

    float rendertime_finish = get_time();
    float time_to_finish = rendertime_finish - rendertime_start;

    float time_rest = fmod(render_finish - time_margin, display_refresh_period);
    sleep(time_rest);
    SwapBuffers();
 }

在我的程序中,我使用这种计时,但出于另一个原因:我让 SwapBuffers 在没有任何帮助程序 sleep 的情况下阻塞,但是我让其他一些工作线程在那个时间通过共享上下文在 GPU 上做一些事情(比如更新纹理)我让垃圾收集器运行。不一定要准确计时,但在 SwapBuffers 返回之前完成的工作线程允许几乎立即开始渲染下一帧,因为那时大多数互斥锁已经解锁。

关于c++ - 避免等待 SwapBuffers,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5829881/

相关文章:

java - 如何实现投影绘画?

c++ - 如何在 PC 的特定位置用 C++ 创建文件

c++ - 来自 n 个字符的长度为 k 的所有排列,在 CPP 中有重复

c++ - 为什么允许我显式实例化模板特化,其中默认参数不能隐式转换为其他类型?

C++ - 无法查看使用 WinObj 创建的互斥体

c - 为什么我的 openGL 纹理只覆盖了我的四边形的一半?包含来源

c++ - 对象 Pascal 上的 C 回调函数崩溃

c++ - 在 C++ 中分区和格式化 USB 闪存驱动器时出错

c++ - win32 句柄和多线程

c++ - 时髦的 OpenGL 立方体