¿Usando instancias para todo?


16

La instancia mejora el rendimiento (significativamente) cuando se procesan varias copias (¿miles? ¿Miles?) De la misma malla a la vez. Pero, ¿cuánto sobrecarga tiene cuando se procesa exactamente una copia con una llamada de extracción? ¿Sería una buena o mala idea usar instancias para toda la geometría renderizada por el motor?

Editar: Digamos que estamos creando un juego FPS. La mayoría de los objetos tienen una sola instancia: un cuchillo, una pistola, una ametralladora, un edificio y una torre de radio. Pero también hay algunos objetos con múltiples instancias: árboles (por ejemplo, 3 tipos de árboles con cientos de instancias), hierba, etc. Lo que quiero decir es: en lugar de representar los objetos de una instancia de la manera "tradicional" y los árboles y hierba usando instancias, los renderizamos todos usando instancias. Entonces, nuestra torre de radio tiene solo una instancia (cuya información almacenamos en un búfer de datos de instancia) y representamos esa torre usando algún tipo de DrawInstanced()llamada con el recuento de instancias igual 1. Lo mismo con todos los demás objetos (por supuesto, los árboles y el césped tienen múltiples instancias).

Entonces mi pregunta es: ¿es una mala idea dibujar una sola instancia de un objeto usando instancing? ¿La creación de instancias tiene demasiada sobrecarga (en cuanto a memoria y rendimiento) o es de alguna manera no deseada para representar objetos de instancia única?

Respuestas:


19

Con D3D9 con XPDM, es casi seguro que desee instanciar siempre que sea posible. La sobrecarga de llamadas de extracción es tan alta que tiene sentido. En ese escenario, el punto de cruce puede ser tan bajo como 2 o 3 instancias.

Si solo tiene una instancia de una malla determinada, en la superficie puede parecer tentador dibujarla sin instancias. Sin embargo, mira lo que implica:

  • Debe pasar de cargar datos en un búfer por instancia a cargar constantes de sombreador.
  • Debe conservar dos copias de su sombreador de vértices: uno para instanciados y otro para no instanciados.
  • Debe conservar dos copias de su código de representación: de la misma manera.
  • Necesitas cambiar los sombreadores.
  • Necesita cambiar los formatos de vértice.
  • Es posible que deba cambiar los búferes de vértices.
  • Y luego debe hacerlo de nuevo si va a volver al dibujo instanciado para el próximo grupo de mallas.

Incluso si solo tiene una malla única (como el modelo de pistola en un FPS), hay casos en los que la instancia es útil. Digamos que está haciendo acumulación de luz multipass en un renderizador hacia adelante y con un z-prepass. En lugar de un pase adicional para cada luz, crea sus datos de luces por instancia y los dibuja de forma instanciada.

Basado en el primer escenario, la moraleja de la historia es que si alguna clase de objeto puede usar instancias, tiene sentido usar siempre instancias para todos los objetos de esa clase.

Basado en el segundo escenario, la moraleja de la historia es que la creación de instancias puede tener usos no obvios que van más allá de simplemente decir "Necesito dibujar 20 árboles".


Las razones que diste son las mismas que me hicieron hacer esta pregunta en primer lugar. Gracias.
NPS

12

(En mi sistema, no lo probé en ningún otro lado) En GL, la creación de una sola malla (dibujo con conteo = 1) tiene una sobrecarga desagradable, pero no sé de dónde viene. Sugiero no hacerlo.

Probé esto en una aplicación práctica hace un par de meses. Codifiqué algunos algoritmos de iluminación global en la escena Crytek Sponza, que consta de aproximadamente 350 mallas (no recuerdo exactamente), de las cuales un par comparte un puñado de casos. Al principio lo hice como sugieres, simplemente instancia todo y dibuja el resto con el recuento de instancias de 1, ya que simplificó un poco el código de representación.

Más adelante, cuando optimicé el renderizador, simplemente volví de instanciar los objetos count = 1 a enviarlos de la manera habitual, lo que me ahorró aproximadamente 3.5 milisegundos por fotograma en un i7 3770k (y GTX 770). Cambiar las mallas con múltiples instancias a solo hacerlo de la manera tradicional me ahorró otros 0.5 ms. En general, la aplicación pasó de ~ 120 FPS a aproximadamente ~ 230 FPS.

Estas cifras, por supuesto, siempre dependen de dónde están los cuellos de botella en su aplicación, y los últimos 0.5 ms podrían llegar a ser más lentos en una aplicación en la que está muy atraído por las llamadas de llamada. Pero de lo contrario, en mi experiencia, la instancia tiene algunos gastos generales desagradables si no está dibujando muchas cosas a la vez.


Interesante, pero sería bueno ver los datos de los controladores AMD e Intel también, de lo contrario, realmente debería decir "En mi sistema" en lugar de "En GL". Por otro lado, incluso si no es un problema con otras implementaciones, el hecho de que podría estar relacionado con algunas es una razón suficiente para evitar instancias si no lo está utilizando.
bcrist

2

Puede estar seguro de que dibujar un solo objeto instanciado es más costoso que dibujar un solo objeto normalmente. Para la creación de instancias, la GPU se está preparando para una gran cantidad de objetos y esta preparación será diferente a la de un solo objeto. Sin embargo, cuán grande es esta brecha de rendimiento solo se puede encontrar experimentando y depende en gran medida de su configuración de representación real. La única forma de saberlo con certeza es probándolo usted mismo. Es difícil comparar una sola llamada de sorteo aquí hay varias ideas sobre cómo podría proceder.


2

Han pasado 4 años ... y creo que es seguro decir que está perfectamente bien enviar llamadas de sorteo "instanciadas" con 1. Como habrás notado, las nuevas API DX12 y Vk tienen un recuento de instancias que puede ser de 0 a NUM_INSTANCES . También tenga en cuenta que no hay DrawIndexed (...) .

EDITAR

Como nota de precaución, lo anterior probablemente esté bien con estas API modernas, tal vez usar algo antiguo como Gl <3.3 o quizás DX11 requerirá algunos perfiles como lo mencionan otros usuarios.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.