Démonstration des compteurs atomiques en OpenGL 4.2

Rendu de l'ordre des fragments

| JeGX | Guillaume Belz | Jérôme Marsaguet |

Traducteur

Alexandre Laurent

Les compteurs atomiques sont une fonctionnalité disponible à partir d'OpenGL 4.2. Cet article explique comment les utiliser.

Commentez

- Titre : Démonstration des compteurs atomiques en OpenGL 4.2

- Auteurs : JeGX, Guillaume Belz, Jérôme Marsaguet

- Traducteur : Alexandre Laurent

- Parution : 16 février 2013

- Mise à jour : 16 février 2013

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2013 Geeks3D. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Aperçu des compteurs atomiques

- II. Compteurs atomiques : la démonstration

- III. Compteurs atomiques : détails d'OpenGL

- IV. Remerciements

I - Aperçu des compteurs atomiques

Il y a quelque temps, j'ai trouvé une vidéo présentant l'ordre de rendu des fragments :

Animation en format "youtube" non supportée.
Contenu uniquement consultable en ligne à cette adresse :
https://www.youtube.com/watch?v=WnUS8kzA3dI

Sympa ! Mais comment cela fonctionne-t-il ? La réponse est dans l'utilisation des compteurs atomiques (atomic counters).

Les compteurs atomiques sont une nouvelle fonctionnalité d'OpenGL 4.2. Ils sont disponibles à n'importe quelle étape : vertex shader, pixel shader, geometry shader, tessellation control shader et tessellation evaluation shader. La spécification complète est disponible sur OpenGL.org.

En un mot, un compteur atomique est un tampon mémoire (en fait, un buffer object qui contient un ou plusieurs unsigned int) qui peut être incrémenté (avec la fonction du GLSL : atomicCounterIncrement()) ou décrémenté (avec la fonction GLSL atomicCounterDecrement()) par un shader.

Information sur les compteurs atomiques dans

Une application simple mais néanmoins intéressante est la visualisation de l'ordre de rendu des fragments. Dans le pixel shader, un compteur atomique est incrémenté à chaque fois que le shader est appelé. Ensuite, si vous convertissez la valeur de ce counter en une couleur, vous pouvez facilement visualiser quel fragment est affiché. Super !

Une fois que le buffer object du compteur atomique est initialisé et lié (voir les morceaux de code OpenGL à la fin de cet article), nous pouvons écrire dans le compteur atomique avec la fonction GLSL atomicCounterIncrement().

Le code suivant permet de voir où les dix premiers fragments sont affichés :

#version 420 compatibility
layout(binding=0, offset=0) uniform atomic_uint ac;
void main(void)
{
uint counter = atomicCounterIncrement(ac);
if (counter < 10)
gl_FragColor = vec4(1, 0, 0, 1);
else
gl_FragColor = vec4(0, 0, 0, 1);
}

L'image suivante montre ces dix premiers fragments :

Les dix premiers fragments

Zoom sur les dix premiers fragments

Maintenant, observons l'ordre de rendu des pixels d'un quadrilatère (constitué de deux triangles) avec le shader suivant :

#version 420 compatibility
layout(binding = 0, offset = 0) uniform atomic_uint ac;
void main(void)
{
uint counter = atomicCounterIncrement(ac);
float r = (counter/255) / 255.f;
gl_FragColor = vec4(r, 0, 0, 1);
}

Sur l'écran, la dimension du quadrilatère est 256x256 (65536 pixels à afficher). Les premiers fragments sont affichés en noir et les derniers en rouge. Voici l'ordre de rendu sur une Geforce GTX 460 :

Compteurs atomiques : ordre de rendu des pixels sur Geforce GTX 460

Et voici l'ordre de rendu sur une Radeon HD 6970 :

Compteurs atomiques : ordre de rendu des pixels sur Radeon HD 6970

Ou si vous préférez sur une Radeon HD 7770 :

Compteurs atomiques : ordre de rendu des pixels sur Radeon HD 7770

Comme vous pouvez le voir, la façon dont sont affichés les pixels (pattern du rasterizer) diffère. La GeForce dessine plusieurs petites zones et remplit les deux triangles de haut en bas alors que la GPU Radeon dessine des zones plus grandes et remplit le premier triangle de haut en bas et le second dans le sens inverse. La GPU de la Radeon HD 6000 semble dessiner les fragments par groupe de 32x32 pixels (taille des carrés que vous pouvez voir sur la capture d'écran). Le GPU de la Radeon HD 7000 ressemble plus à un rendu de GeForce GTX 400.

II - Compteurs atomiques : la démonstration

La démonstration pour GeeXLab est disponible dans le dossier GLSL_Atomic_Counter/ du pack d'exemples. La démonstration nécessite la version 0.3.3 ou supérieure de GeeXLab.

Pour faire fonctionner la démonstration, déposez le fichier de démo (DEMO_Atomic_Counter.xml) dans GeeXLab. C'est tout.

III - Compteurs atomiques : détails d'OpenGL

Pour les développeurs OpenGL, voici quelques morceaux de code montrant comment initialiser et utiliser les compteurs atomiques. En premier, le code pour initialiser le buffer object pour les compteurs atomiques :

GLuint ac_buffer = 0;
glGenBuffers(1, &ac_buffer);
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, ac_buffer);
glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);

Maintenant, l'activation du buffer object des compteurs atomiques :

glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, ac_buffer);

Et pour finir, la réinitialisation la valeur du compteur atomique :

glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, ac_buffer);
GLuint* ptr = (GLuint*)glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint),
GL_MAP_WRITE_BIT |
GL_MAP_INVALIDATE_BUFFER_BIT |
GL_MAP_UNSYNCHRONIZED_BIT);
ptr[0] = value;
glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);

IV - Remerciements

Cet article est une traduction autorisée de l'article paru sur Geeks3D.com.

Je tiens à remercier Winjerome et gbdivers pour leur relecture lors de la traduction de cet article, ainsi que ClaudeLELOUP pour sa relecture orthographique.