Bad performance cube example
-
I’m having performance issues with my c++/qt openGL game, so I thought I’d go back to the basics (the qt cube example). But then I found that the cube example (Qt\Examples\Qt-6.3.1\opengl\cube) also has bad performance, using qt 6.3.1.
The cube example has a timer set to a 12ms interval. I’m guessing Qt has a max frame rate of 60 (16ms per frame), but I’m consistently getting intervals that are much longer. Depending on the machine I get different behaviour:
- 2014 Surface laptop (win10, integrated graphics, i7-6650U): 14% of frame are above 17ms, but most were 18ms, 3% above 20ms. Up to 49ms.
- Desktop (win10, NVIDIA 2060RTX, AMD Ryzen 7 3700X): 1% of frames are above 17ms, of those: avg 51ms(!), up to 98ms(!).
Strangely enough, the problem is visually much worse on my desktop machine. Either way, I expect both machines to never drop any frames on this example.
I added this code to measure frame drops:
MainWidget.h:qint64 lastPaint = 0; int goodFrames = 0; int badFrames = 0;
MainWidget::paintGL():
auto current = QDateTime::currentMSecsSinceEpoch(); if(current - lastPaint > 17){ qDebug() << "frame drop! Frame took " << current - lastPaint << "ms. " << badFrames << "/" << goodFrames << "were late"; badFrames++; } else{ goodFrames++; } lastPaint = current;
I also looked at qt open source game projects to find an example I could copy from, but I see frame drops in those too (Dust Racing 2D, Rise of enigmas).
When running the desktop machine in safe mode, I got a different graphics api (mesa), which was running smoothly. This suggested that the problem is with the nvidia drivers. But when I measured the opengl calls (using glFinish before and after draws), calls were only taking 0 / 1 ms. Also I do not get any frame drops when playing Doom 2016 (1440p, openGL 4.5) on the desktop machine. At this point I don’t know what to make of this…
What could be the cause of the frame drops? Is there a way to improve the performance? Or is qt + QOpenGLWidget not suited for 60fps without frame drops?
-
Take a look at this threads
https://forum.qt.io/topic/55193/what-s-the-fastest-way-to-display-some-text-in-qt/23
and this
https://forum.qt.io/topic/60063/smooth-character-movement/13
There is lots of usefull information about game development and they address your issues
-
@johngod
Thanks a lot for the pointers, this is exactly what I was looking for. I'm going to try to implement the v-sync!
(Sorry for the late reply, I didn't have e-mail notifications on yet)
Also good luck with your QML game, hope you figured out how to use v-sync there! -
Ok, so I've added v-sync by using
QOpenGLWindow
and itsframeSwapped
signal. Some good news and some bad.V-sync solved one issue. At first with v-sync was still measuring many delays, but I found that some of those were actually measurement errors.
QDateTime::currentMSecsSinceEpoch()
is not accurate enough, I'm usingQElapsedTimer
now. Also the code I used to test somehow interfered with the measurement. When I just printedqDebug() << elapsedTimer.elapsed() - lastUpdateRotation;
without branch, and did the analysis in excel, I found that almost all frames took 16-17 ms, so exactly 60fps :)It didn't solve the frame skips on the RTX 2060. I'm getting none on the surface's iGPU (ok, I got a few above 20, but all of these were still below 30ms), but for some reason the desktop with beefy GPU still skips 0.7% of frames. And these are above 40ms, so really noticeable, max is 100ms.
I'm measuring on the
frameSwapped
signal now, so I can't blame the qt event loop for doing something betweenframeSwapped
andpaint
. It might be something between the driver and GPU, but I'm still somewhat lost on this part.