objective-c ios multithreading opengl-es eaglcontext

objective c - ¿Se pueden compartir los objetos de matriz Vertex(VAO) en EAGLContexts en OpenGL ES?



objective-c ios (1)

Spoiler: Estoy bastante seguro de que la respuesta es NO , pero eso es solo después de un día de depuración muy frustrada. Ahora me gustaría saber si ese es realmente el caso (y si es así, cómo podría haberlo sabido), o si simplemente estoy haciendo algo completamente incorrecto.

Aquí está la situación. Estoy usando OpenGL ES 2.0 para renderizar algunas mallas que cargo desde varios archivos (.obj, .md2, etc.). En aras del rendimiento y la experiencia del usuario, delego la carga real de estas mallas y sus texturas asociadas a un subproceso de fondo con GCD.

De acuerdo con Apple''s instructions Apple''s , en cada subproceso en segundo plano, creo y establezco un nuevo EAGLContext con el mismo shareGroup que el contexto de representación principal. Esto permite que los objetos OpenGL, como los objetos de textura y de búfer, que se crearon en el subproceso de fondo sean utilizados inmediatamente por el contexto en el subproceso principal.

Esto ha estado funcionando espléndidamente. Ahora, recientemente aprendí sobre los objetos de matriz de vértices como una forma de almacenar en caché el estado de OpenGL asociado con la representación del contenido de ciertos búferes. Se ve bien, y reduce la verificación del estado y el código de configuración requeridos para renderizar cada malla. Además de todo esto, Apple también recomienda usarlos en su Guía de mejores prácticas para trabajar con datos de vértice .

Pero estaba teniendo serios problemas para que las VAO funcionaran para mí. Como hago con toda la carga, cargaría la malla de un archivo en la memoria en un subproceso en segundo plano y luego generaría todos los objetos asociados con OpenGL. Sin falta, la primera vez que intenté llamar a glDrawElements() utilizando un VAO, la aplicación se bloquea con EXC_BAD_ACCESS . Sin el VAO, queda bien.

Depurar EXC_BAD_ACCESS es una molestia, especialmente cuando NSZombies no ayuda (lo que obviamente no lo harán), pero después de un tiempo de análisis de las tramas OpenGL capturadas, me di cuenta de que, aunque la creación de la VAO en el subproceso de fondo fue buena GL_ERROR y un ID distinto de cero), cuando llegó el momento de vincularse al VAO en el subproceso principal, obtendría un GL_INVALID_OPERATION , que el estado de los documentos sucederá cuando se intente vincular a un VAO no existente. Y, efectivamente, cuando se observan todos los objetos en el contexto actual en el momento de la renderización, no se puede ver un solo VAO, sino que están presentes todos los VBO que se generaron con el VAO AL MISMO MOMENTO . Si cargo el VAO en el hilo principal, funciona bien. Muy frustrante.

Destilé el código de carga a una forma más atómica:

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

Cuando se ejecuta lo anterior en un subproceso en segundo plano, con un EAGLContext válido con el mismo shareGroup que el contexto principal, el contexto principal tendrá 4 VBO, pero no VAO. Si lo ejecuto en el hilo principal, con el contexto principal, tendrá 4 VBO y VAO. Esto me lleva a la conclusión de que existe una excepción extraña a la naturaleza de compartir objetos de EAGLContext s cuando se trata de VAO. Si ese fuera realmente el caso, realmente hubiera esperado que los documentos de Apple lo notaran en alguna parte. Es muy incómodo tener que descubrir pequeños detalles como ese a mano. ¿Es este el caso, o me estoy perdiendo algo?


De acuerdo con this , OpenGL-ES explícitamente no permite compartir objetos VAO:

¿Los objetos de matriz de vértices pueden compartirse en múltiples contextos de OpenGL ES?

RESUELTO: No. El grupo de trabajo de OpenGL ES realizó una encuesta y estuvo de acuerdo en que la compatibilidad con OpenGL y la facilidad de implementación eran más importantes que la creación del primer objeto con nombre no compartido en OpenGL ES.

Como notó, los VBO aún se pueden compartir, así que solo tiene que crear un VAO para cada contexto que vincula al VBO compartido.