IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Apprendre OpenGL moderne

Septième partie : mise en pratique


précédentsommairesuivant

I. Débogage

La programmation graphique est très amusante, mais peut aussi être source de frustration quand quelque chose ne donne pas le résultat escompté, voire pas de résultat du tout ! Afficher tout ce que l’on veut implique de manipuler des pixels et il peut s’avérer difficile de trouver la cause d’une erreur lorsque tout ne se passe pas comme prévu. Déboguer ce genre d’erreurs visuelles est différent de ce que vous avez l’habitude de faire en cherchant les erreurs CPU. On ne dispose pas de console pour afficher du texte, pas de points d’arrêt pour examiner le code GLSL et pas d’outil pour examiner l’exécution sur le GPU.

Dans ce tutoriel, nous verrons plusieurs techniques et astuces pour déboguer un programme OpenGL. Ce n’est pas si difficile et acquérir ces techniques sera payant à long terme.

I-A. glGetError()

Dès que vous utilisez OpenGL incorrectement (comme configurer un tampon sans l’avoir lié), ce sera noté et cela positionnera un ou plusieurs indicateurs d’erreurs en arrière-plan. Vous pourrez récupérer ces informations en utilisant la fonction glGetError() qui teste ces indicateurs et retourne un code d’erreur si OpenGL a été malmené.

 
Sélectionnez
GLenum glGetError();

Lors de l’appel, cette fonction retourne soit un code d’erreur ou pas d’erreur du tout. Ces codes d’erreur sont listés ci-dessous :

Flag

Code

Description

GL_NO_ERROR

0

Pas d’erreur depuis le dernier appel à glGetError().

GL_INVALID_ENUM

1280

Positionné si une énumération passée en paramètre est invalide.

GL_INVALID_VALUE

1281

Positionné si une valeur passée en paramètre est invalide.

GL_INVALID_OPERATION

1282

Positionné si l’état d’une commande est illégal compte tenu des paramètres passés.

GL_STACK_OVERFLOW

1283

Positionné si placer un objet sur la pile provoque un dépassement.

GL_STACK_UNDERFLOW

1284

Positionné si on essaie de retirer un objet d’une pile alors qu’elle est vide.

GL_OUT_OF_MEMORY

1285

Positionné si une allocation mémoire est impossible.

GL_INVALID_FRAMEBUFFER_OPERATION

1286

Positionné en cas de lecture ou d’écriture dans un tampon de rendu incomplet.

Dans la documentation des fonctions OpenGL, vous pourrez toujours trouver les codes d’erreur qu’une fonction génère au moment où l’erreur se produit. Par exemple, si vous regardez la documentation de la fonction glBindTexture(), vous trouverez tous les codes d’erreur dans la section Errors.

Dès qu’un indicateur d’erreur est positionné, plus aucune erreur ne sera enregistrée. De plus, l’appel de glGetError() efface tous les indicateurs d’erreurs (ou seulement un dans un système distribué, voir la note ci-dessous). Cela implique que si vous appelez glGetError() à la fin d’un rendu et que vous trouvez une erreur, vous ne pouvez pas en conclure que c’était la seule erreur et de plus, la source de l’erreur peut se trouver n’importe où dans la boucle de rendu.

Noter que si OpenGL s’exécute de façon distribuée, comme cela est souvent le cas sur les systèmes X11, d’autres codes d’erreur utilisateur peuvent encore être générés tant qu’ils ont différents indicateurs. L’appel à glGetError() n’efface alors que l’un des indicateurs et non pas tous. De ce fait, il est recommandé d’appeler glGetError() à l’intérieur d’une boucle.

 
Sélectionnez
glBindTexture(GL_TEXTURE_2D, tex);
std::cout << glGetError() << std::endl; // retourne 0 (pas d’erreur)

glTexImage2D(GL_TEXTURE_3D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
std::cout << glGetError() << std::endl; // retourne 1280 (énumération invalide)
Textures(-5, textures);
std::cout << glGetError() << std::endl; // retourne 1281 (valeur incorrecte)
std::cout << glGetError() << std::endl; // retourne 0 (pas d’erreur)

L’intérêt majeur de glGetError() est de permettre la localisation précise des erreurs et aussi de valider l’utilisation correcte d’OpenGL. Supposons que vous obteniez un écran noir sans savoir d’où vient le problème : le tampon d’affichage est-il bien établi ? Aurais-je oublié de lier une texture ? En appelant glGetError() vous pouvez trouver rapidement le premier endroit où une erreur apparaît et donc ce qui pose un problème.

Par défaut, glGetError() n’affiche que les codes d’erreur, ce qui n’est pas facile à comprendre, à moins d’avoir mémorisé ces codes. Il est souvent plus pratique d’utiliser une petite fonction utilitaire pour afficher un message d’erreur à l’endroit où la vérification est effectuée :

 
Sélectionnez
GLenum glCheckError_(const char *file, int line)
{
    GLenum errorCode;
    while ((errorCode = glGetError()) != GL_NO_ERROR)
    {
        std::string error;
        switch (errorCode)
        {
            case GL_INVALID_ENUM: error = "INVALID_ENUM"; break;
            case GL_INVALID_VALUE: error = "INVALID_VALUE"; break;
            case GL_INVALID_OPERATION: error = "INVALID_OPERATION"; break;
            case GL_STACK_OVERFLOW: error = "STACK_OVERFLOW"; break;
            case GL_STACK_UNDERFLOW:  error = "STACK_UNDERFLOW"; break;
            case GL_OUT_OF_MEMORY: error = "OUT_OF_MEMORY"; break;
            case GL_INVALID_FRAMEBUFFER_OPERATION: error = "INVALID_FRAMEBUFFER_OPERATION"; break;
        }
        std::cout << error << " | " << file << " (" << line << ")" << std::endl;
    }
    return errorCode;
}
#define glCheckError() glCheckError_(__FILE__, __LINE__)

Si vous n’êtes pas familier des directives du préprocesseur, __FILE__ et __LINE__ sont remplacés lors de la compilation par le nom du fichier et la ligne en cours. Si l’on utilise un certain nombre de ces appels glCheckError(), mieux vaut savoir précisément lequel affiche l’erreur.

 
Sélectionnez
glBindBuffer(GL_VERTEX_ARRAY, vbo);
glCheckError();

Cela produira l’affichage suivant :

Sortie de glGetError() lors d'un débogage OpenGL.

Il nous paraît important de signaler que GLEW renferme un bogue ancien : lors de l’appel glewInit(), la fonction glGetError() positionne l’indicateur d’erreur GL_INVALID_ENUM et retourne donc un code d’erreur qui peut vous tromper. Pour éviter cela, on peut simplement appeler glGetError() pour effacer l’indicateur d’erreur :

 
Sélectionnez
glewInit();
glGetError();

glGetError() ne donne pas beaucoup d’informations sur la cause de l’erreur, mais cela vous aidera à localiser des fautes de frappe et à trouver où votre code est erroné : c’est un outil de débogage assez simple, mais efficace.

I-B. Extension debug output

Un outil moins courant, mais plus pratique que glGetError() est l’extension d’OpenGL nommée debug output (sortie de débogage) qui fait partie d’OpenGL depuis la version 4.3. Avec cette extension, OpenGL renverra lui-même une erreur et un message d’avertissement à l’utilisateur, bien plus détaillé que glCheckError(). Non seulement cela donne plus d’informations, mais vous pouvez localiser les erreurs plus précisément en utilisant le support d’un débogueur.

La sortie de débogage fait partie du noyau d’OpenGL depuis la version 4.3, ce qui rend cette fonctionnalité disponible sur toute machine disposant de la version 4.3 ou ultérieure. Si ce n’est pas le cas, cette fonctionnalité peut être obtenue avec l’extension ARB_debug_output ou bien AMD_debug_output. Cela semble ne pas fonctionner sur OS X (je ne l’ai pas testé moi-même, dîtes-moi si je me trompe).

Pour utiliser la sortie de débogage, il faut obtenir un contexte spécifique auprès d’OpenGL lors du processus d’initialisation. Ce processus dépend de votre système de fenêtrage ; ici, nous utilisons GLFW, mais vous pouvez trouver l’information nécessaire pour d’autres systèmes dans les ressources additionnelles à la fin de ce chapitre.

I-B-1. Sortie de débogage avec GLFW

Obtenir un contexte pour la sortie de débogage est très facile avec GLFW, la seule chose à faire est de le demander, avant de faire appel à glfwCreateWindow() :

 
Sélectionnez
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);

Après avoir initialisé GLFW, on devrait disposer d’un contexte de débogage si l’on utilise OpenGL 4.3 ou plus, ou sinon, il faut espérer que le système peut fournir un contexte de débogage. Enfin, on peut obtenir un contexte de débogage avec les extensions d’OpenGL.

Utiliser OpenGL en mode debug peut ralentir significativement l’exécution, il faudra penser à le supprimer si vous travaillez l’optimisation ou la version finale de l’application.

Pour vérifier que le contexte de débogage a été initialisé avec succès, on peut interroger OpenGL :

 
Sélectionnez
GLint flags; glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
{
    // initialisation de la sortie de débogage
}

La sortie de débogage fonctionne de cette façon : on définit une fonction callback d’enregistrement d’erreur (comme les fonctions callback pour les entrées utilisateur) et nous traitons les données d’erreur dans la fonction callback comme bon nous semble. Dans notre cas, nous afficherons un message d’erreur sur la console. Ci-dessous un prototype de fonction callback qu’OpenGL attend pour la sortie de débogage :

 
Sélectionnez
void APIENTRY glDebugOutput(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, void *userParam);

Noter que dans certaines implémentations d’OpenGL, le dernier paramètre doit être de type const void* au lieu de void*.

Compte tenu du nombre important de données à traiter, on pourra créer un outil pratique d’affichage des erreurs comme ceci :

 
Sélectionnez
void APIENTRY glDebugOutput(GLenum source,
                            GLenum type,
                            GLuint id,
                            GLenum severity,
                            GLsizei length,
                            const GLchar *message,
                            void *userParam)
{
    // on ignore les codes ou avertissements non significatifs
    if(id == 131169 || id == 131185 || id == 131218 || id == 131204)
        return;
    std::cout << "---------------" << std::endl;
    std::cout << "Debug message (" << id << "): " <<  message << std::endl;
    switch (source)
    {
        case GL_DEBUG_SOURCE_API:
        std::cout << "Source: API"; break;
        case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
        std::cout << "Source: Window System"; break;
        case GL_DEBUG_SOURCE_SHADER_COMPILER:
        std::cout << "Source: Shader Compiler"; break;
        case GL_DEBUG_SOURCE_THIRD_PARTY:
        std::cout << "Source: Third Party"; break;
        case GL_DEBUG_SOURCE_APPLICATION:
        std::cout << "Source: Application"; break;
        case GL_DEBUG_SOURCE_OTHER:
        std::cout << "Source: Other"; break;
    }
    std::cout << std::endl;
    switch (type)
    {
        case GL_DEBUG_TYPE_ERROR:
        std::cout << "Type: Error"; break;
        case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
        std::cout << "Type: Deprecated Behaviour"; break;
        case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
        std::cout << "Type: Undefined Behaviour"; break;
        case GL_DEBUG_TYPE_PORTABILITY:
        std::cout << "Type: Portability"; break;
        case GL_DEBUG_TYPE_PERFORMANCE:
        std::cout << "Type: Performance"; break;
        case GL_DEBUG_TYPE_MARKER:
       std::cout << "Type: Marker"; break;
        case GL_DEBUG_TYPE_PUSH_GROUP:
        std::cout << "Type: Push Group"; break;
        case GL_DEBUG_TYPE_POP_GROUP:
        std::cout << "Type: Pop Group"; break;
        case GL_DEBUG_TYPE_OTHER:
        std::cout << "Type: Other"; break;
    }
    std::cout << std::endl;
    switch (severity)
    {
        case GL_DEBUG_SEVERITY_HIGH:
        std::cout << "Severity: high"; break;
        case GL_DEBUG_SEVERITY_MEDIUM:
        std::cout << "Severity: medium"; break;
        case GL_DEBUG_SEVERITY_LOW:
        std::cout << "Severity: low"; break;
        case GL_DEBUG_SEVERITY_NOTIFICATION:
        std::cout << "Severity: notification"; break;
    }
    std::cout << std::endl;
    std::cout << std::endl;
}

Dès lors que le pilote détectera une erreur OpenGL, la fonction callback sera appelée, et nous afficherons un message d’erreur intéressant. Noter que nous ignorons certains codes d’erreur qui ne sont pas d’un intérêt notable (comme 131185 avec les pilotes NVIDIA qui dit qu’un tampon a bien été créé).

Maintenant que nous avons notre fonction callback, il est temps d’initialiser la sortie de débogage :

 
Sélectionnez
if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
{
    glEnable(GL_DEBUG_OUTPUT);
    glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
    glDebugMessageCallback(glDebugOutput, nullptr);
    glDebugMessageControl(GL_DONT_CARE,
                          GL_DONT_CARE,
                          GL_DONT_CARE,
                          0, nullptr, GL_TRUE);
}

Nous demandons à OpenGL d’activer la sortie de débogage. L’appel glEnable(GL_DEBUG_OUTPUT) demande à OpenGL d’appeler directement la fonction callback lorsqu’une erreur se produit.

I-B-2. Filtrer la sortie de débogage

Avec glDebugMessageControl() vous pouvez filtrer le type d’erreur dont vous voulez être averti. Dans notre cas, nous avons décidé de n’appliquer aucun filtre sur la source, le type ou la gravité de l’erreur. Si nous voulions n’afficher que les messages provenant de l’API OpenGL, qui sont des erreurs, et qui sont graves, on aurait configuré les choses comme ceci :

 
Sélectionnez
glDebugMessageControl(GL_DEBUG_SOURCE_API,
                      GL_DEBUG_TYPE_ERROR,
                      GL_DEBUG_SEVERITY_HIGH,
                      0, nullptr, GL_TRUE);

En fonction de votre configuration et en supposant que vous avez un contexte qui supporte la sortie de débogage, chaque commande OpenGL incorrecte vous affichera un message utile et détaillé :

Sortie du contexte de débogage d'OpenGL.

I-B-3. Retrouver l’origine de l’erreur

Un autre avantage de la sortie de débogage est de pouvoir facilement connaître la ligne exacte où s’est produite l’erreur. En plaçant un point d’arrêt dans DebugOutput() sur un type d’erreur particulier (ou bien au début de la fonction si cela vous va bien), le débogueur interceptera l’erreur et vous pourrez remonter la pile des appels jusqu’à la fonction ayant produit l’erreur :

Définition d'un point d'arrêt et utilisation de la liste des appels avec OpenGL pour obtenir la ligne provoquant une erreur.

Il faut intervenir manuellement, mais si vous savez à peu près ce que vous cherchez, c’est extrêmement utile de déterminer rapidement quel appel a produit l’erreur.

I-B-4. Affichages personnalisés des erreurs

En plus de la lecture simple des messages, vous pouvez aussi placer les messages de votre choix dans le système de la sortie de débogage :

 
Sélectionnez
glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0,  GL_DEBUG_SEVERITY_MEDIUM, -1, "votre message d’erreur ici");

Cela est très utile si vous vous intégrez dans une autre application ou un autre code OpenGL qui utilise aussi un contexte supportant la sortie de débogage. D’autres développeurs peuvent ainsi rapidement signaler un bogue qui se produit dans votre propre code.

Pour résumer, la sortie de débogage (si vous pouvez l’utiliser) est extrêmement utile pour trouver rapidement les erreurs, cet outil mérite d’être installé, il vous fera gagner beaucoup de temps de développement. Vous trouverez une copie du code ici, configuré avec glGetError() et la sortie de débogage, voyez si vous pouvez retrouver toutes les erreurs.

I-C. Déboguer les sorties des shaders

Quant à GLSL, nous ne disposons malheureusement pas d’une fonction comme glGetError() ni de la possibilité de placer des points d’arrêt dans le code d’un shader. Si vous obtenez un écran tout noir ou un effet visuel complètement faux, il est assez difficile de savoir ce qui ne fonctionne pas dans un shader. Les erreurs de compilation sont bien signalées, mais trouver les erreurs de logique est une autre histoire.

Une astuce souvent utilisée pour déboguer un shader consiste à évaluer toutes les variables d’un programme shader en les envoyant directement en sortie du fragment shader. En substituant les variables directement aux couleurs produites par le fragment shader, on peut souvent obtenir des informations intéressantes en inspectant les résultats visuellement. Par exemple, supposons que l’on veuille vérifier les normales d’un modèle, on peut les passer (transformées ou non) du vertex shader au fragment shader et on les sortira comme suit :

 
Sélectionnez
#version 330 core
out vec4 FragColor;
in vec3 Normal;
[...]
void main()
{
    […]
    FragColor.rgb = Normal;
    FragColor.a = 1.0f;
}

En sortant une variable (qui n’est pas une couleur) comme une couleur, on peut visualiser si la variable semble correcte. Si par exemple le résultat est complètement noir, il est clair que les normales ne sont pas correctement passées aux shaders ; et si elles s’affichent, il est facile de vérifier si elles semblent correctes ou non :

L'image du modèle 3D avec les normales affichées avec la sortie du fragment shader pour déboguer l'application OpenGL.

On voit que les normales semblent correctes, les normales pointant vers la droite sont rouges, celles pointant vers l’avant sont bleues, et celles vers le haut sont vertes.

Cette approche peut être étendue à tout type de variable à tester. Si vous suspectez un problème dans un shader, essayez d’afficher certains résultats sous forme de couleur.

I-D. Compilateur GLSL de référence

Chaque pilote graphique a ses propres manies et bizarreries. Par exemple, les pilotes NVIDIA sont assez relax et négligents quant aux spécifications, tandis que les pilotes ATI/AMD sont plus rigoureux et tendent à renforcer la spécification d’OpenGL (ce qui me semble la bonne approche). Le problème, c’est qu’un shader peut fonctionner sur une machine et pas sur une autre, du fait de pilotes différents.

Avec quelques années d’expérience, vous pourrez peut-être apprendre les différences mineures entre les constructeurs de GPU, mais si vous voulez être sûr que votre code fonctionne sur toutes les machines, vous pouvez le tester en utilisant le compilateur GLSL de référence. Vous pouvez télécharger le binaire « GLSL lang validator » ici ou le code source complet ici.

Avec « GLSL lang validator », vous pouvez facilement vérifier le code de vos shaders en passant le code de votre shader comme premier argument. Sachez que « GLSL lang validator » détermine le type de shader au moyen d’une liste d’extensions fixes :

  • .vert : vertex shader.
  • .frag : fragment shader.
  • .geom : geometry shader.
  • .tesc : tessellation control shader.
  • .tese : tessellation evaluation shader.
  • .comp : compute shader.

Exécuter le compilateur de référence de GLSL est très simple :

 
Sélectionnez
glsllangvalidator shaderFile.vert

S’il n’y a pas d’erreur, il ne retourne rien. Si un vertex shader comporte une erreur, on obtiendra ce genre d’affichage :

Sortie du compilateur GLSL de référence (GLSL lang validator) en OpenGL.

Il ne vous donnera pas les différences subtiles entre les versions des compilateurs GLSL d’AMD, NVIDIA ou Intel, ni ne vous aidera à complètement déboguer vos shaders, mais au moins vous aidera à les comparer aux spécifications officielles de GLSL.

I-E. Affichage d’un tampon de rendu

Une autre astuce utile pour déboguer consiste à afficher le contenu d’un tampon de rendu (voir chapitre 26) dans une zone prédéfinie de votre application OpenGL. Vous allez très souvent utiliser ces tampons de rendu nommés « framebuffers », et comme l’essentiel de leur rôle se déroule en arrière-plan, il est quelquefois difficile de réaliser ce qu’il s’y passe. Afficher le contenu d’un tampon de rendu dans votre application est un moyen pratique de voir rapidement si tout se passe bien.

Notons que l’affichage du contenu d’un tampon de rendu comme expliqué ici ne fonctionnera que pour le rendu dans une texture, et non pas pour les objets de tampon de rendu.

En utilisant un simple shader qui affiche une texture, on peut facilement écrire une petite fonction utilitaire pour afficher n’importe quelle texture en haut à droite de l’écran :

 
Sélectionnez
// vertex shader
#version 330 core
layout (location = 0) in vec2 position;
layout (location = 1) in vec2 texCoords;
out vec2 TexCoords;
void main()
{
    gl_Position = vec4(position, 0.0f, 1.0f);
    TexCoords = texCoords;
}

// fragment shader
#version 330 core
out vec4 FragColor;
in  vec2 TexCoords;
uniform sampler2D fboAttachment;
void main()
{
    FragColor = texture(fboAttachment, TexCoords);
}

void DisplayFramebufferTexture(GLuint textureID)
{
    if(!notInitialized)
    {
        // initialise le shader et le VAO avec les coordonnées de sommets en espace de périphérique, en haut à droite de l’écran
        […]
    }
     glActiveTexture(GL_TEXTURE0);
     glUseProgram(shaderDisplayFBOOutput);
     glBindTexture(GL_TEXTURE_2D, textureID);
     glBindVertexArray(vaoDebugTexturedRect);
     glDrawArrays(GL_TRIANGLES, 0, 6);
     glBindVertexArray(0);
     glUseProgram(0);
}

int main()
{
    […]
    while (!glfwWindowShouldClose(window))
    {
        […]
        DisplayFramebufferTexture(fboAttachment0);
        glfwSwapBuffers(window);
    }
}

Ce code vous donnera une petite fenêtre sympa au coin de votre écran pour déboguer un tampon de rendu. Utile, par exemple, pour déterminer si les normales d’un rendu différé semblent correctes :

Affichage des FBO à des fins de débogage en OpenGL.

On peut bien sûr étendre ce genre de fonction pour supporter le rendu de plus d’une texture. C’est un moyen rapide, mais peu orthodoxe d’obtenir un retour de ce qui se passe dans vos tampons de rendu.

I-F. Logiciel externe de débogage

Quand tout ceci ne suffit pas, on peut encore utiliser un outil tiers pour aider au débogage. Ces applications externes s’insèrent souvent elles-mêmes dans les pilotes d’OpenGL et sont capables d’intercepter toutes sortes d’appels OpenGL pour vous donner un vaste tableau de données intéressantes concernant votre application. Ces outils peuvent vous aider dans de nombreux domaines comme : suivre l’utilisation des fonctions OpenGL, trouver des goulots d’étranglement, inspecter les tampons mémoire, afficher des textures et les objets attachés au tampon de rendu. Si vous travaillez sur des codes de grosses productions, ces outils procurent une aide inestimable pour votre processus de développement.

J’ai listé ci-dessous, certains parmi les plus connus de ces logiciels de débogage ; essayez-les et voyez ce qui vous convient le mieux.

I-F-1. RenderDoc

RenderDoc est un puissant outil autonome (entièrement open source). Pour lancer une capture, vous spécifiez l’exécutable que vous voulez capturer et un répertoire de travail. Votre application fonctionne alors comme d’habitude, et à chaque fois que vous souhaitez inspecter un rendu particulier, vous laissez RenderDoc capturer un ou plusieurs rendus dans l’état courant de l’exécutable. Dans les rendus capturés, vous pouvez voir l’état du pipeline, toutes les commandes OpenGL, les tampons et textures en cours d’utilisation.

Image de RenderDoc avec une application OpenGL.

I-F-2. CodeXL

CodeXL est un outil de débogage du GPU délivré comme autonome ou bien comme plugin de Visual Studio. CodeXL donne pas mal d’informations et permet de suivre efficacement les applications graphiques. CodeXL fonctionne avec les cartes NVIDIA et Intel, mais sans support pour déboguer OpenCL.

Image de CodeXL avec une application OpenGL.

Je n’ai pas beaucoup d’expérience sur CodeXL, car je trouve RenderDoc plus facile à utiliser, mais je le mentionne, car il semble être un outil solide et développé par l’un des plus grands fabricants de GPU.

I-F-3. NVIDIA Nsight

Nsight de NVIDIA est un outil de débogage GPU bien connu. Ce n’est pas un logiciel autonome, mais un plugin pour Visual Studio ou encore Eclipse. Le plugin Nsight est un outil incroyablement utile pour les développeurs graphiques, il présente de nombreuses statistiques sur l’utilisation du GPU et de l’état du GPU passe de rendu par passe de rendu.

Dès que vous lancez votre application depuis Visual Studio (ou Eclipse) en utilisant le débogage ou le profilage, Nsight s’exécutera dans l’application elle-même. Le grand intérêt de Nsight est d’afficher une interface utilisateur au premier plan, à partir de l’application, que l’on peut utiliser pour obtenir toutes sortes d’informations sur l’application, soit pendant l’exécution, soit pendant l’analyse des passes de rendu.

Image de NSight avec une application OpenGL.

Nsight est un outil très puissant qui, selon moi, est le plus performant, mais son inconvénient majeur est de ne fonctionner qu’avec les cartes NVIDIA. Si vous travaillez avec NVIDIA et (Visual Studio), cela vaut vraiment la peine de se doter de Nsight.

Je suis sûr que d’autres logiciels méritent d’être mentionnés (comme VOGL de Valve et APItrace), mais cette courte liste vous donne déjà beaucoup d’outils à essayer. Je ne suis pas un expert avec ces outils, dîtes-moi dans les commentaires si je me trompe quelque part et je corrigerai où ce sera nécessaire.

I-G. Ressources supplémentaires

  • Pourquoi votre code donne-t-il une fenêtre noire ? : liste des causes principales sur le fait que l’application n’affiche rien, par Reto Koradi.
  • Debug Output : un article approfondi sur la sortie de débogage avec des informations détaillées sur la mise en place d’un contexte de débogage des systèmes multifenêtrés, par Vallentin Source.

I-H. Remerciements

Ce tutoriel est une traduction réalisée par Jean-Michel Fray dont l’original a été écrit par Joey de Vries et qui est disponible sur le site Learn OpenGL.


précédentsommairesuivant

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 © 2018 Joey de Vries. Aucune reproduction, même partielle, ne peut être faite de ce site ni 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.