2017-04-24 23 views
0


我正在开发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,响应时间约为7ms,这意味着如果显示器正好在红色屏幕启动时刷新,它将在那里停留13ms。
我得到了什么?
通过拍摄屏幕,我注意到红色屏幕停留时间为〜32ms,这对我来说太长了。
此外,间隙在大多数时间和有时5-9ms显示值为〜2ms

如何显示最短时间的红色屏幕?这将是多久?

+2

睡眠在Windows下是不可靠的,它会睡眠到下一个时间表,通常约20ms。你是否在去除睡眠线方面遇到同样的问题? –

+0

@Adrian Maire之前调用'timeBeginPeriod'应该将计时器分辨率设置为1 ms,所以'睡眠'应该工作得相当准确。 – VTT

+0

@AdrianMaire我提到睡眠准确。 – Hido

回答

3

您的方法将无法工作 - 包括SwapBuffers在内的所有OpenGL函数都可以在您的代码片段完成后很久就排队并在GPU上执行。

相反,确保垂直同步打开(这是默认设置,通常情况下),并在中间执行所有这些命令没有任何睡觉:

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.7ms)。

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

+0

问题是,当我录制我的屏幕(使用我的OnePlus 3T与“打开相机”应用程序,而帧速率设置为120,然后以1/8的慢动作播放它时),我没有看到任何红色屏幕,但它应该出现。我怎么知道我的显示器显示红色屏幕? – Hido

+0

你的眼睛看到一个红色的屏幕?如果没有,那么这意味着你的VSync在驱动程序设置中被禁用 - 查找它。 – ybungalobill

+0

您可以使用'wglSwapIntervalEXT(1)'通过代码强制执行VSync。 – ybungalobill