OpenGL in Qt 5.1 – Part 4

This article continues our series on what is new in Qt 5.1 with respect to OpenGL. Earlier articles in this series are available at:

OpenGL Debug Output

The traditional way to debug OpenGL is to call glGetError() after every GL function call. This is tedious, clutters up our code, and doesn’t warn about performance issues or other non-error situations. In the last couple of years various debug extensions have been proposed and have proven their usefulness. These have very recently been unified into the GL_KHR_debug extension for both OpenGL and OpenGL ES.

KDAB engineer Giuseppe D’Angelo has exposed the functionality of the GL_KHR_debug extension via the new class QOpenGLDebugLogger which will also be part of Qt 5.1. The QOpenGLDebugLogger class can be used to either request previously logged messages from OpenGL or to emit a signal each time OpenGL logs a message. The QOpenGLDebugLogger::messageLogged() signal can be connected up to a slot where you can respond to the message appropriately, say by outputting using qDebug(), handling the error etc.

The signal can be emitted either asynchronously for minimal performance impact on your running application, or synchronously and with a larger performance impact. Although the synchronous approach has a cost, it does have one massive advantage. Setting a break point in a slot connected to the messageLogged() signal will allow you to break execution and see the stack and the exact OpenGL function call that caused the error or

warning. This is incredibly useful when debugging OpenGL applications and not a glGetError() call in sight!

Using the above mechanism, OpenGL is also able to provide informational messages to us as well as errors. These may include data about where particular vertex buffer objects reside (GPU or CPU memory), if the correct usage hint has been given for a buffer object, or if we are violating it and causing the driver grief resulting in performance issues. All of these and more are now trivially available to us. It is even possible for your application or Qt to inject their own messages into the OpenGL logging system and we can filter based upon message type, severity etc.

Using the QOpenGLDebugLogger is very simple:

void Scene::initialize() { m_logger = new QOpenGLDebugLogger( this ); connect( m_logger, SIGNAL( messageLogged( QOpenGLDebugMessage ) ), this, SLOT( onMessageLogged( QOpenGLDebugMessage ) ), Qt::DirectConnection ); if ( m_logger->initialize() ) { m_logger->startLogging( QOpenGLDebugLogger::SynchronousLogging ); m_logger->enableMessages(); } // Populate a buffer object m_positionBuffer.create(); m_positionBuffer.setUsagePattern( QOpenGLBuffer::StreamDraw ); m_positionBuffer.bind(); m_positionBuffer.allocate( positionData, vertexCount * 3 * sizeof( float ) ); } void Scene::onMessageLogged( QOpenGLDebugMessage message ) { qDebug() << message; }

If the debug logger is successfully initialized, the following calls that buffer some vertex data would result in a message like:

QOpenGLDebugMessage("APISource", 131185, "Buffer detailed info: Buffer object 1 (bound to GL_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations.", "LowSeverity", "OtherType")

It is highly recommended to use the above example as a guide for adding QOpenGLDebugLogger to your own OpenGL code. You will likely be amazed at the things it uncovers for you.