原文见:
http://www.kdab.com/opengl-in-qt-5-1-part-3/?utm_source=rss&utm_medium=rss&utm_campaign=opengl-in-qt-5-1-part-3 OpenGL in Qt 5.1 – Part 3Published: March 18, 2013 by Sean Harmer
This article continues our series on what is new in Qt 5.1 withrespect to OpenGL. If you haven’t already seen them, you may beinterested in reading
Part 1 and
Part 2.
Timer QueriesOpenGL on the desktop exposes a very useful tool in the shape of
timer query objects. These can be used to record the amount of time taken by the
GPUto process sequences of commands. If we couple this with the usual CPUprofiling techniques then we can get a very complete understanding ofthe bottlenecks in our rendering code.One obvious place that could take advantage of this is the Qt Quick 2renderer. Although the Qt Quick 2 renderer does have options to enabletimings of various stages of rendering, this only tells us half of thestory. Namely, the CPU half. Using OpenGL timer queries would allow usto fill in the gap and gain an understanding of how the GPU isperforming.
Another common use for OpenGL timer queries is to provide feedback toadaptive rendering routines in order to maintain more consistent framerates. For example, if we instrument our rendering function and find atruntime that our application is rendering too slowly, we can perhapsincrease the frame rate by using less complex shaders or by using lowerresolution meshes etc. Conversely, if we find that we have GPU cycles tospare then we could improve rendering quality by perhaps using higherlevels of tessellation.Qt 5.1 will
make such tasks much easier with the introduction of two new classes developed by KDAB engineers:
QOpenGLTimerQuery and
QOpenGLTimeMonitor. The
QOpenGLTimerQueryclass is a simple wrapper around a single OpenGL timer query object andcan be used if you wish to have total control. It is expected that
QOpenGLTimeMonitorwill be the more commonly used class as this is a wrapper around asequence of timer query objects and makes it trivial to measure the GPUtime of the various stages of our rendering functions:
- void Scene::initialize()
- {
- // Create a timer query object
- m_timeMonitor = new QOpenGLTimeMonitor( this );
- m_timeMonitor->setSampleCount( 5 );
- if ( !m_timeMonitor->create() )
- qWarning() << "Failed to create timer query object";
-
- // Generate some names for the various stages of rendering
- m_renderStages << "Clear Buffer" << "VAO Binding"
- << "Shader Program Binding" << "Drawing";
- }
-
- void Scene::render()
- {
- // Start the timer query
- m_timeMonitor->recordSample();
-
- // Do some rendering
- m_funcs->glClear( GL_COLOR_BUFFER_BIT );
- m_timeMonitor->recordSample();
- m_vao.bind();
- m_timeMonitor->recordSample();
- m_shaderProgram.bind();
- m_timeMonitor->recordSample();
- m_funcs->glDrawArrays( GL_TRIANGLES, 0, 3 );
-
- // End the timer query
- m_timeMonitor->recordSample();
-
- // Block until the results are available
- QVector<GLuint64> timeSamples = m_timeMonitor->waitForSamples();
- qDebug() << "timeSamples =" << timeSamples;
-
- QVector<GLuint64> intervals = m_timeMonitor->waitForIntervals();
- for ( int i = 0; i <= intervals.count(); ++i )
- qDebug() << i << m_renderStages.at( i )
- << double( intervals.at( i ) ) / 1.0e6 << "msecs";
-
- // Clear the query results ready for the next frame
- m_timeMonitor->reset();
- }
This is obviously a trivial example but gives an idea of the usage.Note that the timer intervals and timestamps are recorded innanoseconds. Sample output from this is:
timeSamples = QVector(5850713788736, 5850713794176, 5850713794848, 5850713795552, 5850713801952)
0 "Clear Buffer" 0.00544 msecs
1 "VAO Binding" 0.000672 msecs
2 "Shader Program Binding" 0.000704 msecs
3 "Drawing" 0.0064 msecs
So here we see in this trivial example (which just draws a singlelarge triangle) that the GPU is using only a fraction of a millisecond.This means that we could easily ask the GPU to do more work per-frame(as we would certainly hope!).There is much more to say about the nuances of using timer queries but we’ll leave that to a future more in-depth article.