Lerne OpenGL. Lektion 7.1 - Debuggen

Bild Grafische Programmierung ist nicht nur eine Quelle des Spaßes, sondern auch der Frustration, wenn etwas nicht wie beabsichtigt angezeigt wird oder überhaupt nichts auf dem Bildschirm angezeigt wird. Angesichts der Tatsache, dass das meiste, was wir tun, mit der Manipulation von Pixeln zusammenhängt, kann es schwierig sein, die Ursache des Fehlers herauszufinden, wenn etwas nicht so funktioniert, wie es sollte. Das Debuggen dieser Art von Fehler ist schwieriger als das Debuggen von Fehlern auf der CPU. Wir haben keine Konsole, auf der wir den Text ausgeben können, wir können keinen Haltepunkt in den Shader setzen und wir können nicht einfach den Status des Programms auf der GPU übernehmen und überprüfen.


In diesem Tutorial werden wir Ihnen einige der Debugging-Methoden und -Techniken für Ihr OpenGL-Programm vorstellen. Das Debuggen in OpenGL ist nicht so schwierig, und das Erlernen einiger Tricks wird sich definitiv auszahlen.



glGetError ()


Wenn Sie OpenGL falsch verwenden (z. B. wenn Sie einen Puffer einrichten und vergessen, ihn zu binden), bemerkt OpenGL hinter den Kulissen ein oder mehrere benutzerdefinierte Fehlerflags und erstellt diese. Wir können diese Fehler verfolgen, indem glGetError() Funktion glGetError() aufrufen, die einfach die gesetzten glGetError() überprüft und den Fehlerwert zurückgibt, wenn Fehler auftreten.


 GLenum glGetError(); 

Diese Funktion gibt ein Fehlerflag oder gar keinen Fehler zurück. Liste der Rückgabewerte:


FlaggeCodeBeschreibung
GL_NO_ERROR0Seit dem letzten Aufruf von glGetError wurde kein Fehler generiert
GL_INVALID_ENUM1280Wird festgelegt, wenn ein Aufzählungsparameter ungültig ist
GL_INVALID_VALUE1281Wird festgelegt, wenn der Wert ungültig ist
GL_INVALID_OPERATION1282Wird festgelegt, wenn ein Befehl mit angegebenen Parametern ungültig ist
GL_STACK_OVERFLOW1283Es wird festgelegt, wenn das Verschieben von Daten auf den Stapel (Push) einen Stapelüberlauf verursacht.
GL_STACK_UNDERFLOW1284Es wird festgelegt, wenn die Operation zum Poppen von Daten vom Stapel (Pop) vom kleinsten Punkt auf dem Stapel aus erfolgt.
GL_OUT_OF_MEMORY1285Wird festgelegt, wenn eine Speicherzuweisungsoperation nicht genügend Speicher zuweisen kann.
GL_INVALID_FRAMEBUFFER_OPERATION1286Wird beim Lesen / Schreiben in / aus einem Framebuffer festgelegt, der nicht abgeschlossen ist

In der Dokumentation zu OpenGL-Funktionen finden Sie Fehlercodes, die von falsch verwendeten Funktionen generiert werden. Wenn Sie sich beispielsweise die Dokumentation zur Funktion glBindTexture() , finden Sie die von dieser Funktion generierten Fehlercodes im Abschnitt Fehler.
Wenn das Fehlerflag gesetzt ist, werden keine weiteren Fehlerflags generiert. Wenn glGetError aufgerufen wird, löscht die Funktion außerdem alle glGetError (oder nur eines auf einem verteilten System, siehe unten). Dies bedeutet, dass wenn Sie glGetError nach jedem Frame einmal aufrufen und einen Fehler erhalten, dies nicht bedeutet, dass dies der einzige Fehler ist und Sie immer noch nicht wissen, wo dieser Fehler aufgetreten ist.


Beachten Sie, dass, wenn OpenGL auf verteilte Weise arbeitet, wie dies häufig bei Systemen mit X11 der Fall ist, andere Fehler generiert werden können, wenn sie unterschiedliche Codes haben. glGetError Sie glGetError wird einfach nur eines der Fehlercode-Flags anstelle von allen glGetError . Aus diesem Grund empfehlen sie, diese Funktion in einer Schleife aufzurufen.

 glBindTexture(GL_TEXTURE_2D, tex); std::cout << glGetError() << std::endl; //  0 ( ) glTexImage2D(GL_TEXTURE_3D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, data); std::cout << glGetError() << std::endl; //  1280 ( ) glGenTextures(-5, textures); std::cout << glGetError() << std::endl; //  1281 (  std::cout << glGetError() << std::endl; //  0 ( ) 

Eine Besonderheit von glGetError besteht darin, dass es relativ einfach ist, festzustellen, wo Fehler auftreten können, und zu überprüfen, ob OpenGL korrekt verwendet wird. Angenommen, Sie zeichnen nichts und wissen nicht, was der Grund ist: Der Frame-Puffer ist falsch eingestellt? Vergessen, die Textur einzustellen? Wenn Sie glGetError überall aufrufen, können Sie schnell herausfinden, wo der erste Fehler auftritt.
Standardmäßig meldet glGetError nur die Fehlernummer, die erst dann leicht zu verstehen ist, wenn Sie sich die Codenummern merken. Oft ist es sinnvoll, eine kleine Funktion zu schreiben, um eine Fehlerzeichenfolge zusammen mit der Position zu drucken, von der aus die Funktion aufgerufen wird.


 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__) 

Wenn Sie weitere Aufrufe von glCheckError tätigen glCheckError , ist es hilfreich zu wissen, wo der Fehler aufgetreten ist.


 glBindBuffer(GL_VERTEX_ARRAY, vbo); glCheckError(); 

Fazit:



Eine wichtige Sache bleibt: Es gibt einen langjährigen Fehler in GLEW: glewInit() setzt immer das Flag GL_INVALID_ENUM . Um dies zu beheben, rufen glGetError einfach glGetError nach glewInit auf, um das Flag zu löschen:


 glewInit(); glGetError(); 

glGetError hilft nicht viel, da die zurückgegebenen Informationen relativ einfach sind, aber es hilft oft, Tippfehler zu erkennen oder die Stelle zu ermitteln, an der der Fehler aufgetreten ist. Dies ist ein einfaches, aber effektives Debugging-Tool.


Debug-Ausgabe


Das Tool ist weniger bekannt, aber nützlicher als glCheckError , die OpenGL-Erweiterung "Debug-Ausgabe", die im OpenGL 4.3- glCheckError enthalten war. Mit dieser Erweiterung sendet OpenGL eine Fehlermeldung mit den Details des Fehlers an den Benutzer. Diese Erweiterung bietet nicht nur weitere Informationen, sondern ermöglicht es Ihnen auch, Fehler mit dem Debugger abzufangen, wo sie auftreten.


Die Debug-Ausgabe ist in OpenGL ab Version 4.3 enthalten. Dies bedeutet, dass Sie diese Funktionalität auf jedem Computer finden, der OpenGL 4.3 und höher unterstützt. Wenn diese Version nicht verfügbar ist, können Sie die Erweiterungen ARB_debug_output und AMD_debug_output . Es gibt auch nicht überprüfte Informationen darüber, dass die Debugging-Ausgabe unter OS X nicht unterstützt wird (der Autor des Originals und der Übersetzer haben nicht getestet. Bitte informieren Sie den Autor des Originals oder mich in privaten Nachrichten über den Fehlerkorrekturmechanismus, wenn Sie eine Bestätigung oder Widerlegung dieser Tatsache finden. UPD: Jeka178RUS hat dies überprüft Tatsache: Standardmäßig funktioniert die Debug-Ausgabe nicht, er hat die Erweiterungen nicht überprüft.

Um die Debug-Ausgabe verwenden zu können, müssen wir während des Initialisierungsprozesses den OpenGL-Debug-Kontext anfordern. Dieser Prozess ist auf verschiedenen Fenstersystemen unterschiedlich, aber hier werden wir nur GLFW diskutieren, aber am Ende des Artikels im Abschnitt "Zusätzliche Materialien" finden Sie Informationen zu anderen Fenstersystemen.


Debug-Ausgabe in GLFW


Das Anfordern von Debugging-Kontexten in GLFW ist überraschend einfach: Sie müssen GLFW lediglich einen Hinweis geben, dass wir einen Kontext wünschen, der die Debugging-Ausgabe unterstützt. Wir müssen dies tun, bevor glfwCreateWindow aufrufen:


 glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); 

Sobald wir GLFW initialisiert haben, sollten wir einen Debugging-Kontext haben, wenn wir OpenGL 4.3 oder höher verwenden. Andernfalls müssen wir unser Glück versuchen und hoffen, dass das System weiterhin einen Debugging-Kontext erstellen kann. Im Fehlerfall müssen wir die Debug-Ausgabe über den OpenGL-Erweiterungsmechanismus anfordern.


Der OpenGL-Debugging-Kontext kann langsamer als normal sein. Sie sollten diese Zeile daher entfernen oder auskommentieren, während Sie an Optimierungen arbeiten oder vor der Veröffentlichung.

Um das Ergebnis der Initialisierung des Debug-Kontexts zu überprüfen, reicht es aus, den folgenden Code auszuführen:


 GLint flags; glGetIntegerv(GL_CONTEXT_FLAGS, &flags); if (flags & GL_CONTEXT_FLAG_DEBUG_BIT) { //  } else { //   } 

Wie funktioniert die Debug-Ausgabe? Wir übergeben eine Rückruffunktion an einen Nachrichtenhandler in OpenGL (ähnlich wie Rückrufe in GLFW) und können in dieser Funktion OpenGL-Daten nach Belieben verarbeiten und in unserem Fall nützliche Fehlermeldungen an die Konsole senden. Der Prototyp dieser Funktion:


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

Beachten Sie, dass unter einigen Betriebssystemen der Typ des letzten Parameters möglicherweise const void* .
Angesichts des großen Datensatzes können wir ein nützliches Fehlerdruckwerkzeug erstellen, wie unten gezeigt:


 void APIENTRY glDebugOutput(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, void *userParam) { // ignore non-significant error/warning codes 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; } 

Wenn die Erweiterung einen OpenGL-Fehler erkennt, ruft sie diese Funktion auf und wir können eine große Menge an Fehlerinformationen drucken. Beachten Sie, dass wir einige Fehler ignoriert haben, da sie unbrauchbar sind (z. B. 131185 in den NVidia-Treibern zeigt an, dass der Puffer erfolgreich erstellt wurde).
Nachdem wir den gewünschten Rückruf erhalten haben, ist es Zeit, die Debug-Ausgabe zu initialisieren:


 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); } 

Deshalb teilen wir OpenGL mit, dass wir die Debug-Ausgabe aktivieren möchten. Der Aufruf von glEnable(GL_DEBUG_SYNCRHONOUS) teilt OpenGL mit, dass eine Fehlermeldung glEnable(GL_DEBUG_SYNCRHONOUS) werden soll, wenn dies gerade passiert ist.


Debug-Ausgabefilterung


Mit der Funktion glDebugMessageControl können Sie die Arten von Fehlern auswählen, die Sie erhalten möchten. In unserem Fall erhalten wir alle Arten von Fehlern. Wenn wir nur die OpenGL-API-Fehler wie Fehler und das Signifikanzniveau Hoch haben wollten, würden wir den folgenden Code schreiben:


 glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, GL_DEBUG_SEVERITY_HIGH, 0, nullptr, GL_TRUE); 

In diesem Konfigurations- und Debugging-Kontext sendet jeder falsche OpenGL-Befehl viele nützliche Informationen:



Suchen Sie die Fehlerquelle über den Aufrufstapel


Ein weiterer Trick beim Debuggen der Ausgabe besteht darin, dass Sie den genauen Ort des Fehlers in Ihrem Code relativ einfach ermitteln können. Durch Festlegen eines Haltepunkts in der DebugOutput Funktion für den gewünschten Fehlertyp (oder am Anfang der Funktion, wenn Sie alle Fehler abfangen möchten) erkennt der Debugger den Fehler und Sie können im Aufrufstapel navigieren, um herauszufinden, wo der Fehler aufgetreten ist:



Dies erfordert einige manuelle Eingriffe. Wenn Sie jedoch ungefähr wissen, wonach Sie suchen, ist es unglaublich nützlich, schnell festzustellen, welcher Anruf den Fehler verursacht.


Eigene Fehler


Zusammen mit Lesefehlern können wir sie mit glDebugMessageInsert an das Debug-Ausgabesystem glDebugMessageInsert :


 glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_MEDIUM, -1, "error message here"); 

Dies ist sehr nützlich, wenn Sie eine Verbindung zu einer anderen Anwendung oder einem anderen OpenGL-Code herstellen, der einen Debugging-Kontext verwendet. Andere Entwickler können schnell alle gemeldeten Fehler in Ihrem benutzerdefinierten OpenGL-Code herausfinden.
Im Allgemeinen ist das Debuggen der Ausgabe (falls verfügbar) sehr nützlich, um Fehler schnell zu erkennen, und es lohnt sich auf jeden Fall, sich für die Optimierung einzusetzen, da dies erhebliche Entwicklungszeit spart. Eine Kopie des Quellcodes finden Sie hier mit glGetError und Debug-Ausgabe. Es gibt Fehler, versuchen Sie sie zu beheben.


Shader-Debug-Ausgabe


Wenn es um GLSL geht, haben wir keinen Zugriff auf Funktionen wie glGetError oder die Möglichkeit, den Code glGetError im Debugger glGetError . Wenn Sie auf einen schwarzen Bildschirm oder eine völlig falsche Anzeige stoßen, kann es sehr schwierig sein zu verstehen, was passiert, wenn das Problem im Shader liegt. Ja, Kompilierungsfehler melden Syntaxfehler, aber das Abfangen semantischer Fehler ist dieses Lied.
Eine der häufig verwendeten Methoden, um herauszufinden, was mit einem Shader nicht stimmt, besteht darin, alle relevanten Variablen im Shader-Programm direkt an den Ausgabekanal des Fragment-Shaders zu senden. Indem wir Shader-Variablen mit Farbe direkt auf den Ausgabekanal ausgeben, können wir interessante Informationen herausfinden, indem wir das Bild am Ausgang überprüfen. Zum Beispiel müssen wir herausfinden, ob die Normalen für das Modell korrekt sind. Wir können sie (transformiert oder nicht) vom Scheitelpunkt an den Fragment-Shader senden, wo wir die Normalen wie folgt ableiten:
(Hinweis: Warum gibt es keine Syntaxhervorhebung für GLSL?)


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

Durch die Ausgabe einer nicht farbigen Variablen an den Ausgabekanal mit der aktuellen Farbe können wir den Wert der Variablen schnell überprüfen. Wenn das Ergebnis beispielsweise ein schwarzer Bildschirm ist, ist es klar, dass die Normalen falsch auf die Shader übertragen werden, und wenn sie angezeigt werden, ist es relativ einfach, sie auf Richtigkeit zu überprüfen:



Aus den visuellen Ergebnissen können wir erkennen, dass die Normalen korrekt sind, da die rechte Seite des Anzugs überwiegend rot ist (was bedeutet, dass die Normalen ungefähr in Richtung der x-Spülachse angezeigt werden) und auch die Vorderseite des Anzugs in Richtung der positiven z-Achse (blau) gefärbt ist.


Dieser Ansatz kann auf jede Variable erweitert werden, die Sie testen möchten. Versuchen Sie jedes Mal, wenn Sie nicht weiterkommen und davon ausgehen, dass der Fehler in den Shadern liegt, einige Variablen oder Zwischenergebnisse zu zeichnen und herauszufinden, in welchem ​​Teil des Algorithmus ein Fehler vorliegt.


OpenGL GLSL Referenzcompiler


Jeder Grafiktreiber hat seine eigenen Macken. Zum Beispiel machen NVIDIA-Treiber die Anforderungen der Spezifikation etwas weicher, und AMD-Treiber erfüllen die Spezifikationen besser (was meiner Meinung nach besser ist). Das Problem ist, dass Shader, die auf einem Computer ausgeführt werden, aufgrund unterschiedlicher Treiber möglicherweise kein Geld auf einem anderen Computer verdienen.


Nach mehrjähriger Erfahrung können Sie alle Unterschiede zwischen verschiedenen GPUs kennenlernen. Wenn Sie jedoch sicherstellen möchten, dass Ihre Shader überall funktionieren, können Sie Ihren Code mithilfe des GLSL-Referenz-Compilers anhand der offiziellen Spezifikation überprüfen. Den sogenannten GLSL lang validator können Sie hier herunterladen ( Quelle ).


Mit diesem Programm können Sie Ihre Shader testen, indem Sie sie als erstes Argument an das Programm übergeben. Denken Sie daran, dass das Programm den Shadertyp durch Erweiterung bestimmt:


  • .vert : Vertex-Shader
  • .frag : Fragment-Shader
  • .geom : geometrischer Shader
  • .tesc : Shader zur Steuerung der Tessellation
  • .tese : Tessellation Computing Shader
  • .comp : Compute Shader

Das Programm auszuführen ist einfach:


 glslangValidator shader.vert 

Beachten Sie, dass das Programm nichts ausgibt, wenn keine Fehler vorliegen. Bei einem fehlerhaften Vertex-Shader sieht die Ausgabe folgendermaßen aus:



Das Programm zeigt nicht die Unterschiede zwischen den GLSL-Compilern von AMD, NVidia oder Intel an und kann nicht einmal alle Fehler im Shader melden, überprüft jedoch zumindest die Shader auf Übereinstimmung mit den Standards.


Bildpufferausgabe


Eine andere Methode für Ihr Toolkit besteht darin, den Inhalt des Bildpuffers in einem bestimmten Teil des Bildschirms anzuzeigen. Höchstwahrscheinlich verwenden Sie häufig Framebuffer, und da die ganze Magie hinter den Kulissen geschieht, kann es schwierig sein, festzustellen, was passiert. Die Ausgabe des Inhalts des Bildpuffers ist ein nützlicher Trick, um die Richtigkeit zu überprüfen.


Beachten Sie, dass der Inhalt des Bildpuffers, wie hier erläutert, mit Texturen und nicht mit Objekten in den Zeichenpuffern funktioniert

Mit einem einfachen Shader, der eine einzelne Textur zeichnet, können wir eine kleine Funktion schreiben, die schnell jede Textur in der oberen rechten Ecke des Bildschirms zeichnet:


 // 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); } 

 //main.cpp void DisplayFramebufferTexture(GLuint textureID) { if(!notInitialized) { // initialize shader and vao w/ NDC vertex coordinates at top-right of the screen [...] } 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); } } 

Dadurch erhalten Sie in der Ecke des Bildschirms ein kleines Fenster zum Debuggen der Ausgabe des Bildpuffers. Dies ist beispielsweise nützlich, wenn Sie versuchen, die Richtigkeit von Normalen zu überprüfen:



Sie können diese Funktion auch so erweitern, dass mehr als eine Textur gerendert wird. Dies ist eine schnelle Möglichkeit, um kontinuierliches Feedback von allen Elementen in Frame-Puffern zu erhalten.


Externe Debugger-Programme


Wenn alles andere fehlschlägt, gibt es noch einen Trick: Programme von Drittanbietern zu verwenden. Sie sind in den OpenGL-Treiber integriert und können alle OpenGL-Aufrufe abfangen, um Ihnen viele interessante Daten über Ihre Anwendung zu liefern. Diese Anwendungen können die Verwendung von OpenGL-Funktionen profilieren, nach Engpässen suchen und Frame-Puffer, Texturen und Speicher überwachen. Während der Arbeit an (großem) Code können diese Tools von unschätzbarem Wert sein.


Ich habe einige beliebte Tools aufgelistet. Probieren Sie jeden aus und wählen Sie den, der am besten zu Ihnen passt.


Renderderoc


RenderDoc ist ein gutes (vollständig geöffnetes ) separates Debugging-Tool. Wählen Sie zum Starten der Erfassung die ausführbare Datei und das Arbeitsverzeichnis aus. Ihre Anwendung funktioniert wie gewohnt. Wenn Sie ein einzelnes Bild anzeigen möchten, können Sie mit RenderDoc mehrere Bilder Ihrer Anwendung erfassen. Unter den erfassten Frames können Sie den Status der Pipeline, alle OpenGL-Befehle, den Pufferspeicher und die verwendeten Texturen anzeigen.



Codexl


CodeXL - GPU-Debugging-Tool, funktioniert als eigenständige Anwendung und Plugin für Visual Studio. CodeXL Bietet viele Informationen und eignet sich hervorragend zum Profilieren grafischer Anwendungen. CodeXL läuft auch auf Grafikkarten von NVidia und Intel, jedoch ohne OpenCL-Debugging-Unterstützung.



Ich habe CodeXL nicht viel verwendet, weil mir RenderDoc einfacher erschien, aber ich habe CodeXL in diese Liste aufgenommen, weil es wie ein ziemlich zuverlässiges Tool aussieht und hauptsächlich von einem der größten Hersteller von GPUs entwickelt wird.


NVIDIA Nsight


Nsight ist ein beliebtes NUIDIA GPU-Debugging-Tool. Es ist nicht nur ein Plug-In für Visual Studio und Eclipse, sondern auch eine separate Anwendung . Das Nsight-Plugin ist eine sehr nützliche Sache für Grafikentwickler, da es viele Echtzeitstatistiken zur GPU-Nutzung und zum Frame-für-Frame-Status der GPU sammelt.


Sobald Sie Ihre Anwendung über Visual Studio oder Eclipse mit den Debug-Befehlen oder der Nsight-Profilerstellung starten, wird sie in der Anwendung selbst gestartet. Eine gute Sache in Nsight: Rendern eines GUI-Systems (GUI, grafische Benutzeroberfläche) über einer laufenden Anwendung, mit dem alle Arten von Informationen über Ihre Anwendung in Echtzeit oder Frame-für-Frame-Analyse gesammelt werden können.



Nsight ist ein sehr nützliches Tool, das meiner Meinung nach die oben genannten Tools übertrifft, aber einen schwerwiegenden Nachteil hat: Es funktioniert nur auf NVIDIA-Grafikkarten. Wenn Sie NVIDIA-Grafikkarten und Visual Studio verwenden, ist Nsight auf jeden Fall einen Versuch wert.


, ( , VOGL APItrace ), , . , , () ( , ).


Zusätzliche Materialien


  • ? — Reto Koradi.
  • — Vallentin Source.

PS : - . , !

Source: https://habr.com/ru/post/de462897/


All Articles