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é.
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.
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 :
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.
glBindBuffer(GL_VERTEX_ARRAY, vbo);
glCheckError();
Cela produira l’affichage suivant :
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 :
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() :
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 :
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 :
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 :
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 :
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 :
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é :
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 :
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 :
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 :
#
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 :
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 :
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 :
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 :
// 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 :
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.
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.
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.
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.