glFlush,glFinish和SwapBuffers用法

OpenGL 繪圖的機制是:先用 OpenGL 的繪圖上下文 Rendering Context (簡稱爲 RC )把圖畫好,再把所繪結果通過 SwapBuffer() 函數傳給 Window 的繪圖上下文 Device Context (簡記爲 DC)。要注意的是,程序運行過程中,可以有多個 DC,但只能有一個 RC。因此當一個 DC 畫完圖後,要立即釋放 RC,以便其它的 DC 也使用。

      glFlush:將GL命令隊列中的命令發送給顯卡並清空命令隊列,發送完立即返回;glFlush()就是強制刷新,OpenGL是使用一條渲染管線線性處理命令的,一般情況下,我們提交給OpenGL的指令並不是馬上送到驅動程序裏執行的,而是放到一個緩衝區裏面,等這個緩衝區滿了再一次過發到驅動程序裏執行;很多時候只有幾條指令是填充不滿那個緩衝區的,就是說這些指令根本沒有被髮送到驅動裏,所以我們要調glFlush來強制把這些指令送到驅動裏進行處理。

      glFinish:將GL命令隊列中的命令發送給顯卡並清空命令隊列,顯卡完成這些命令(也就是畫完了)後返回。

      因此,在繪圖命令比較冗長的情況下,可以分段調用 glFlush 以清空命令隊列並讓顯卡開始先執行這些命令,最後調用glFinish來同步。舉個例子:我的渲染器一共有9種shader,渲染時從shader0一直渲染到shader8,以前是在所有shader渲染完成後才調用glFinish(注意:這裏如果把glFinish換成glFlush,那麼調用wglSwapBuffer的時候在不同的平臺上會產生不同的結果,具體結果我也不清楚,個人感覺好像沒什麼問題,但是遊戲的時鐘系統會被擾亂——最明顯的就是幀速算錯),那麼CPU就要等GPU繪圖,浪費了大把大把的時間;現在改成每個shader完成後調用一次glFlush,強制GPU開始執行命令隊列中的GL命令,最後調用glFinish等待GPU完成當前幀渲染,然後調用wglSwapBuffer調換前後緩存。

      這裏就會發現這樣一件事情:無論如何,都要等glFinish返回了,如果GPU繪製需要比較多的時間,那麼CPU在這裏等待的時間就比較可觀了,如何提高CPU效率呢?個人認爲有兩個辦法:

      1、使用多線程。將更新和渲染作爲線程A,輔助性計算如AI策略、地圖生成作爲線程B。那麼當線程A因爲glFinish阻塞時,線程B便可以利用CPU進行計算。

      2、使用CPU時間預算方法。即先給出一幀所需要的時間預算,在調用glFinish之前判斷是否還有多的時間預算,若有多,則先作輔助計算,完成或超過預算時間後才調用glFinish(若此時GPU已經完成命令,就不需要等待了)。

     對於SwapBuffers,SwapBuffer命令只是把前臺和後臺的緩衝區指針交換一下而已也就是把前臺的內容變成後臺緩衝的內容,把後臺的緩衝內容換到了前臺這個函數它本身並不對換過來的成爲了後臺的buffer做清理工作,所以每幀都glClear一次,然後再繪製,而後再SwapBuffers。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章