2013-06-20 9 views
5

Sono su iOS 6.1.4, OpenGL ES 2 e sto riscontrando un comportamento strano con glGenTextures restituendo "nomi" di texture che sono stati precedentemente restituiti da glGenTextures.glGenTextures Restituzione nome trama esistente

In particolare, in fase di inizializzazione, ho scorrere le mie trame e fare OpenGL consapevoli di loro, in questo modo:

// Generate the OpenGL texture objects 
for (Object3D *object3D in self.objects3D) 
{ 
    [self installIntoOpenGLObject3D:object3D]; 
} 

- (void)installIntoOpenGLObject3D:(Object3D *)object3D 
{ 
    GLuint nID; 
    glGenTextures(1, &nID); 

    Texture *texture = object3D.texture; 
    texture.identifier = nID; 
    glBindTexture(GL_TEXTURE_2D, nID); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, [texture width], [texture height], 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)[texture pngData]); 
    ARLogInfo(@"Installed texture '%@' with OpenGL identifier %d", texture.name, texture.identifier); 
} 

In questo momento, vedo nomi di texture come 1, 2, 3, ... n come previsto.

Tuttavia, qualche volta dopo (dopo una chiamata di rete asincrona restituisce) creo nuove trame e chiamo installIntoOpenGLObject3D: per installarle. È in questo momento successivo che vedo i nomi di ritorno glGenTextures che sono stati emessi in precedenza. Ovviamente questo fa sì che l'app renda la texture errata.

La documentazione, http://www.khronos.org/opengles/sdk/docs/man/xhtml/glGenTextures.xml, suggeriscono che:

nomi Texture restituiti da una chiamata a glGenTextures non vengono restituiti dalle chiamate successive, a meno che non siano in primo luogo cancellati con glDeleteTextures.

e non sto effettuando chiamate allo glDeleteTextures; tuttavia i documenti dicono:

è garantito che nessuno dei nomi restituiti era in uso immediatamente prima della chiamata a glGenTextures.

che è fonte di confusione, in quanto implica che i nomi restituiti potrebbe essere la stessa se non fossero "in uso". A quanto mi risulta, chiamando lo glBindTexture per la texture soddisfa la nozione "in uso", ma qualcosa non va.

Un altro pensiero che avevo era forse il EAGLContext stava cambiando da qualche parte tra la prima serie di chiamate a glGenTextures ma, ahimè, passando attraverso nel debugger mi dice che il contesto non cambia.

Come soluzione alternativa (forse folle) ho tentato di garantire che i nomi delle texture fossero unici, come potete vedere qui sotto, tuttavia ho semplicemente un nome di trama che non tracciamo, ma rappresenta anche un altro tessitura, per cui questo approccio non fornisce una soluzione:

- (void)installIntoOpenGLObject3D:(Object3D *)object3D 
{ 
    if (!self.object3DTextureIdentifiers) 
    { 
     self.object3DTextureIdentifiers = [NSMutableSet set]; 
    } 

    GLuint nID; 
    NSNumber *idObj; 
    do { 
     glGenTextures(1, &nID); 
     GLboolean isTexture = glIsTexture(nID); 
     idObj = [NSNumber numberWithUnsignedInt:nID]; 
    } while ([self.object3DTextureIdentifiers containsObject:idObj]); 

    [self.object3DTextureIdentifiers addObject:idObj]; 

    Texture *texture = object3D.texture; 
    texture.identifier = nID; 
    glBindTexture(GL_TEXTURE_2D, nID); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, [texture width], [texture height], 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)[texture pngData]); 
    ARLogInfo(@"Installed texture '%@' with OpenGL identifier %d", texture.name, texture.identifier); 
} 

Dei pensieri su perché glGenTextures sta tornando nomi che in precedenza restituito?

+0

Oh, e ho dimenticato di menzionare che la chiamata 'glIsTexture' nel' do while' restituisce sempre false. – levigroker

+0

Il semplice fatto di postare il tuo post mi ha fatto pensare che stai utilizzando più thread su cui lo fai. Potresti provare a forzare il caricamento delle texture più tardi, ad essere sullo stesso thread del primo caricamento e segnalare se il problema persiste.(ogni thread dovrebbe creare il proprio contesto e se si desidera condividere il contenuto tra i contesti è necessario utilizzare un gruppo di condivisione) –

+0

Grazie Matic. Ho il doppio (triplo?) Controllato e la chiamata a 'glGenTextures' si verifica sempre sul thread principale. – levigroker

risposta

3

Dopo tanto debug, credo che la causa principale sia il threading.

Mentre ero sicuro che glGenTextures venisse chiamato solo da un thread (principale), risulta che le chiamate ad altri metodi OpenGL venivano chiamate su un thread diverso. Refactoring in modo che le chiamate a glGenTextures si verifichino anche solo su quell'altro thread (non principale) sembra risolvere il problema.