2017-04-24 56 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