OpenGL Debugging

I normally use the NVIDIA OpenGL Debugger for debugging OpenGL related issues.

What is nice about the debugger is that it is simple to use when compared to using most other OpenGL debuggers.

When deciding to use an OpenGL debugger you need to consider two things:
  • Is the problem only seen on particular GPUs?
  • Is the problem only seen on a particular OS?
If the answer is yes to the GPU then you have to debug on a system with that GPU or class of GPUs. You have no choice as the bug is likely to be device or driver specific.

If the answer is yes to the OS you may still have a choice on the debugger you use.

If I can I try to use a desktop system when debugging OpenGL related issues, this means that everything I write will work on Windows, Linux, Android and Embedded Linux. This means that I am only left with the device/OS specific issues that I have to debug using a specific hardware/OS combination.

Starting the debugger:

  • /usr/local/Tegra-Graphics-Debugger/nvidia-gfx-debugger &

Setup

Select either x64 or x86 target platform.

You then need to enter the hostname, username and password for the system you will be debugging on:
If you are running an application local then use 'localhost'.

Switch to the Launch tab and navigate to the location of your executable. Select the executable and expand the 'Launch Environment' section.
Add the following Environment variables:
  • LD_LIBRARY_PATH
  • Any application specific environment variables.
Click Launch once you are satisfied with the setup.
The debugger works by capturing a frame. This means that your application pretty much runs at normal speed when using an OpenGL debug context.

Once you have your application setup you then 'Capture' a frame by pressing 'Capture Frame'.

If you are attempting to capture something from an automated test harness then you need to loop over the particular frame in such away as to make the debugger think you are running an application with each frame being presented as a frame would normally be presented in an application. This is not ideal but the majority of OpenGL debuggers are 'frame debuggers', i.e. they are not program debuggers.

Debugging a Frame

The debugger provides the following windows:
  • Scrubber View
  • Current Target View
  • Events View
  • API Inspector View
The application I am developing/debugging makes heavy use of Transform Feedback.

If I select one  of the 'glDrawTransformFeedback' calls I can see what is being drawn with the call and the current OpenGL state and data.
The information is presented in the 'Current Target View' and 'API Inspector View'. The application window is also annotated.

You will need to work your way down the OpenGL pipeline stages and the OpenGL Objects in order to debug a frame. The debugger includes cross references so that you can easily view the data associated with a particular OpenGL call (or the data at the time of the call).

The one downside with debugging transform feedback is that all the debugger presents you with is a memory dump of the buffers. There is no linkup between the program inputs (shader inputs) and the memory buffer being used for the drawing. All you see is pretty much as follows:
At this point you may need to modify your program to read back the data from the buffer and write the data out in a form that you understand.

The problem with viewing data and understanding what you are looking at is more common than just transform feedback.

The way I normally approach debugging a frame is to select each of the draw commands in turn and see if what I am seeing is valid. Once I find a draw command that produces the wrong result I can look at the the buffers and OpenGL objects.

In the sample I am debugging something is going wrong with the transform feedback. Looking at Transform Feedback buffer object name I can then trace back to where the data was setup. The following screenshot shows the line where something has gone wrong. The transform feedback object is 50 (the red outlined triangles in the 'Current Target View').
Search backwards in the log I look for the binding of this transform feedback object (glBindTransformFeedback).
This allows me to check the shaders being used and the OpenGL state.

What this does not help me with is viewing the input and output to the transform feedback but I can check that everything else is as I expect it too be before I start modifying the code to look at the buffers.

What I have noticed is that before this draw occurs the display is exactly as I would have expected it to be, so I am drawing too much. Therefore I need to drop back to using a debugger such as gdb to figure out why I am drawing this polygon.

OpenGL State Tracking

You may have noticed a lot of calls to OpenGL to check the state. This is a debug build and as part of the inbuilt application validation I check that the OpenGL state is what I expect it to be.

All calls to change the OpenGL state go through a class which keeps track of the OpenGL state within the application.

This allows me to minimise the state changes and to also validate that the state has not changed behind my back (other peoples code running in my application via a plugin).

Additionally OpenGL state changes can be expensive and querying the state on the fly is expensive so it is best to minimise both queries and setting of state.

Other Debugger Options

On Linux you have the option of using Mesa and apitrace.

This combination is quite powerful especially if you are working with a company developing/fixing a GPU driver on Linux.

apitrace allows you to capture a series of frames and to then playback those frames on a similar setup.

Comments