This article has been updated with new demos and new GI technique. Read the complete article here: OpenGL Geometry Instancing: GeForce GTX 480 vs Radeon HD 5870.
Voici une petite démo qui utilise les techniques d’instancing (instancing simple, pseudo-instancing et geometry instancing(ou GI)) pour effectuer le rendu d’un anneau composé de 10000 petites sphères.
La démo est livrée en 5 versions:
- chaque sphère est composée de 1800 triangles (18 millions de triangles pour l’anneau entier)
- chaque sphère est composée de 800 triangles (8 millions de triangles pour l’anneau entier)
- chaque sphère est composée de 200 triangles (2 millions de triangles pour l’anneau entier)
- chaque sphère est composée de 72 triangles (720000 triangles pour l’anneau entier)
- chaque sphère est composée de 18 triangles (180000 triangles pour l’anneau entier)
J’ai ajouté au dernier moment un extra: une version avec 20000 instances de 5000 triangles chacune soit 100 millions de polygones (fichier Demo_Instancing_100MTriangles_20kInstances.exe).



DOWNLOAD
Il y a plusieurs techniques d’instancing qui sont utilisées et chaque technique est accessible avec une des touches F1 à F6.
- F1: instancing simple avec camera frustum culling: il y a une seule source de géométrie (un mesh) et elle est rendu pour chaque instance. Le calcul de la matrice de transformation est fait sur le CPU ainsi que le test de clipping avec la camera. Le rendu OpenGL utilise la fonction glDrawElements().
- F2: instancing simple SANS camera frustum culling: il y a une seule source de géométrie (un mesh) et elle est rendu pour chaque instance. Le calcul de la matrice de transformation est fait sur le CPU mais il n’y a plus de test de clipping avec la camera. Le rendu OpenGL utilise la fonction glDrawElements().
- F3: pseudo-instancing lent: il y a une seule source de géométrie (un mesh) et elle est rendu pour chaque instance. Le calcul de la matrice de transformation est maintenant effectué sur le GPU. Le passage des paramètres pour chaque instance se fait avec des variables uniformes. Il n’y a pas de test de clipping avec la camera. Le rendu OpenGL utilise la fonction glDrawElements().
- F4: pseudo-instancing rapide: il y a une seule source de géométrie (un mesh) et elle est rendu pour chaque instance. Le calcul de la matrice de transformation est maintenant effectué sur le GPU. Le passage des paramètres pour chaque instance se fait avec des attributs de vertex persistants (comme les coordonnées de textures ou la couleur). C’est cette technique qui
a été mise en avant par NVIDIA avec son whitepaper: GLSL Pseudo-Instancing. Il n’y a pas de test de clipping avec la camera. Le rendu OpenGL utilise la fonction glDrawElements(). - F5: Geometry Instancing: c’est le vrai instancing hardware. Il y a une seule source de géométrie (un mesh) et le rendu se fait par lots (ou batchs) de 400 instances par draw call. Le rendu complet de l’anneau ne nécessite que 25 draw-calls au lieu de 10000. Le calcul de la matrice de transformation est effectué sur le GPU. Le passage des paramètres pour chaque batch se fait avec des tableaux de variables uniformes. Il n’y a pas de test de clipping avec la camera. Le rendu OpenGL utilise la fonction glDrawElementsInstancedEXT(). Actuellement, seules les cartes NVIDIA GeForce 8 (et sup.) supportent cette fonction.
- F6: Geometry Instancing avec attributs de vertex persistants: c’est le geometry instancing hardware couplé avec le passage des paramètres par les attributs de vertex persistants. Mais le nombre d’attributs de vertex persistants est très limité. Au maximum j’ai reussi à rendre 4 instances par draw-call. Mais étrangement, 2 instances par draw-call donne de meilleurs résultats. Dans ce cas, le rendu complet de l’anneau nécessite que 5000 draw-calls au lieu des 10000. Le calcul de la matrice de transformation est effectué sur le GPU. Il n’y a pas de test de clipping avec la camera. Le rendu OpenGL utilise la fonction glDrawElementsInstancedEXT(). Actuellement, seules les cartes NVIDIA GeForce 8 (et sup.) supportent cette fonction.
18 millions triangles – 1800 tri/instance
NVIDIA GeForce 8800 GTX – Forceware 169.38 XP32
- F1: 223MTris/sec – 13FPS
- F2: 223MTris/sec – 13FPS
- F3: 223MTris/sec – 13FPS
- F4: 223MTris/sec – 13FPS
- F5: 223MTris/sec – 13FPS
- F6: 171MTris/sec – 10FPS
ATI Radeon HD 3870 – Catalyst 8.2 XP32
- F1: 429MTris/sec – 25FPS
- F2: 463MTris/sec – 27FPS
- F3: 446MTris/sec – 26FPS
- F4: 274MTris/sec – 16FPS
- F5: mode not available
- F6: mode not available
8 millions de triangles – 800 tri/instance
NVIDIA GeForce 8800 GTX – Forceware 169.38 XP32
- F1: 190MTri/sec – 25FPS
- F2: 190MTri/sec – 25FPS
- F3: 205MTri/sec – 27FPS
- F4: 213MTri/sec – 28FPS
- F5: 205MTri/sec – 27FPS
- F6: 152MTri/sec – 20FPS
ATI Radeon HD 3870 – Catalyst 8.2 XP32
- F1: 251MTris/sec – 33FPS
- F2: 236MTris/sec – 31FPS
- F3: 297MTris/sec – 39FPS
- F4: 251MTris/sec – 33FPS
- F5: mode not available
- F6: mode not available
2 millions de triangles – 200 tri/instance
NVIDIA GeForce 8800 GTX – Forceware 169.38 XP32
- F1: 47MTri/sec – 25FPS
- F2: 47MTri/sec – 25FPS
- F3: 57MTri/sec – 30FPS
- F4: 131MTri/sec – 69FPS
- F5: 167MTri/sec – 88FPS
- F6: 148MTri/sec – 78FPS
ATI Radeon HD 3870 – Catalyst 8.2 XP32
- F1: 47MTris/sec – 25FPS
- F2: 59MTris/sec – 31FPS
- F3: 74MTris/sec – 39FPS
- F4: 112MTris/sec – 59FPS
- F5: mode not available
- F6: mode not available
720,000 triangles – 72 tri/instance
NVIDIA GeForce 8800 GTX – Forceware 169.38 XP32
- F1: 17MTri/sec – 25FPS
- F2: 17MTri/sec – 25FPS
- F3: 20MTri/sec – 30FPS
- F4: 47MTri/sec – 69FPS
- F5: 60MTri/sec – 88FPS
- F6: 53MTri/sec – 78FPS
ATI Radeon HD 3870 – Catalyst 8.2 XP32
- F1: 17MTris/sec – 25FPS
- F2: 21MTris/sec – 31FPS
- F3: 26MTris/sec – 39FPS
- F4: 40MTris/sec – 59FPS
- F5: mode not available
- F6: mode not available
180000 triangles – 18 tri/instance
NVIDIA GeForce 8800 GTX – Forceware 169.38 XP32
- F1: 4MTri/sec – 25FPS
- F2: 4MTri/sec – 25FPS
- F3: 5MTri/sec – 30FPS
- F4: 11MTri/sec – 69FPS
- F5: 15MTri/sec – 89FPS
- F6: 13MTri/sec – 79FPS
ATI Radeon HD 3870 – Catalyst 8.2 XP32
- F1: 4MTris/sec – 25FPS
- F2: 5MTris/sec – 31FPS
- F3: 6MTris/sec – 39FPS
- F4: 10MTris/sec – 59FPS
- F5: mode not available
- F6: mode not available
Analyse rapide des resultats:
- nous comprenons maintenant pourquoi NVIDIA a appellé “Pseudo-Instancing” la technique utilisant les attributs persistants de vertex (key F4). La fonction glDrawElements() d’OpenGL est extremement rapide et optimisée et les attrubuts persistants de vertex nécessitent moins de traitement que les variables uniformes pour être passés au vertex shader. Les deux couplés ensemble donnent ce boost de performance.
- le bénéfice du vrai hardware geometry instancing est principalement visible losqu’il y a peu de triangles par instance.
- lorsqu’il y a beacoup de triangles par instance (1800), l’impémentation matérielle de glDrawElements() semble être plus efficace (près de deux fois!) sur le GPU RV670 que sur le G80.
Conclusion
Au vu des résultats, le hardware geometry instancing n’est pas la kill-feature que j’attendais. Je trouve cela très curieux car la différence entre 10000 render-calls avec glDrawElements et 25 render-calls avec glDrawElementsInstancedEXT n’est pas très importante. On dirait que la gestion de l’instancing (variable gl_InstanceID dans le vertex shader) fait perdre beaucoup de temps. Je trouve aussi dommage qu’ATI n’ait pas encore pris le temps d’implémenter le geomtry instancing dans les pilotes Catalyst. Je serais très curieux de tester le GI hardware avec un RV670.
Pingback: Game Rendering » Instancing
I have a GTX 280 and the F5,F6 options throw up the dialog about needing Gforce 8+ hardware.
just FYI..
yes, the way the capability is checked is based on old NVIDIA drivers. Start GPU Caps Viewer GI demo to see the difference
Thanks for the information! The tests you have performed give important insight about the relationship between the batch sizes and the instancing techniques.
the download link of the DemoPack seems broken… could you fix/reupload it? thnx
Hi.
You wrote:
“I find that very weird since the différence between 10000 render-calls with glDrawElements and 25 render-calls with glDrawElementsInstancedEXT is not verx important.”
But have you also considered the CPU-Overhead. The impact might not be very big due to GPU work, but it should definitely on CPU side! Have you checked this too?
I mean in terms of CPU/GPU boundness.
Anyway, good work, this is quite interesting.
Btw, I got similar results with texture buffer objects.
Hi
The download file isn’t available anymore.
Link to demo is not working
Hi,
The download files are not available….
Pingback: [Test] OpenGL Geometry Instancing: GeForce GTX 480 vs Radeon HD 5870 - 3D Tech News, Pixel Hacking, Data Visualization and 3D Programming - Geeks3D.com