Skip to content

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.

About KDAB

KDAB is a consulting company offering a wide variety of expert services in Qt, C++ and 3D/OpenGL and providing training courses in:

KDAB believes that it is critical for our business to contribute to the Qt framework and C++ thinking, to keep pushing these technologies forward to ensure they remain competitive.

FacebookTwitterLinkedInEmail

Categories: KDAB Blogs / KDAB on Qt / OpenGL / QtDevelopment

Tags: /
is a senior software engineer at KDAB where he heads up our UK office and also leads the 3D R&D team. He has been developing with C++ and Qt since 1998 and is Qt 3D Maintainer and lead developer in the Qt Project. Sean has broad experience and a keen interest in scientific visualization and animation in OpenGL and Qt. He holds a PhD in Astrophysics along with a Masters in Mathematics and Astrophysics.

6 thoughts on “OpenGL in Qt 5.1 – Part 4”

  1. Could you upload the complete source code of part1-part4? It is new for me. It is hard to follow. Thanks

  2. Excellent post. Though I miss the lively discussions with Grumpy OpenGL from Part 1 & 2. Yes I know he was kind of rude, but he asked useful questions. It’s important to have the option to just use Qt for the OpenGL context versus using these helper classes, and to understand the trade-offs about when and how to use each…

    It would also be good to understand more about how Qt OpenGL helpers relate to using Qt with ANGLE versus desktop OpenGL. My understanding is that the Qt OpenGL helpers are based on OpenGL ES 2.0, which means they focus on ANGLE.

    Most of all, it would also be great to see more info on how to use raw opengl, and how to mix Qt helpers with raw opengl… And if you do this, then how to make sure you can build for both ANGLE and desktop OpenGL… Or is there an easy way to have one build which uses desktop OpenGL when advanced features are supported (on the OpenGL implementation), but uses ANGLE for compatibility mode.

  3. Hello,
    I don’t understood why this error is send. The function allocate fill the openGLBuffer so the transfer will be from CPU memory to video memory.
    I think I have misunderstood something, but I really don’t know what. Could you explain it to me please ?

      1. The warning throw by the exemple :
        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”)

Leave a Reply

Your email address will not be published. Required fields are marked *