Esta es una pregunta compleja con muchos pequeños detalles que realmente importan, el rendimiento variará según la plataforma y la aplicación. Por lo tanto, debe hacer un perfil de posibles cuellos de botella antes de invertir en optimizaciones.
Dicho esto, en primer lugar, supongo que debe reducir las cargas y actualizaciones tanto como pueda, por ejemplo, usar instancias.
En segundo lugar, tenga en cuenta que las GPU no pueden transferir buffers y renderizar al mismo tiempo, por lo que el dispositivo procesa secuencialmente todos los comandos de OpenGL en la cola de comandos. Existen diferentes formas de copiar datos y / o hacer que estén disponibles para que la GPU los use.
Hay varias formas de transmitir datos a la GPU
1- glBufferData
o glBufferSubData
método
Usar glBufferData
o glBufferSubData
es como memcpy. se pasa un puntero y se puede realizar una operación DMA , dije que podría porque la memoria podría estar anclada en la memoria de la CPU y utilizada directamente por la GPU sin que realmente se produzca una transferencia de memoria a la GPU, dependiendo del indicador de uso (GL_STREAM). En opinión, deberías probar esto al principio porque es más sencillo de implementar.
2- obtener un puntero a la memoria interna usando glMapBuffer
Si lo anterior no es lo suficientemente bueno que puede usar glMapBuffer
, obtiene un puntero a la memoria interna, y puede usar este puntero para llenar el búfer directamente, esto es bueno con las operaciones de lectura y escritura de archivos, ya que puede asignar directamente los datos del archivo a la memoria de la GPU en lugar de copiar primero a un búfer temporal. Si no desea mapear todo el búfer, puede usarlo glMapBufferRange
para mapear una parte del búfer.
Un truco es crear un búfer grande, usar la primera mitad para renderizar y la segunda mitad para actualizar.
3- Huérfano de búfer
Con respecto a la huérfana del búfer, esto se puede hacer usando glBufferData con nulo y los mismos parámetros que tenía. El controlador devolverá el bloque de memoria una vez que no se use. Y será utilizado por la próxima llamada glBufferData (no se asignará memoria nueva).
Todos los métodos mencionados causan una gran cantidad de sincronización costosa, nuevamente las GPU no pueden transferir buffers y renderizar al mismo tiempo.
4- Unsynchronized Buffers
El método más rápido (y el más difícil de acertar) es usar buffers sin sincronización con los que puede usar el GL_MAP_UNSYNCHRONIZED_BIT
indicador glMapBufferRange
, el problema es que no se realiza la sincronización, por lo que podríamos cargar datos en un buffer comenzar a usar, y por lo tanto arruinar todo. Puede usar múltiples buffers con bit de sincronización para facilitar un poco las cosas.