Foros - Stratos

Programadores => Programación gráfica => Mensaje iniciado por: tewe76 en 13 de Enero de 2009, 04:10:17 PM

Título: ¿Triángulos por segundo normales?
Publicado por: tewe76 en 13 de Enero de 2009, 04:10:17 PM
Hola :)
Estoy haciendo pruebas de rendimiento con el engine irrlicht sobre C++ y me han sorprendido negativamente >:( . Pero como soy novato en 3D (más o menos), en el motor irrlicht y en C++ (estoy aprendiendo sobre la marcha), quería compartir los resultados a ver si son normales o es que estoy haciendo algo mal.

Tened en cuenta que las pruebas las hago en un PC con XP, que el ordenador es bueno, FarCry2 y semejantes me van perfectamente con calidad alta. Para las pruebas uso DX8 (aunque con DX9 sale semejante, con OGL un poco menos).

Prueba 1: cargo un archivo "aaa.3ds", que es básicamente un cubo modificado, con un total de 20 triángulos. Sin textura.
Número de Copias que dibujo -> Frames Por Segundo
1->7500
10->6800
10x10->2000
100x10->250
100x100->25
1000x100->3
Nota 1: irrlicht permite "invisibilizar" los meshes. Así, dibujando 1000x100 copias, pero con todas invisibles menos:
100x100 -> 17 FPS
100x10 -> 45 FPS
1 -> 50 FPS
Es decir, si "dibujo" 100.000 copias, aunque sólo haya una visible, lo máximo que consigo son 50 FPS (vamos, que afecta claramente, aunque sean invisibles).
Nota 2: estos resultados son independientes de si en pantalla estoy viendo todo (lejos) o sólo unos pocos cubos (cerca)(hasta aquí Barrio Sésamo :) ).

Prueba 2: cargo un archivo "bbb.3ds", que es básicamente un grid, con un total aprox. de 20.000 triángulos. Sin textura.
Número de Copias que dibujo -> Frames Por Segundo
1->750
5 ->220
10 ->110
10x10 -> 12
Las Notas 1 y 2 anteriores son válidas aquí también.

Conclusión:
Usando objetos de 20 tris a partir de 1000 objetos ya tiene FPS normalillos (250). Es decir: 20x1000=20.000 tris
Usando objetos de 20.000 tris puedo poner 5 objetos para conseguir aprox lo mismo (220FPS). Es decir: 20000x5=100.000 tris

Preguntas:
¿Véis normales estos resultados? ¿Es normal que un buen ordenador no pueda mover más de 3000 o 4000 cubos con fluidez?
Título: Re: ¿Triángulos por segundo normales?
Publicado por: tamat en 13 de Enero de 2009, 04:48:58 PM
Creo que cuando se trata de hacer benchmarking tienes que tener en cuenta todos los factores:
- Numero de meshes renderizados
- Numero de poligonos de cada mesh
- Pixeles que ocupa en pantalla el objeto (importante si trabajas con pixel shaders complejos)
- Ordenacion en Z (importante si tienes pixel shaders complejos)
- Complejidad de los shaders
- Pases de rendering

Como ves, no todo es "numero de poligonos"
Título: Re: ¿Triángulos por segundo normales?
Publicado por: Ruben en 13 de Enero de 2009, 05:04:14 PM
Hi,
Irrlicht usa la funcion DrawIndexedPrimitiveUP en no me acuerdo que casos, mira que no la este llamando. Si mal no recuerdo, la familia de funciones Draw*UP lo que hace es que para cada llamada crea y destruye internamente los buffers necesarios para poder pintar los vertices que les pasas. Tiene pinta de ser eso. :)

Un saludo,
Ruben
Título: Re: ¿Triángulos por segundo normales?
Publicado por: senior wapo en 13 de Enero de 2009, 05:18:49 PM
Lo que estás experimentando se llama "draw call overhead" y en este caso la culpa es de Irrlicht y de Direct3D a partes iguales.

La simplicidad de Irrlicht se paga, y es que la última vez que miré (hace ya tiempo), abusaba mucho de buffers intermedios para todo (no solo por los datos para DrawPrimitiveUP sino incluso para conversiones,listas de objetos visibles y demás).

Soluciones:
- Por la parte de Direct3D, no uses muchos objetos de poco tamaño, sino pocos buffers con mucha geometría, si es que te es viable. A ésto se le llama "batching".
- Por la parte de Irrlicht, supongo que será mejor mantener en tu grafo de escena solamente lo que sea visible e ir añadiendo y quitando nodos en cada frame en lugar de mantenerlo siempre todo dentro y ocultarlo/mostrarlo.

EDITO: Aunque visto lo visto, miedo me da pensar en como gestiona la lista de hijos de cada nodo del scenegraph.
Título: Re: ¿Triángulos por segundo normales?
Publicado por: Prompt en 14 de Enero de 2009, 08:29:49 PM
Cita de: senior wapo en 13 de Enero de 2009, 05:18:49 PM
- Por la parte de Direct3D, no uses muchos objetos de poco tamaño, sino pocos buffers con mucha geometría, si es que te es viable. A ésto se le llama "batching".

Realmente solo deberia existir 1 solo buffer, demostrado! :) es menos costoso modificar el buffer en CPU, gestionarlo en cada frame (bueno cuando tenga que cambiar, depende del frustum culling q cada uno implemente). Realmente habria que tener quizas un buffer por material no?

Mmm...bueno no, porque puedes decidir desde que "punto hasta que punto" pintar y lo metes dentro de un begin / end de un shader y listo. Si! un solo buffer vamos!
Título: Re: ¿Triángulos por segundo normales?
Publicado por: tewe76 en 15 de Enero de 2009, 10:45:20 AM
No respondo porque estoy haciendo algunas pruebecillas  :)
Vuelvo pronto...
Título: Re: ¿Triángulos por segundo normales?
Publicado por: tewe76 en 15 de Enero de 2009, 12:29:41 PM
Aquí estoy :)

Primero, rectificar lo que dije de "Nota 2: estos resultados son independientes de si en pantalla estoy viendo todo (lejos) o sólo unos pocos cubos (cerca)". Creí que era así, pero ahora no lo es: si me acerco y sólo veo unos pocos meshes suben los FPS, aunque no mucho.

Y ahora vuestros comentarios:
CitarCreo que cuando se trata de hacer benchmarking tienes que tener en cuenta todos los factores:
Sí, lo tengo en cuenta. Son unas primeras pruebas caseras, intentando simular el uso que pretendía darle para mi juego.

CitarIrrlicht usa la funcion DrawIndexedPrimitiveUP en no me acuerdo que casos, mira que no la este llamando.
Sí, podría ser éso. Pero no tengo ni idea de cómo comprobarlo. Con "DrawIndexedPrimitiveUP" te refieres a una función de DX, ¿no? El irrlicht no tiene nada que se llame así, creo.

CitarPor la parte de Direct3D, no uses muchos objetos de poco tamaño, sino pocos buffers con mucha geometría, si es que te es viable.
¿Tus "buffers" son los "Node" de irrlicht o no tiene nada que ver? Porque he probado dos cosas: meter todas las copias del mesh en un solo Node y crear un montón de Nodes cada uno con un solo mesh. El resultado es idéntico.
Ah, veo que habláis bastante de D3D. Tened en cuenta que con OGL va igual (incluso peor).
CitarPor la parte de Irrlicht, supongo que será mejor mantener en tu grafo de escena solamente lo que sea visible e ir añadiendo y quitando nodos en cada frame en lugar de mantenerlo siempre todo dentro y ocultarlo/mostrarlo.
Eso me ha parecido una buena idea, aunque no he probado si lo de crear/destruir en runtime irá a una velocidad aceptable... De todas maneras, el minimo número de "cubos" que necesito a la vez en pantalla (tienen que estar creados, por narices) ya me baja los FPS demasiado, así que aún así no sería solución.

A Prompt: tu mensaje es demasiado avanzado para mí, me temo ;). Entiendo lo que dices, pero no sabría aplicarlo.

Bueno, os dejo el código de mi prueba, es corto. A ver si véis algo que no os cuadra:
Código (cpp) [Seleccionar]
//Inicializo el irrlicht (segun los tutoriales)
#include <irrlicht.h>
using namespace irr;using namespace core;using namespace scene;
using namespace video;using namespace io;using namespace gui;
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif

int main(){
//800x600x32 Windowed
IrrlichtDevice *device = createDevice( EDT_DIRECT3D8, dimension2d<s32>(800, 600), 32,false, false, false, 0);
if (device == 0)   return 1;
//Cosillas del irrlicht...
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();

//tamanyo del array de meshes (para hacer pruebas rapidas)
const long CantX =100;const long CantZ=100;
//cargamos mesh (aaa.3ds tiene 20 tris, sin textura)
IAnimatedMesh*  mesh = smgr->getMesh("aaa.3ds");
//creamos un array de Nodes
IAnimatedMeshSceneNode* node[CantX][CantZ];

//anyadimos el Mesh a cada Node del array:
for (int a=0;a<CantX;a++){
for (int b=0;b<CantZ;b++){
//anyadimos el mesh
node[a][b] = smgr->addAnimatedMeshSceneNode( mesh,0,-1,vector3df(0,0,0));
//autoiluminado, al no usar luz externa en esta prueba
node[a][b]->setMaterialFlag(EMF_LIGHTING, false);
//ponemos cada node en su sitio, formando un "cuadrado"
node[a][b]->setPosition (vector3df(a*(2.2)-CantX/2*2,0,b*(2.2)-CantZ/2*2+1));
}
}
//anyadimos una camara (que se puede mover con las flechas y el raton, tipo FPS)
smgr->addCameraSceneNodeFPS();
//para medir los Frames Por Segundo
int lastFPS = -1;

//comienza el loop eterno
while(device->run()){
//funciones propias de irrlicht para dibujar la escena
driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll();
driver->endScene();
//calcula FPS y los pone en el caption
int fps = driver->getFPS();
if (lastFPS != fps) {core::stringw str = L"["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; }
}
//descargamos el engine
device->drop();
return 0;
}
Título: Re: ¿Triángulos por segundo normales?
Publicado por: Ruben en 15 de Enero de 2009, 12:47:28 PM
Hi,
CitarSí, podría ser éso. Pero no tengo ni idea de cómo comprobarlo. Con "DrawIndexedPrimitiveUP" te refieres a una función de DX, ¿no? El irrlicht no tiene nada que se llame así, creo.
busca en el codigo fuente de Irrlicht las funciones DrawIndexedPrimitiveUP y pon breakpoints. Compila en debug y mira a ver que es lo que pasa.  :)

Un saludo,
Ruben
Título: Re: ¿Triángulos por segundo normales?
Publicado por: mi-go en 15 de Enero de 2009, 06:55:55 PM
tewe, ¿pero no dijiste que querías usar Irrlicht porque ibas a hacer un juego gráficamente sencillo?
¿vas a cargar 100.000 cubos en pantalla?

Igual estás pensando en hacer un juego de romper miles de cubos, y entonces no me hagas caso, pero te lo digo por romperte un poco la idea de lo que estás haciendo; no vayas a estar perdiendo el tiempo en prubas.

Título: Re: ¿Triángulos por segundo normales?
Publicado por: tewe76 en 15 de Enero de 2009, 07:30:44 PM
Citarbusca en el codigo fuente de Irrlicht las funciones DrawIndexedPrimitiveUP y pon breakpoints. Compila en debug y mira a ver que es lo que pasa
Debo parecer tonto, pero sólo soy un novato en C++ (y en Visual C++) ::) La cuestión, que no consigo hacer éso que dices. Por un lado, cuando cargo el proyecto sólo "veo" el archivo cpp, no sé cómo llegar a los includes para ponerles los BP (dentro de VC++, me refiero). Y he probado a poner un BP en mi cpp e ir debugando paso por paso, pero, no entiendo por qué, pero la llamada "smgr->drawAll();", que es donde sospecho que hará las llamadas a DrawIndexedPrimitiveUP, no me deja entrar, pasa directamente a la siguiente línea ???

Citartewe, ¿pero no dijiste que querías usar Irrlicht porque ibas a hacer un juego gráficamente sencillo?
¿vas a cargar 100.000 cubos en pantalla?
:D
Sí, es que pensaba que era sencillo ::) .
Cuando digo sencillo me refiero a que no voy a usar normalmaps, ni shaders, ni cosas así. Pero sí, era mi idea, necesito cargar muchos objetos.

Explicaré un poco lo que quiero, seguramente me entenderéis mejor:
Mi idea es hacer un juego con lógica 2D pero con gráficos 3D. Mi primera idea era hacerlo todo 2D, pero pensé que los gráficos en 3D no deberían complicar la lógica, que seguiría siendo la misma, pero me permitirían hacer efectos de luces, zooms, "vuelos" por la escena, cinemáticas, gráficos más animados, etc.
Para entendernos, digamos que quiero coger un zelda clásico (2D), pero en vez de mostrarlo dibujando tiles 2D, hacerlo con "tiles 3D". Así, un tile de suelo no es una imagen, sino un cubo, una piedra no es una imagen, sino un mesh, los personajes no son sprites, sino md2, etc.
Y, claro, un simple mapa de 100x100 tiles, bastante pequeño, ya se te pone en 10.000 cubos, y éso sólo para dibujar el suelo Oo

¿Ahora me entendéis? :P ¿Alguna sugerencia?
Título: Re: ¿Triángulos por segundo normales?
Publicado por: Ruben en 15 de Enero de 2009, 08:57:09 PM
Cita de: tewe76 en 15 de Enero de 2009, 07:30:44 PM
Citarbusca en el codigo fuente de Irrlicht las funciones DrawIndexedPrimitiveUP y pon breakpoints. Compila en debug y mira a ver que es lo que pasa
Debo parecer tonto, pero sólo soy un novato en C++ (y en Visual C++) ::) La cuestión, que no consigo hacer éso que dices. Por un lado, cuando cargo el proyecto sólo "veo" el archivo cpp, no sé cómo llegar a los includes para ponerles los BP (dentro de VC++, me refiero). Y he probado a poner un BP en mi cpp e ir debugando paso por paso, pero, no entiendo por qué, pero la llamada "smgr->drawAll();", que es donde sospecho que hará las llamadas a DrawIndexedPrimitiveUP, no me deja entrar, pasa directamente a la siguiente línea ???
No joer, ¿porque vas a parecer tonto? Si no lo sabes, no eres tonto es que no lo sabes. Parece obvio pero hay un monton de gente que lo piensa. Me cabrea un huevo que se confunda desconocimiento con inteligencia!  :grrr: :grrr: :grrr: si no lo has hecho en tu vida, porque coj**** tienes que parecer tonto?  >.< >.<

Aclarado que no pareces tonto..... se me ocurre que te este pasando dos cosas:
a) Tienes incluido el proyecto del irrlicht en la solucion y le estes dando al F10 y para entrar en las funciones en visual se usa la tecla F11.
b) No tienes el proyecto del irrlicht incluido en tu solucion. Para debugear una libreria que usas (supongo que tienes el codigo fuente como es el caso del irrlicht), lo mas sencillo es incluirla en tu solucion, hacer que el proyecto que la use depende de ella y poco mas. Una vez que ejecutes en modo debug (F5), te aconsejo que hayas compilado en Debug aunque tambien podrias hacerlo en Release, puedes meterte en las funciones que usen irrlicht. Yo te aconsejaria que intentases hacer esta solucion, asi aprendes como manejarte con varios proyectos en una misma solucion, con dependencias entre ellos (que no es trivial).

Con cualquier duda, a postear! :D

Un saludo,
Ruben
Título: Re: ¿Triángulos por segundo normales?
Publicado por: Zaelsius en 16 de Enero de 2009, 01:50:23 AM
La última versión de Irrlicht permite el uso de VBOs:

CitarHardware accelerated Vertex and Index Buffer support finally integrated into Irrlicht. Thanks to a resource handling idea by Klasker and the almost immediate implementation by Luke, Irrlicht now supports VBOs under OpenGL and D3D.
   Hardware buffers make rendering the same vertices much faster. To use this feature with a mesh, simply set a usage type via MeshBuffer->setHardwareMappingHint(scene::EHM_STATIC). The driver will upload the vertices and indices on the next draw and reuse this information without the need to upload it each frame.
   Vertex and Index buffers can also be updated separately, which is e.g. useful for the terrain node's LOD.

De esa manera Irrlicht dejaría de usar DrawIndexedPrimitiveUP (D3D) internamente para mandar los triángulos a la tarjeta.

@Tewe: para poder depurar una librería en C++, la librería debe estar compilada en "modo debug", de otra manera no es depurar código dentro de ella. Aunque con los VBO probablemente ya ganes velocidad, si aun así quieres depurar código de Irrlicht lo más sencillo en tu caso sería bajarte el código fuente del motor y:

1. Compilar la solución de VS que viene con él con la configuración "debug".
2. Enlazar con el .lib (o es una dll?) generado desde la configuración "debug" de la solución de tu juego y listo.

Hace bastante tiempo que no trasteo con VS pero más o menos sería eso. También podrías meter tanto tu juego como Irrlicht dentro de la misma solución, como apunta Rubén.
Título: Re: ¿Triángulos por segundo normales?
Publicado por: tewe76 en 17 de Enero de 2009, 06:20:22 PM
CitarNo joer, ¿porque vas a parecer tonto? Si no lo sabes, no eres tonto es que no lo sabes.
Tranquilo, que lo decía de cachondeo :) . Sólo me considero tonto cuando intento atravesar una puerta de cristal o situaciones semejantes :P .

Citarb) No tienes el proyecto del irrlicht incluido en tu solucion.
No, no lo tengo (creo ::)). Lo he intentado, pero no me aclaro. ¿Podrías explicarme qué hay que hacer?

CitarLa última versión de Irrlicht permite el uso de VBOs:
Pues sí, éso parecía una buena solución. Pero lo he puesto siguiendo cosas que he encontrado en los foros y, o no lo hago bien, o no tiene utilidad en mi caso, porque no me da ningún error pero los FPS no cambian ??? .
En cualquier caso, tengo una duda: ¿los VBO los soportan todas las tarjetas gráficas o sólo las modernas?