performance - usar - Preguntas de rendimiento de bajo nivel de OpenGL
usar procesador grafico photoshop desactivado (4)
Este tema, como con cualquier problema de optimización, se golpea mucho, pero simplemente no pude encontrar lo que (creo) que quiero.
Una gran cantidad de tutoriales, e incluso SO preguntas tienen consejos similares; generalmente cubriendo
- Use GL face culling (la función OpenGL, no la lógica de la escena)
- Solo envíe 1 matriz a la GPU (combinación projectionModelView), por lo tanto, disminuyendo los cálculos de MVP de por vértice a una vez por modelo (como debería ser).
- Utilizar vértices intercalados.
- Minimice la mayor cantidad posible de llamadas GL, por lotes cuando sea apropiado
Y posiblemente algunos / muchos otros. Estoy (por razones de curiosidad) renderizando 28 millones de triángulos en mi aplicación usando varios buffers de vértices. He probado todas las técnicas anteriores (según mi leal saber y entender) y casi no he cambiado el rendimiento.
Si bien recibo alrededor de 40FPS en mi implementación, lo que no es en modo alguno problemático, sigo sintiendo curiosidad por saber dónde se ponen en uso estos "consejos" de optimización.
Mi CPU está inactiva en torno al 20-50% durante el renderizado, por lo que supongo que estoy destinado a GPU para aumentar el rendimiento.
Nota: estoy buscando en gDEBugger en este momento
Cross publicado en Game Development
- Sí
- No tiene sentido ya que el conductor puede combinar estas matrices por usted (sabe que son uniformes, por lo que no cambiará durante la llamada del sorteo).
- Sí
- solo si estas ligado a la CPU
Lo primero que debe saber es dónde está exactamente su cuello de botella. GPU no es una respuesta, porque es un sistema complejo. El problema real podría estar entre estos:
- Procesamiento de sombreado (vértice / fragmento / geometría)
- Tasa de relleno
- Llamar número de llamadas
- GPU <-> VMEM (ahí es donde ayudan el intercalado y las texturas más pequeñas)
- Sistema de bus (¿transmitiendo algunos datos a cada fotograma?)
Es necesario realizar una serie de pruebas para ver el problema. Por ejemplo, dibuje todo a un FBO más grande para ver si se trata de un problema de tasa de llenado (o aumente la cantidad de MSAA). O dibuje todo dos veces para verificar los problemas de sobrecarga de la llamada de sorteo.
El punto 1 es obvio, al igual que la tasa de relleno ahorra. En caso de que las primitivas de la parte trasera de un objeto se procesen primero, se omitirán esas caras. Sin embargo, las GPU modernas toleran el sobregiro bastante bien. Una vez (GeForce8800 GTX) medí hasta un 20% de sobregiro antes de un impacto significativo en el rendimiento. Pero es mejor guardar esta reserva para cosas como el sacrificio de oclusión, la representación de la geometría combinada y similares.
El punto 2 es, bien inútil. Las matrices nunca se han calculado en la GPU; bueno, si no se cuenta el SGI Onyx. Las matrices siempre fueron solo un tipo de parámetro global de representación calculado en la CPU, y luego insertadas en registros globales en la GPU, ahora llamado uniforme, por lo que unirlas tiene muy poco beneficio. En el sombreador que guarda solo una multiplicación de matriz vectorial adicional (se reduce a 4 instrucciones MAD), a expensas de una menor flexibilidad algorítmica.
El punto 3 tiene que ver con la eficiencia del caché. Los datos que pertenecen juntos deben caber en una línea de caché.
El punto 4 se trata de evitar que los cambios de estado destruyan los cachés. Pero depende en gran medida de qué llamadas GL significan. Cambiar de uniformes es barato. Cambiar una textura es caro. La razón es que un uniforme se encuentra en un registro, no un pedazo de memoria que se almacena en caché. Cambiar un sombreador es costoso, ya que los diferentes sombreadores muestran un comportamiento de tiempo de ejecución diferente, lo que destruye la predición de ejecución de la canalización, altera la memoria (y por lo tanto) los patrones de acceso a la memoria caché, etc.
Pero esas son todas optimizaciones micro (algunas de ellas con gran impacto). Sin embargo, recomiendo buscar en optimizaciones de gran impacto, como implementar un paso Z temprano; utilizando la consulta de oclusión en la Z temprana para una rápida discriminación de lotes de geometría completa. Una optimización de gran impacto, que consiste esencialmente en sumar una gran cantidad de micro optimizaciones tipo Point-4, es ordenar los lotes de procesamiento por estados GL caros. Así que agrupa todo con sombreadores comunes, dentro de esos grupos ordenados por textura y así sucesivamente. Esta agrupación de estado solo afectará las pasadas de render visible. Al principio de Z, solo estás probando los resultados en el búfer Z, por lo que solo hay transformación de geometría y los sombreadores de fragmentos solo pasarán el valor Z.
Esto depende mucho de qué hardware en particular está ejecutando y cuáles son los escenarios de uso. Las sugerencias de rendimiento de OpenGL tienen sentido para el caso general: la biblioteca es, después de todo, una abstracción sobre muchas implementaciones de controladores diferentes. Los fabricantes de controladores son libres de optimizar lo que quieran bajo el capó, por lo que pueden eliminar los cambios de estado redundantes o realizar otras optimizaciones sin su conocimiento. En otro dispositivo, no pueden. Es mejor atenerse a las mejores prácticas para tener una mejor oportunidad de un buen rendimiento en una variedad de dispositivos.
Solo para agregar mis 2 centavos a las respuestas de @kvark y @datenwolf, me gustaría decir que, si bien los puntos que menciona son consejos de rendimiento de GPU "básicos", la optimización más compleja depende mucho de la aplicación.
En su caso de prueba de geometría pesada, ya está lanzando 28 millones de triángulos * 40 FPS = 1120 millones de triángulos por segundo; esto ya es bastante: la mayoría de las GPU (no todas, especialmente Fermi) tienen una configuración de triángulo de 1 triángulo por ciclo de reloj de GPU. Lo que significa que una GPU que se ejecuta a 800 MHz, digamos, no puede procesar más de 800 millones de triángulos por segundo; Esto sin siquiera dibujar un solo píxel. NVidia Fermi puede procesar 4 triángulos por ciclo de reloj.
Si está alcanzando este límite (no menciona su plataforma de hardware), no hay mucho que pueda hacer en el nivel de OpenGL / GPU. Todo lo que puede hacer es enviar menos geometría, a través de una selección más eficiente (frustum u oclusión), o a través de un esquema LOD.
Otra cosa es que los pequeños triángulos dañan la velocidad de relleno ya que los rasterizadores hacen un procesamiento paralelo en bloques cuadrados de píxeles; vea http://www.geeks3d.com/20101201/amd-graphics-blog-tessellation-for-all/ .