Friday, April 29, 2016

Evaluation of the Qt Quick Scene Graph Performance

To get a grasp of what I should do to achieve the best performance I played a little with Qt Quick Scene Graph.

Difference between QPainter approach and Qt Quick Scene Graph.

QPainter, which is the base of drawing in KStars, uses an imperative way whereas QtQuick Scene Graph utilizes declarative paradigm. In Scene Graph you add some set of "nodes" (classes with prefix QSG) to the root node that is returned by calling QQuickItem::updatePaintNode() whenever you want to render QQuickItem and manipulate them during the runtime (change position, geometry, material, etc.) This gives possibilities to perform some optimization like batching the nodes to draw them in fewer calls to OpenGL, which can be of tremendous help for us in drawing stars, for example.


My initial idea of SkyMapLite in KStars Lite was to create for every SkyComponent separate QQuickItem derived object and reparent it to SkyMapLite, thus making it visible. The QQuickItem derived object would contain the painting code and communicate with SkyComponent to get the actual coordinates of the object in sky and convert them using Projector to "x" and "y" coordinates. However, it seemed to me that this approach would result in making a lot of unnecessary actions like calling signals during the change of "x", "y" and "visible" properties.

Another approach is to directly ask SkyMapLite to instantiate a QSGNode derived object, which would visually represent SkyComponent, and add it to the root node of SkyMapLite, thus bypassing the QQuickItem. However, this way the code would become more complicated as the Scene Graph on the most platforms lives in the separate thread and possibilities in communicating with the GUI thread from QSGNodes are slightly limited.

To test both approaches I made two versions of program that just shows you 5000 .png images of blue balls with the resolution 16x16 (Use of images with the resolution of some power of 2 allows better batching). The first version - each ball is a separate QQuickItem derived object with overridden updatePaintNode() function, and the second one consists of the object of class Canvas, which instantiates objects of QSGNode derived class that paints the same texture on the screen. I also played with plain rectangles instead of textures and the results of my small test you can find here. The table shows the number of CPU counts used to create nodes and render the first frame of the program.

Areas with similar color are drawn in batch. Visualized by setting QSG_VISUALIZE env. variable to "batches"

As you can see from the test results - batching reduces the number of instructions executed in CPU significantly. As for the difference between two approaches - the direct creation of QSGNodes doesn't perform significantly better than instantiating QQuickItems.

So what I noticed was that rectangles with different colors are not drawn in batch, and late very good expert in Scene Graph, Gunnar Sletta, told me that I should use QSGGeometryNode + QSGVertexColorMaterial instead of QSGSimpleRectNode. Also to draw the texture in batch the QQuickWindow::TextureCanUseAtlas flag has to be set during the creation of texture and to include a lot of texture in texture atlas you probably would have to set QSG_ATLAS_WIDTH and QSG_ATLAS_HEIGHT env. variables to the GL_MAX_TEXTURE_SIZE. You can visualize what textures are included in atlas by setting QSG_ATLAS_OVERLAY to 1. A structure of all nodes in Scene Graph can be obtained by setting QSG_RENDERER_DEBUG to "dump". You can read our full conversation here.

Then I made textures "movable" and tried to measure how much CPU counts requires setting "x", "y" and "visible" properties when the QQuickItem is moved or gets out of screen. xChanged() and yChanged() each took about 2 500 000 counts during the few seconds of moving 5000 objects out and to the screen and visibleChanged() signal required 238.564 instructions to execute.;postID=6946697078078991651
I tested the "moving" version with QQuickItems on my laptop and Nexus 7 (2nd gen) and got fairly smooth results, especially when part of the items was set to invisible state because they were out of the screen. I even managed to run it with 1000 objects on my old Motorola Defy with Android 2.3!


I inserted a counter in SkyObject constructor to see that KStars creates about 14400 of them with standard set of catalogs (this count is just to get an idea about approximate amount of objects). Given that number and the fact that various objects appear only on some levels of zoom and not all of them will be inside the current user's view, although we won't be able to batch everything in SkyMapLite, as elements differ in their visual representation, I think that my initial approach with QQuickItem will be enough.
Doing all of this was very useful to me as I've used for the first time the Valgrind profiler and now know better the internals of Scene Graph.
From now on I will concentrate on prototyping the SkyComponentsLite derived objects and details of SkyMapLite.

Monday, April 25, 2016

Hello World!

Dear readers of my blog.

This year I'm happy to be a participant of Google Summer of Code 2016 program and work together with my mentor Jasem Mutlaq on such an exciting project like Lite version of one of the KDE's applications KStars (you can find more about KStars here).

What is KStars Lite?

As the title suggests it is a lite version for mobile/tablets, slow machines like budget laptops, netbooks, single-board computers like Raspberry Pi, etc. One of the main differences between desktop and lite versions is that the graphics of the latter is based on QML/QtQuick. KStars Lite is built bearing in mind the differences between mouse/touch interfaces and the graphical frontend will be designed according to touch interfaces of mobile platforms.


What will be done?

The first goal of this project is to build a QML/QtQuick version of SkyMap, the "heart" of the KStars. . This includes displaying of almost all sky objects like planets, stars, asteroids, etc (you can find a detailed list of sky objects in my proposal in the end of this post). It can be done using several approaches and my first task is to choose the best one to provide fluent and smooth experience to the end user.
User will be able to interact with the SkyMap by panning with touch screen, using gestures like "pinch to zoom" and tap on the objects. Everything from this list will be also available for use with mouse.
Other features include Search, Simulation Time, Location retrieval and Timekeeping, Projection Systems and Color Schemes.
To provide the best experience the logic behind loading the sky objects from catalogs will be changed (you can read details in my proposal).

Why KStars? 

I become interested in Astronomy last year after reading a book about the space exploration. Right now I'm subscribed to the one of the astronomy magazines and with each its issue I'm getting a part of the telescope so my first newbie telescope is on my way :)
KStars Lite is also a great opportunity to strength my skills in QML/QtQuick. I like the declarative way of designing the interfaces and see KStars Lite as a probable motivation to move the whole project to QML/QtQuick.


About me

My name is Artem Fedoskin and I come from Kazakhstan. I'm a first-year master student majoring in Computer Science at South Kazakhstan State University. Apart from programming I love music (different genres from rock and metal to synthpop), reading sci-fi and fantasy books and comics. Especially I like Star Wars universe :)

You can find my proposal for KStars Lite here