2016-04-08 33 views
2

我最近將舊款Galaxy S2手機升級爲全新Galaxy S7,並且非常驚訝地發現我寫的舊遊戲似乎在新手機上表現更差。在把所有東西都切割成一個簡單的骨頭項目之後,我發現了這個問題 - 我在每個onDrawFrame結尾執行的GLES20.glFinish()調用。在這裏,有一個glClear,但沒有繪製調用,FPS在40左右。沒有glFinish,固體60 FPS。無論如何,我的舊S2擁有堅實的60 FPS。Opengl es 2.0 - 爲什麼glFinish會讓我的新Android手機的幀率低於舊的?

然後我回到了遊戲中,取消了glFinish方法調用,確保足夠的性能恢復到完美狀態,並且沒有明顯的缺點。

爲什麼glFinish在我的新手機上放慢了我的幀頻,但不是我的舊手機?

回答

4

我認爲投機性的回答是好,因爲它會得到,所以 - 道歉幾乎可以肯定是重複的很多事情你已經知道:

命令發送到OpenGL的經歷三種狀態,相對於命名事情GPU方面:

  1. 未提交
  2. 提交,但懸而未決
  3. 完成

與運行GPU的代碼通信通常很昂貴。所以大多數的OpenGL實現都接受你的調用,並且只是在你的內存空間裏排隊工作一段時間。在某個時候,它會決定溝通是合理的,並且將支付一次轉移所有電話的費用,並將它們提升到提交狀態。然後,GPU將完成每一個(可能無序,但不會破壞API)。

glFinish

...不會返回,直到完成所有以前稱爲GL 命令的效果。這些影響包括GL狀態的所有更改,連接狀態的所有更改以及幀緩衝區內容的所有更改。

因此,對於CPU線程可能一直在做某事的某段時間,現在肯定不會。但是,如果你不要glFinish那麼你的輸出可能仍然會出現,但現在還不清楚。 glFlush往往是正確的方向 - 它會推進所有提交的內容,但不會等待完成,所以一切都會很快出現,你只是不打擾等待它。

OpenGL綁定到操作系統差異很大;一般來說,如果你的環境允許你這樣做,你幾乎可以肯定地想要衝洗而不是完成。如果無論是刷新還是完成均無效,並且操作系統不會根據任何條件爲您推送某些內容,那麼可能會導致一些額外的延遲(例如,發出一幀的命令在填滿之前可能無法到達GPU在下一幀期間再次提交未提交的隊列),但如果您無限期地執行GL工作,則輸出幾乎肯定會繼續。

Android位於EGL之上。根據規範,3.9.3:

...eglSwapBufferseglCopyBuffers上下文執行隱式沖水操作 ...

因此,我相信,你並不需要,如果你是雙緩衝進行任何沖洗或在Android上完成。調用交換緩衝區將在繪製完成後立即進行緩衝區交換,而不會阻塞CPU。對於真正的問題,S7有一個Adreno 530 GPU。 S2擁有Mali T760MP6 GPU。 Malis由Qualcomm的Adrenos公司生產,因此它們是完全不同的體系結構和驅動程序實現。所以導致阻塞的差異幾乎可以說是任何事情。但它是被允許的。 glFinish不是必需的,是一個非常鈍的工具;它可能不是主要的優化目標之一。

+2

Android圖形體系結構與完成時發送信號的內核fence對象配對。這意味着您可以渲染,調用'eglSwapBuffers()',並在渲染開始之前讓系統合成器中的緩衝區可用......這允許緩衝和IPC機制與渲染重疊。調用'glFinish()'會阻止它工作。我懷疑這是造成幀頻急劇下降的唯一原因,但同步等待完成無疑是沒有幫助的。 https://source.android.com/devices/graphics/architecture.html – fadden

+1

另一方面要記住的是,有些供應商實際上並沒有等到你調用'glFinish()'時完成所有的事情。你可能會認爲它違反了規範,但它仍然是這樣做的。 –