¿Debería desenlazar los tampones?

12

Estoy haciendo algunas pruebas con OpenGL ES 2 y tengo algunas preguntas, mi programa actual es así:

Init
-------
-> create index buffer
-> fill index buffer glBufferData 
-> create vertex buffer
-> fill vertex buffer glBufferData 

Draw
-------
 1. Apply vertex buffer

    -> Bind VAO
       -> bind vertex buffer
          - enable attributs (glVertexPointer, …)
       -> unbind vertex buffer
    -> Unbind VAO
    -> Bind VAO

 3. Apply index buffer
 4. Draw

El problema

El bloqueo de código dado, después de algunas investigaciones, he entendido por qué: necesito desvincular mi búfer de índice en la parte init (después de "llenar el búfer de índice glBufferData") o desvincularlo antes del primer "Bind VAO"

Mis preguntas son:

  • ¿Puedo poner mi buffer de índice en VAO (VAO stock index buffer?)?
  • ¿Tenía que desvincular buffers después de cada actualización (glBufferData)?

En mi aplicación, tengo algunos buffers que se actualizan en cada cuadro (Ejemplo: Partículas), así que tengo una pila de OpenGL como esta:

-> bind buffer 1
-> update buffer 1
-> close buffer 1
-> bind buffer 1
-> draw

Las primeras 3 líneas actualizan el búfer Vertex, los dos últimos objetos de dibujo, que deberían ser algo así:

-> bind buffer 1
-> update buffer 1
-> draw

Gracias

user30088
fuente

Respuestas:

12

Parece que está haciendo mucho en encuadernación / desvinculación innecesaria. Si está utilizando un VAO, solo debe vincular el VAO cuando lo configura y al dibujar la geometría. Solo vincula VBO / IBO nuevamente cuando necesita actualizarlos.

Después de dibujar o actualizar un búfer, no necesariamente tiene que desvincularlo, aunque podría ser una buena idea hacerlo para evitar escrituras accidentales en los búferes que quedaron enlazados.

Ahora tomando su primera secuencia de operaciones, este es el orden general que esperaría ver:

En init:

  1. Crear y vincular una VAO. Cualquier VBO e IBO que enlace en la secuencia se asociará con el VAO actual (este).

  2. Crear y vincular el búfer de índice.

    • Rellenar el búfer de índice con glBufferData/glMapBuffer.
  3. Crear y vincular buffer de vértices.

    • Rellenar el búfer de vértices glBufferData/glMapBuffer.
  4. Configure los atributos de vértice con glEnableVertexAttribArray/glVertexAttribPointer, etc.

  5. Opcionalmente, desvincula todo para evitar modificaciones accidentales de los buffers y VAO. Recuerde desvincular el VAO primero . P.ej:glBindVertexArray(0);

En el sorteo:

  1. Si solo dibuja los tampones :

    • Atar a la VAO;
    • Realice las llamadas de sorteo.
  2. Si actualiza y dibuja :

    • Atar el VAO, VBO, IBO;
    • Actualice los búferes (la actualización de los atributos de vértice solo es necesaria si el formato del vértice ha cambiado);
    • Realice las llamadas de sorteo.
  3. Opcionalmente, desvincula para evitar modificaciones accidentales de los buffers y VAO.

Eso es tan simple como eso. Este orden de operaciones debería funcionar sin problemas.

glampert
fuente
2
Quisiera agregar que en mis experimentos (2014) con casos de la vida real (pero con sombreadores simples para evitar cuellos de botella en la GPU), descubrí que las mejoras de rendimiento con VAO son insignificantes (<2% de ahorro de CPU) después de realizar un pedido adecuado de las llamadas de renderizado se implementó para omitir por completo la configuración de VBO cuando se usa el mismo VBO en llamadas de renderizado consecutivas (10 a 33% de ahorro de CPU), y eliminé algunos errores de los controladores con VAO, así que terminé apagándolos por defecto. Era incluso menos significativo cuando se usaban sombreadores complejos, MSAA, etc., que causan un cuello de botella en la GPU que deja a la CPU esperando de todos modos incluso en dispositivos móviles.
Stephane Hockenhull
2
Tenga en cuenta que la desalineación de los datos de vértice de una manera que no sea compatible con el hardware obligará a los controladores de GPU a reordenar los datos de VBO en cada configuración, mientras que los controladores pueden reordenarlos una vez con VAO siempre que no se cambie nada, por lo que YMMV. Lo mejor es alinear y rellenar datos de vértices de todos modos.
Stephane Hockenhull
1
¿Por qué la VAO debe estar desligado antes que todo lo demás?
Daniel Safari
@DanielSafari, ¿quieres decir después de la configuración? Si primero se desenlazara un búfer (búfer de unión 0 / nulo), se eliminaría ese punto de unión en el VAO actual. Es por eso que el VAO nulo debe establecerse primero.
glampert
@glampert: no, no es así como funcionan los enlaces; el enlace del búfer se usa cuando se llama a glVertexAttribPointer, y no de otra manera (excepción: GL_ELEMENT_ARRAY_BUFFER). Cambiar el enlace del búfer después de su llamada glVertexAttribPointer no tiene ningún efecto.
Maximus Minimus