QGLWidget performance questions
-
Hello,
I've been developing an application in Qt and have noticed a few strange performance issues in QGLWidget. My application consists of a central QGLWidget that fills the screen (1920x1200 for these tests), which I update in a timing loop. I noticed that there's a considerable delay between calls to the painGL method that is not explained entirely by the time to do the drawing. Here's a short trace of these timings:
Double buffering
interval 0.033373 time 0.015671
interval 0.033138 time 0.019200
interval 0.033421 time 0.017561
interval 0.033190 time 0.018223
...The first number is the time between calls to paintGL and the second number is the time for the paintGL method. I'm calling update() at the end of paintGL() to ensure that it's continuously painting. I noticed that if I disable double buffering, the timings change:
Single Buffer
interval 0.019626 time 0.019320
interval 0.019488 time 0.019134
interval 0.019301 time 0.019390
interval 0.019549 time 0.019208So, my first question, is whether double buffering really incurs this large a performance hit in Qt? That 0.015 seconds seems to be the difference between fluid real-time performance and noticeable stuttering.
Second, I noticed that adding a QStatusBar->showMessage() call with each paint throws the timings completely out of whack. Here's a trace with status bar updates on each iteration, still using single buffering:
Single buffer with status bar update
interval 0.042759 time 0.019768
interval 0.036161 time 0.019612
interval 0.032568 time 0.020782
interval 0.035944 time 0.020431Any ideas why drawing a status message would slow things down so much? Even without the status bar messages, there are still some odd slowdowns when I move the mouse over the GL pane.
The only other potentially relevant information that I can think of:
- The QGLWidget is inside a QAbstractScrollArea
- I'm using pixel buffers to send a texture to the GL
- Version 4.8.3 of the Qt library
Andrew
-
I have pared down my test case to this:
[code]
#include <QtGui>
#include <QGLWidget>
#include <QtOpenGL>
#include <QTime>class Window : public QGLWidget {
public:
Window();
virtual ~Window();protected:
void paintGL();private:
QTime timer;
};Window::Window() : QGLWidget(QGLFormat(QGL::NoDepthBuffer))
{
timer.start();
}Window::~Window()
{
}void
Window::paintGL()
{
fprintf(stderr, "%g\n", timer.elapsed()/1000.0);
timer = QTime();
timer.start();
update();
}int main(int argc, char *argv[])
{
QApplication app(argc, argv);Window widget; widget.show(); return app.exec();
}
[/code]It seems there's a constant 16ms overhead regardless of the window size or anything else, with double buffering enabled. Can anyone else reproduce this?
Andrew
-
I think that I've partially answered my first question, after much research. This article was very helpful:
http://www.anandtech.com/show/2794/2
In summary, my working theory is that Qt is double buffering with vsync, meaning that it's only swapping buffers at the refresh rate of the monitor. That's where the 16ms comes in, since that's exactly 60Hz. In my original test case, where the painting took just over 16ms, it needed to wait until the next vsync to swap the buffers - making it 30Hz. I also found the QGLFormat::setSwapInterval() function but unfortunately setting the value to 0 or -1 did not cause vsync to be disabled, on my platform at least. So it seems that if I want double buffering (I do), I'll have to live with this behavior.
My second question still stands, regarding why updating a status bar text message causes so much lag. I'll see if I can post a modified test case for this later today.
-
I choose a little bit different method of working with QGLWidget. I`m using timer to call updateGL which runs paintGL.
In your reimplemented QGLWidget
@QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateGL()));
timer->start(40); // update 25 times in second @P.S. Thanks for sharing info on v-syncing with double buffer.