Rendering, swapping, QML_RENDER_TIMING, too long
-
Hello,
I've developped a small QtQuick application that displays 50 very large images (1600900 pxl) to run on an embedded system with a dedicated GPU and VRAM. The output screen is 800480 pxl
On top of them, it displays a colored rectangle, which is animated (translation on x axis) for 1 second in an infinit loop.
Of course the rendering seems to last way more than one second (something 10 times longer).
I exported the QML_RENDER_TIMING=1 to get information on the rendering timings.The code looks like this:
@import QtQuick 2.0Item {
visible: true
width: 800
height: 480property bool bRunning: false SequentialAnimation { loops: Animation.Infinite running: bRunning NumberAnimation { target: idMyRectangle from: -800 to: 0 property: "x" duration: 2000 easing.type: Easing.Linear } } Item { id: idImagesContainer width: 1600 height: 900 clip: false
// width: 800
// height: 480
// clip: trueImage { source: "images/01.jpg" }
... 50 images (5 times 10 different sources)
Rectangle {
id: idMyRectangle
x: -800
width: 800
height: 480
color: "green"
}MouseArea { anchors.fill: parent onClicked: { parent.bRunning = true } }
}
@The traces give something like:
@- Breakdown of frame time; sync: 0 ms render: 3 ms swap: 170 ms total: 173 ms time since last frame: 175 ms
- Breakdown of frame time; sync: 1 ms render: 5 ms swap: 164 ms total: 170 ms time since last frame: 170 ms
- Breakdown of frame time; sync: 0 ms render: 2 ms swap: 168 ms total: 170 ms time since last frame: 172 ms
- Breakdown of frame time; sync: 0 ms render: 6 ms swap: 162 ms total: 168 ms time since last frame: 169 ms
- Breakdown of frame time; sync: 0 ms render: 2 ms swap: 170 ms total: 172 ms time since last frame: 172 ms
- Breakdown of frame time; sync: 1 ms render: 2 ms swap: 166 ms total: 169 ms time since last frame: 169 ms
- Breakdown of frame time; sync: 0 ms render: 2 ms swap: 169 ms total: 171 ms time since last frame: 172 ms
- Breakdown of frame time; sync: 0 ms render: 3 ms swap: 171 ms total: 174 ms time since last frame: 176 ms
- Breakdown of frame time; sync: 0 ms render: 2 ms swap: 168 ms total: 170 ms time since last frame: 171 ms
- Breakdown of frame time; sync: 0 ms render: 4 ms swap: 163 ms total: 167 ms time since last frame: 169 ms
- Breakdown of frame time; sync: 1 ms render: 5 ms swap: 164 ms total: 170 ms time since last frame: 171 ms
- Breakdown of frame time; sync: 1 ms render: 2 ms swap: 172 ms total: 175 ms time since last frame: 175 ms
- Breakdown of frame time; sync: 0 ms render: 3 ms swap: 175 ms total: 178 ms time since last frame: 179 ms
- Breakdown of frame time; sync: 0 ms render: 3 ms swap: 181 ms total: 184 ms time since last frame: 184 ms
- Breakdown of frame time; sync: 0 ms render: 3 ms swap: 167 ms total: 170 ms time since last frame: 171 ms
- Breakdown of frame time; sync: 1 ms render: 5 ms swap: 166 ms total: 172 ms time since last frame: 173 ms
- Breakdown of frame time; sync: 0 ms render: 5 ms swap: 167 ms total: 172 ms time since last frame: 173 ms
- Breakdown of frame time; sync: 1 ms render: 4 ms swap: 164 ms total: 169 ms time since last frame: 170 ms
- Breakdown of frame time; sync: 0 ms render: 2 ms swap: 168 ms total: 170 ms time since last frame: 172 ms
- Breakdown of frame time; sync: 0 ms render: 3 ms swap: 167 ms total: 170 ms time since last frame: 172 ms
@
I'm sadly not very good at these things.
So I understand that there is a synchronization occurring, I suppose between the rendering thread and the main thread of something like 1ms or less. I also understand that the rendering itself is of 3 to 4 ms. But I don't understand why the swap is taking so long.At some point, I tried to limit the size of the containing Item to match the 800*480 pxl output, and to clip the content, but with no noticeable improvements.
Also my viewer was tested with a basic viewer leading to worse results. The results presented here are obtain with the following viewer initialization:
@int main(int argc, char *argv[])
{
QApplication app(argc, argv);QQuickView view; // Set Viewer frameless and transparent view.setSurfaceType(QSurface::OpenGLSurface); QSurfaceFormat format; format.setAlphaBufferSize(8); format.setDepthBufferSize(24); format.setRenderableType(QSurfaceFormat::OpenGLES); view.setFormat(format); QColor color; color.setRedF(0.0); color.setGreenF(0.0); color.setBlueF(0.0); color.setAlphaF(0.0); view.setColor(color); view.setClearBeforeRendering(true); view.setFlags(Qt::FramelessWindowHint); view.setSource(QUrl(QStringLiteral("main.qml"))); view.show(); return app.exec();@
Any explanation why the swap time is taking so long is welcome.
Thank you,
Bill -
Hmmm, 50 images are a lot of graphics memory. You want to implement a simple slideshow? For this maybe its better to use "StackView":http://qt-project.org/doc/qt-5/qml-qtquick-controls-stackview.html and push and pull the images when you need them.
-
Hello,
Sorry if you misunderstood, i don't want to display image after image. In the contrary, I want all images displayed on top of the other, then play an animation on top of them, and check performances.
My expectations is that only the rectangle gets redrawn frame after frame, and that therefore the rendering frame rate should be as if no images were drawn at all.Bill
-
Sorry if i understand it wrong, but when you have an animated rectangle, the application need to redraw the screen. I dont know if the qtquick renderer know that only the top image need to be redrawn because the others are hidden from this one.
-
Hello again,
I expect QtQuick and the famous scenegraph to know not to spend to much time to redraw the images, because the associated node in the scenegraph did not change, and it seems like it does not indeed.
But I have issues with the swapping apparently (170ms), not with the rendering itself (3ms). -
I have googled a bit of pages, and apparently the swap operation includes not only the swap itself but the actual execution of all openGL commands in the queue. That must explain why it's taking so much time.
Then I bet my GPU is limited to execute this simple program.
What do you think? -
Hmmm what's with this, found "here":http://www.opengl.org/wiki/Swap_Interval
A swap interval of 1 tells the GPU to wait for one v-blank before swapping the front and back buffers. A swap interval of 0 specifies that the GPU should never wait for v-blanks, thus performing buffer swaps as soon as possible when rendering for a frame is finished.
-
As the output suggests, the scheduling of the rendering is pretty fast. However, when the GPU is told to layer 50 unique images on top of each other, it will struggle. Even my MacBook Pro struggles with alpha blending 50 images on top of each other :)
On a lower end chips, you can expect to fill the screen 2-3 times per frame.
The scene graph will use z buffer to perform early-z IF the image is opaque (aka a .jpg), but that is still a per-pixel operation. And it only applies if the GPU does have early z.
-
Hello,
I checked my application on Qt5.0.2 and Qt5.2.1, and noticed a 7x improvement on a same HW. Is this possible according to your knowledge???
Bill
-
I don't see how it should for the example you posted above, but for a more general UI, this is very possible. Qt 5.2 introduced a new renderer which does things much better: http://blog.qt.digia.com/blog/2013/09/02/new-scene-graph-renderer/
-
Well,
I just tested an even more complex application on my Windows laptop (4700HQ processor, 32GB RAM, Dedicated NVIDIA GPU with 2GB RAM).
I have around 200 images below my rectangle. (with less images I did not get obvious differences)
With Qt5.0.2, I have this typical results: (QML_RENDER_TIMING=1)
- Breakdown of frame time; sync: 0 ms render: 12 ms swap: 20 ms total: 32 ms time since last frame: 33 ms
With Qt5.2.1, I have these typical results:(QSG_RENDER_TIMING=1)
WindowsRenderLoop: animations=0 ms- Breakdown of render time: preprocess=0, updates=0, binding=0, render=0, total=0
WindowsRenderLoop(t=4009): window=0x28fe1c, polish=0 ms, sync=0 ms, render=0 ms, swap=10 ms
It seems almost like 3x times faster on my PC!
-
Oh you are right. I did not configure anything at all on installation as far as I remember. How can I easily check this? On the link instruction basically?
Thank you.
Bill -
configure should print which OpenGL you are getting when you configure Qt. Inside Qt, you should have the QT_OPENGL_ES_2 define set if you have ANGLE. On the binaries you can check with depends.exe if qtgui is linking with opengl.dll (which is OpenGL proper) or if it using the egl/gles ANGLE library.
-
5.2.1: g++ -Wl,-subsystem,windows -mthreads -o debug\test.exe debug/main.o -lglu32 -lopengl32 -lgdi32 -luser32 -lmingw32 -lqtmaind -LC:\Qt521\5.2.1\mingw48_32\lib -lQt5Quickd -lQt5Qmld -lQt5Widgetsd -lQt5Networkd -lQt5Guid -lQt5Cored
5.0.2:g++ -Wl,-subsystem,windows -mthreads -o debug\test.exe debug/main.o -lmingw32 -lqtmaind -LC:\Qt\Qt5.0.2\5.0.2\mingw47_32\lib -lQt5Quickd -lQt5Qmld -lQt5Widgetsd -lQt5Networkd -lQt5Guid -lQt5Cored -llibEGLd -llibGLESv2d -lgdi32 -luser32
Apparently it's not the same libraries, but still no trace of Angle though?
Also in the build environment, no trace of this QT_OPENGL_ES_2 variable in either case.
What is your opinion?
Bill
-
grrr