Oui nan, l’objet triangle n’est pas un truc constitué de vertexes mêmes (ca je m’en doutes bien que c’est pas efficace). En fait, Triangle et Diamond sont deux classes qui sont des containeurs a variables (index du vertex, positions, etc…). Pour l’affichage j’utilise un vertexbuffer + indexbuffer; tu verras avec les résultats du profiler que le problème ne vient pas du rendering mais bien des split et merge.
Voici les infos retourné par le profiler:
Update.Noise average execution time: 3,07714903499825E-05, called 4502 times. Total time: 0,138533249555621
Update.Split average execution time: 0,00985244757169758, called 934 times. Total time: 9,20218603196554
Update.Split.One average execution time: 1,00290221016207E-05, called 2106 times. Total time: 0,0211211205460131
Update.Split.Two average execution time: 0,000754144801088261, called 2106 times. Total time: 1,58822895109188
Update.Split.Three average execution time: 0,00109452492804171, called 2106 times. Total time: 2,30506949845585
Update.Split.Four average execution time: 0,00102781994095665, called 2106 times. Total time: 2,16458879565471
Update.Merge average execution time: 0,00546861818517465, called 934 times. Total time: 5,10768938495312
Render average execution time: 0,000557831714680863, called 934 times. Total time: 0,521014821511926
Quelques explications s’imposent:
Update.noise est la fonction fractale qui indique la hauteur de la montagne (j’utilise un perlin modifié pour mes tests). 0.1 secondes pour 5000 appels, ca va.
Update.split est la fonction qui coupe un triangle en 2, régénère les voisins, etc… 10 secondes pour 1000 appels, c’est la que ca fait mal. Très mal même. J’ai découpé la fonction en plusieurs sous profils, visiblement ca merde à partir du profil 2 à 4. Voir plus bas le code.
Update.merge est aussi une fonction bouffe temps, mais moins que celle de split.
Comme tu peux le voir, le rendering (régénération du VB/IB en fonction des triangles) est très rapide, le problème ne vient pas d’une mauvaise utilisation du GPU.
Le bout de code incriminé:
[code]Profiler.StartProfiling(“Update.Split.Two”);
OppositeVertex = TriangleVertex;
// Now create two new triangles for the split
Triangle[] NewTriangle = new Triangle[2];
NewTriangle[0] = new Triangle();
NewTriangle[1] = new Triangle();
// Split the first one from Triangle
Triangle.SetPriorityWait(0);
NewTriangle[0].Flags = Triangle.Flags;
Triangles.AddAfter(Triangles.Find(Triangle), NewTriangle[0]);
NewTriangle[0].SetVertices(Triangle.VertexIndex[2], nTriangleVertex, Triangle.VertexIndex[1]);
Triangle.SetVertices(Triangle.VertexIndex[1], nTriangleVertex, Triangle.VertexIndex[0]);
NewTriangle[0].SetNeighbors(Opposite, Triangle, Triangle.Neighbors[1]);
Triangle.Neighbors[1].ReplaceNeighbor(Triangle, NewTriangle[0]);
Triangle.SetNeighbors(NewTriangle[0], NewTriangle[1], Triangle.Neighbors[0]);
if(NewTriangle[0].Neighbors[2].Neighbors[2] == NewTriangle[0])
NewTriangle[0].CopyPriorityInfo(NewTriangle[0].Neighbors[2]);
else
UpdateTriangleOffset(NewTriangle[0]);
if(Triangle.Neighbors[2].Neighbors[2] == Triangle)
Triangle.CopyPriorityInfo(Triangle.Neighbors[2]);
else
UpdateTriangleOffset(Triangle);
Profiler.EndProfiling(“Update.Split.Two”);
Profiler.StartProfiling(“Update.Split.Three”);
// Split the second one from Opposite
Opposite.SetPriorityWait(0);
NewTriangle[1].Flags = Opposite.Flags;
Triangles.AddAfter(Triangles.Find(Opposite), NewTriangle[1]);
NewTriangle[1].SetVertices(Opposite.VertexIndex[2], nOppositeVertex, Opposite.VertexIndex[1]);
Opposite.SetVertices(Opposite.VertexIndex[1], nOppositeVertex, Opposite.VertexIndex[0]);
NewTriangle[1].SetNeighbors(Triangle, Opposite, Opposite.Neighbors[1]);
Opposite.Neighbors[1].ReplaceNeighbor(Opposite, NewTriangle[1]);
Opposite.SetNeighbors(NewTriangle[1], NewTriangle[0], Opposite.Neighbors[0]);
if(NewTriangle[1].Neighbors[2].Neighbors[2] == NewTriangle[1])
NewTriangle[1].CopyPriorityInfo(NewTriangle[1].Neighbors[2]);
else
UpdateTriangleOffset(NewTriangle[1]);
if(Opposite.Neighbors[2].Neighbors[2] == Opposite)
Opposite.CopyPriorityInfo(Opposite.Neighbors[2]);
else
UpdateTriangleOffset(Opposite);
Profiler.EndProfiling(“Update.Split.Three”);
Profiler.StartProfiling(“Update.Split.Four”);
// Set up parent pointers
NewTriangle[0].Parent = Triangle;
NewTriangle[1].Parent = Opposite;
// If either of the original triangles was part of a diamond, it has been destroyed.
if(Triangle.Diamond != null)
{
Diamonds.Remove(Triangle.Diamond);
Triangle.Diamond = null;
}
if(Opposite.Diamond != null)
{
Diamonds.Remove(Opposite.Diamond);
Opposite.Diamond = null;
}
Diamonds.AddLast(new Diamond(Vertexes, Triangle, Opposite, NewTriangle[0], NewTriangle[1]));
LevelOfDetailsHasChanged = true;
Profiler.EndProfiling(“Update.Split.Four”);[/code]
De prime abord, je vois le new qui pourrait causer le problème dans la partie Update.Split.Two? Tout le reste n’est qu’accès et assignation de variables.
Je suis en train de me demander si mon problème ne viendrait pas du déréférencement des Diamond (objet composé de 4 triangles) à la fin de la partie 4?
J’avais oublié de préciser: j’avais testé sans pure getter/setter, aucune augmentation de performance à signaler… la récursivité, je suis obligé pour le moment, je crois que ca me ferait trop de modifications au code pour le faire fonctionner sans (sans compter le fait que ca risque de ne pas marcher :P). Je n’ai pas de fonctions virtuelles (abstraction ou autres conneries non plus) dans ce bout de code là.