2011-10-24 23 views
10

Sto sperimentando con la scrittura di un motore di gioco per Android con OpenGL ES. Ho creato una discussione di gioco che aggiorna gli oggetti del gioco e GLThread con la scena. Avevo letto che è necessario caricare le trame nel metodo onSurfaceCreated di GLSurfaceView. Sto seguendo questo, ma per qualche scopo di debug stavo cercando di caricare trame dal mio thread di gioco invece del GLThread. Non ho avuto errori e la texture non è stata visualizzata sullo schermo. Ho passato tutta la giornata a cercare di capire il problema e alla fine ho letto il seguente herePerché le funzioni OpenGL ES non possono essere chiamate da un'altra discussione

"Assicurati di utilizzare solo OpenGL nel thread principale." Molto importante. Non puoi chiamare il tuo Game Engine (che potrebbe trovarsi in un'altra discussione) una funzione di caricamento della trama che non è sincronizzata con il gl-thread. Imposta un flag per segnalare il tuo gl-thread per caricare una nuova texture (ad esempio, puoi inserire una funzione in OnDrawFrame (GL gl) che controlla se deve essere caricata una nuova texture

Modificherò il mio codice in modo che le trame vengano caricate dal thread GL. Non riesco proprio a capire perché è così? Perché le funzioni OpenGL non funzionano da un altro thread?

So come creare thread ma non so cosa mezzi di sincronizzazione. L'estratto sopra menziona, "Non puoi chiamare il tuo Game Engine (che potrebbe essere in un altro thread) una funzione di caricamento della trama che non è sincronizzata con il gl-thread." Quindi penso che il mio Thread di gioco potrebbe non essere sincronizzato con il GL Thread. È possibile creare un altro thread che è sincronizzato con il GL Thread in modo che le funzioni GL possano essere chiamate da esso? Cosa dovrei imparare nel threading per comprendere questi concetti?

+5

Non sono un ragazzo Android, ma in iOS ci sono due ragioni per avvertimenti simili: uno è che il contesto GL corrente è specifico del thread, quindi è necessario trasferire la valuta di contesto attraverso i thread e la seconda (altro importante) è che fare confusione con lo stato GL da più thread senza sincronizzazione finisce per danneggiare lo stato del contesto GL. HTH. –

+0

Penso che sia solo per evitare l'accesso concurent –

risposta

8

Il commento di quixoto è il più vicino, penso. La ragione tradizionale per cui i contesti OpenGL sono specifici per thread su praticamente tutte le piattaforme è che OpenGL è fortemente dipendente dagli stati e non ha semantica per fare atomiche una serie di modifiche. Così, per esempio, l'operazione di disegno su un thread potrebbe essere:

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

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

Quindi la chiamata finale fornisce risultati prevedibili solo nel contesto delle chiamate precedenti. Se consenti che quel bit di codice venga messo in pausa dopo, ad esempio, glVertexPointer, un altro thread hopping e facendo la stessa sequenza per disegnare la sua geometria e poi questo codice procedendo, disegnerà con una geometria del tutto sbagliata, forse anche causando -di-limiti di accesso alla memoria se alcuni degli array sostituiti sono più piccoli degli originali.

Android fornisce EGL, che supporta il concetto comune di un gruppo di condivisione OpenGL (sebbene implicitamente, si fornisce un contesto esistente in cui si desidera un nuovo contesto in un gruppo comune con il terzo argomento su eglCreateContext). Se due contesti sono in un gruppo di condivisione, ciascuno di essi ha uno stato indipendente ed è sicuro chiamare da un solo thread, ma gli oggetti denominati come trame o oggetti buffer vertice sono disponibili per ciascuno di essi. Pertanto, utilizzando i gruppi di condivisione è possibile eseguire azioni OpenGL su più thread contemporaneamente in modo da poter combinare i risultati su un singolo thread.

Unire un contesto a un singolo thread non è quindi un problema. Anche pianificare il problema in OpenGL sarebbe un non-starter, perché parte del motivo per cui i contesti OpenGL sono creati, gestiti e smaltiti in modo specifico per il sistema operativo è che alcuni sistemi operativi devono gestire questa roba in modo radicalmente diverso dagli altri o sono in grado di offrire soluzioni migliori esponendo le proprie soluzioni uniche.

Problemi correlati