【问题标题】:How to swap buffer as fast as possible如何尽可能快地交换缓冲区
【发布时间】:2017-04-24 08:54:21
【问题描述】:


我正在开发 OpenGL 项目,我正在使用 VS15 C++。
我的代码:

timeBeginPeriod(1);

//start timer to measure the gap 
GetSystemTime(&timeMiddle);             
timeMiddleLong = (timeMiddle.wMinute * 60 * 1000) +                                        
       (timeMiddle.wSecond * 1000) + timeMiddle.wMilliseconds;
myfile << "middle time = " << timeMiddleLong << endl;


glClearColor(1.0f, 0, 0, 1.0f);//red screen

//update screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SwapBuffers(hdc);
glfwPollEvents();

Sleep(1); //sleep for ~2ms

glClearColor(0, 0, 0, 0);//invisiable screen

//update screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SwapBuffers(hdc);
glfwPollEvents();

//stop timer and print to file the result
GetSystemTime(&timeEnd);
timeEndLong = (timeEnd.wMinute * 60 * 1000) + (timeEnd.wSecond * 1000) + 
            timeEnd.wMilliseconds;
myfile << "gap = " << timeEndLong - timeMiddleLong << endl;

ReleaseDC(hWnd, hdc);

我想要什么?
尽快在红屏和隐形屏之间切换。
我知道什么?
我的显示器是 60Hz,响应时间约为 7 毫秒,这意味着如果显示器在红屏出现时准确刷新,它将在那里停留 13 毫秒。
我得到了什么?
通过拍摄屏幕,我注意到红色屏幕停留了约 32 毫秒,这对我来说太长了。
此外,间隙在大多数时间显示约 2 毫秒的值,有时 5-9 毫秒

如何在最短的时间内显示红屏?会持续多久?

【问题讨论】:

  • windows下sleep是不可靠的,它会一直sleep到下一个schedule,一般是20ms左右。你在移除睡眠线时遇到同样的问题吗?
  • @Adrian Maire 之前调用 timeBeginPeriod 应将计时器分辨率设置为 1 毫秒,因此 Sleep 应该工作得相当准确。
  • @AdrianMaire 我提到睡眠准确。
  • @VTT:正确,但是,这也是不可靠的:如果处理器忙,则处理器不会重新调度,因此 1ms 仅在 CPU 忙之前有效。之后,回到 20 毫秒。
  • @AdrianMaire 是的,但根据我的计时器,睡眠工作正常。

标签: c++ opengl


【解决方案1】:

你的方法行不通——所有的 OpenGL 函数,包括 SwapBuffers,都可以在你的代码片段完成很久之后在 GPU 上排队和执行。

相反,请确保 VSync 已打开(默认情况下通常是打开的),并执行所有这些命令,中间不要有任何睡眠:

glClearColor(1.0f, 0, 0, 1.0f);//red screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SwapBuffers(hdc);
glClearColor(0, 0, 0, 0); //invisiable screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SwapBuffers(hdc);

这将使红色屏幕闪烁一帧(60Hz 显示器为 16.7 毫秒)。

由于 OpenGL 的异步特性,您的时间测量也不明智。您应该使用OpenGL Time Query Objects 来测量 GPU 端的时间。

【讨论】:

  • 问题是当我录制我的屏幕时(使用我的 OnePlus 3T 和“打开相机”应用程序,同时帧速率设置为 120,然后以 1/8 的慢动作播放)我没有看不到任何红屏,但它应该会出现。我怎么知道我的显示器红屏了?
  • 你的眼睛看到红屏了吗?如果不是,则意味着您的 VSync 在驱动程序设置中的某个位置被禁用 - 查找它。
  • 您可以使用wglSwapIntervalEXT(1)通过代码强制垂直同步。
  • @Peewe: 1) 这不是真的。 1/1000 秒是相机闪光灯的典型持续时间,人们看得非常清楚。许多频闪灯远低于此。 2) 重要的是闪光灯的总能量输出,因此显示器上的 1/1000 秒闪光灯将比 1/60 秒闪光灯暗 16 倍,但仍然非常明显。 3)你还是没有回答你是否看到了闪光灯。 4) 你想要解决的真正问题是什么?
  • @Peewe:我们的眼睛不是快门相机,而是时间积分和推导空间分辨功率计。一个非常短但强烈的闪光肯定会被记录下来。只是给你一个想法:我在一个实验室工作,该实验室也在研究视网膜的功能过程。其中一个小组正在对视网膜中的过程进行高速功能成像(每秒数百帧),以响应仅持续 1/1000000(百万分之一)秒的明亮闪光。并且测试对象非常清楚地看到这些闪光,就好像他们看着相机闪光灯
猜你喜欢
  • 2019-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-15
  • 2020-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多