Les objects Vertex Array Objects (VAO) peuvent-ils être partagés entre EAGLContexts dans OpenGL ES?

Spoiler: Je suis assez confiant que la réponse est NO , mais c'est seulement après une journée de debugging très frustré. Maintenant, je voudrais savoir si c'est effectivement le cas (et si oui, comment je pourrais avoir connu), ou si je fais juste quelque chose de complètement faux.

Voici la situation. J'utilise OpenGL ES 2.0 pour rendre certaines mailles que je charge depuis différents files (.obj, .md2, etc.). Par souci de performance et d'expérience user, je délègue le chargement réel de ces maillages et de leurs textures associées à un fil de fond en utilisant GCD.

Selon les instructions d'Apple , sur chaque thread d'arrière-plan, je crée et définit un nouvel EAGLContext avec le même shareGroup que le context de rendu principal. Cela permet aux objects OpenGL, comme les objects de texture et de tampon, créés sur le thread d'arrière-plan, d'être immédiatement utilisés par le context sur le thread principal.

Cela a fonctionné magnifiquement. Maintenant, j'ai récemment appris sur Vertex Array Objects comme un moyen de mettre en cache l'état OpenGL associé au rendu du contenu de certains tampons. Cela a l'air sympa et réduit la vérification de l'état standard et le code de réglage requirejs pour rendre chaque maillage. Pour couronner le tout, Apple recommand également de les utiliser dans leur guide des meilleures pratiques pour travailler avec Vertex Data .

Mais j'avais de sérieux problèmes à faire travailler les VAO pour moi. Comme je le fais avec tout le chargement, je voudrais charger le maillage d'un file dans la memory sur un thread d'arrière-plan, puis générer tous les objects OpenGL associés. Sans EXC_BAD_ACCESS , la première fois que j'ai essayé d'appeler glDrawElements() utilisant un VAO, l'application plante avec EXC_BAD_ACCESS . Sans le VAO, ça rend bien.

EXC_BAD_ACCESS est une douleur, surtout quand NSZombies ne va pas aider (ce qui ne sera évidemment pas le cas), mais après un certain time d'parsing des frames OpenGL capturés, j'ai réalisé que, bien que la création du VAO sur le thread de fond se passe GL_ERROR , et un ID différent de zéro), quand le time est venu de se lier au VAO sur le thread principal, j'obtiendrais un GL_INVALID_OPERATION , que l' état de docs arrivera en essayant de se lier à un VAO inexistant. Et bien sûr, en regardant tous les objects dans le context actuel au moment du rendu, il n'y a pas un seul VAO à voir, mais toutes les VBO qui ont été générées avec le VAO EN MÊME TEMPS sont présentes . Si je charge le VAO sur le fil principal, cela fonctionne très bien. Très frustrant.

J'ai distillé le code de chargement à une forme plus atomique:

 - (void)generate { glGenVertexArraysOES(1, &_vao); glBindVertexArrayOES(_vao); _vbos = malloc(sizeof(GLuint) * 4); glGenBuffers(4, vbos); } 

Lorsque ce qui précède est exécuté sur un thread d'arrière-plan, avec un EAGLContext valide avec le même shareGroup que le context principal, le context principal aura 4 VBO, mais pas de VAO. Si je l'exécute sur le thread principal, avec le context principal, il aura 4 VBO, et le VAO. Cela m'amène à la conclusion qu'il existe une étrange exception à la nature du partage des EAGLContext de EAGLContext lorsqu'il s'agit de VAO. Si c'était le cas, je m'attendais vraiment à ce que les docs Apple notent ça quelque part. C'est très gênant d'avoir à découvrir de petites friandises à la main. Est-ce le cas, ou ai-je oublié quelque chose?

En conséquence, OpenGL-ES interdit explicitement le partage d'objects VAO:

Les objects de tableau de sumt devraient-ils être partageables entre plusieurs contexts OpenGL ES?

RÉSOLU: Non. Le groupe de travail OpenGL ES a fait un sondage et a convenu que la compatibilité avec OpenGL et la facilité d'implémentation étaient plus importantes que la création du premier object nommé non partagé dans OpenGL ES.

Comme vous l'avez noté, les VBO sont toujours partageables, il vous suffit donc de créer un VAO pour chaque context qui lie le VBO partagé.