2011-10-24 23 views
10

我正在嘗試使用OpenGL ES爲Android編寫一個小型遊戲引擎。我創建了一個Game Thread來更新遊戲對象和GLThread來繪製場景。我讀過你需要在GLSurfaceView的onSurfaceCreated方法中加載紋理。我跟着,但爲了一些調試目的,我試圖加載我的遊戲線程,而不是GLThread的紋理。我沒有任何錯誤,紋理沒有顯示在屏幕上。我花了整整一天的時間試圖找出問題,最後我看了下面的內容here爲什麼不能從另一個線程調用OpenGL ES函數

「只要確保在主線程中只使用OpenGL。」很重要。您不能在您的遊戲引擎(可能位於另一個線程中)調用與gl線程不同步的紋理加載函數。設置一個標誌來指示你的gl線程加載一個新紋理(例如,你可以在OnDrawFrame(GL gl)中放置一個函數來檢查是否必須加載一個新的紋理。所以紋理將被加載從GL線程我只是不明白爲什麼是這樣的爲什麼OpenGL函數不能從另一個線程工作

我知道如何創建線程,但我不知道是什麼同步手段上面的提取提到:「你不能在你的遊戲引擎(可能在另一個線程中)調用一個與gl線程不同步的紋理加載函數。」所以我猜我的遊戲線程可能不同步與GL線程是否可以創建另一個與GL線程同步的線程所以可以從它調用GL函數?我應該通過線程學到什麼來理解這些概念?

+5

我不是Android的傢伙,但在iOS中有類似警告的兩個原因:其一是當前GL上下文是線程特定的,所以您需要跨上下文線程傳遞上下文貨幣,第二個(更多重要的是)在沒有同步的情況下從多線程混淆GL狀態只會導致GL上下文狀態的破壞。 HTH。 –

+0

我認爲這只是爲了避免同時訪問 –

回答

8

quixoto的評論是最接近的,我認爲。 OpenGL上下文在所有平臺上都是線程特定的傳統原因是OpenGL嚴重依賴於狀態,並且沒有用於使一系列更改處於原子狀態的語義。因此,例如,在一個線程的繪製操作可能是:

glVertexPointer(... supply vertex positions ...) 
glTexCoordPointer(... provide texture positions ...) 
/* and supply a few other pointers, maybe bind a texture */ 

glDrawArrays(... draw some geometry ...) 

所以最後只調用在前面呼叫的環境提供可預測的結果。如果你允許這段代碼在glVertexPointer之後暫停,另一個線程跳入並執行相同的順序來繪製它的幾何圖形,然後這個代碼繼續執行,它將畫出相當錯誤的幾何圖形,甚至可能導致如果一些被替換的數組小於原始數據,則限制內存訪問。

Android支持EGL,它支持OpenGL共享組的通用概念(儘管隱式地;您提供了一個現有的上下文,您希望新的上下文通過第三個參數與eglCreateContext共享組)。如果兩個上下文位於共享組中,那麼它們中的每一個都有一個獨立的狀態,並且只能從一個線程調用,但每個線程都可以使用諸如紋理或頂點緩衝區對象之類的命名對象。因此,使用共享組可以同時在多個線程上執行OpenGL操作,以便能夠將結果合併到單個線程中。

因此將上下文綁定到單個線程並不是一個問題。在OpenGL本身中規劃這個問題也將是一個非起步者,因爲OpenGL上下文是以操作系統特定的方式創建,管理和處置的部分原因是,有些操作系統需要以與其他操作系統完全不同的方式處理這些東西或者能夠通過揭示他們自己獨特的解決方案來提供更好的解決方案。

相關問題