Most efficient way to approach lots of polygons in QML/C++?

  • I am struggling with getting my QML application to run smoothly. I have extended QQuickPaintedItem to make a 2D map page. I then use the painter to draw out all of my map components which are store in QPolygons. The problem is that there are a lot of items to draw on the page. For example, the following screenshot is composed of 695 polygons with a total of 363051 points.

    I tried setting the render target to QQuickPaintedItem::FramebufferObject but that seems to make it run slower...

    I know from the 40000 chips example that Qt is capable of handling such things. I think I just need to implement it differently.

    What design changes can I make to make this run smoother?

    1_1513951727892_efis map.png

  • Moderators

    You can switch to QGraphicsView instead of QML.

    However, staying with QML is a good idea, but you probably need to forget about QQuickPainted item. Consider using raw OpenGL instead, or the QNanoPainter: check out other blogs from this guy, a lot of performance-related information there.

    Also, this article might help you along the way.

  • @sierdzio I originally wrote this project in only C++ with raw OpenGL calls. The whole reason that I switched to Qt was for the convience that the painter offered so I really want to stick with the painter. What are the big drawback to switching to QGraphicsView at this point?

  • @j_omega "What design changes can I make to make this run smoother?

    Hi J, not an answer to your problem as such, but I'm currently reading this mind-blowing C++ book by Bob Nystrom, and it delves into such matters as shoveling polygons into the CPU and GPU. You may find it interesting.

  • Moderators

    @j_omega said in Most efficient way to approach lots of polygons in QML/C++?:

    What are the big drawback to switching to QGraphicsView at this point?

    Well, the code rewriting might be a drawback of course :-) QGraphicsView is based on widgets, not QML so it will require changes in the UI code. It also lacks some QML features like shader support, graphical effects etc.
    But it offers a lot when it comes to fine tuning the performance, and excellent support for custom shapes.

    Perhaps a good idea would be to wrtie a small test project/ benchmark with QGraphicsView, it will allow you to compare ease of maintenance, performance etc. of both solutions.

    Also, going back to your original question:

    What design changes can I make to make this run smoother?

    Here are a few general ideas on how to (potentially... I recommend checking with some benchmark) improve the performance. Some may not apply to your app:

    • make sure you only paint and keep in memory items which are visible on the screen - invisible parts of the map should be clipped
    • use lazy initialization - only load part of the scene initially, then continue loading more items only if needed
    • check out the QNanoPainter and other hints from the articles I linked before
    • use caching - this is potentially the biggest gain. For example, only paint your QPolygons in a single item once and store the result in an image. Then, when QML engine wants to paint the item, provide the image from cache instead of recalculating and repainting the whole QPainterPath
    • try to reuse components as much as possible - it looks like a lot of them are really similar so if the cache mentioned above can be shared between items, you could see even better results
    • if you use SVG images anywhere - don't :-) Rendering SVG is very slow
    • read through the official guidelines for QML performance
    • don't use QML Shape components - they are great but slow :-)
    • see if you can port some of the items to use shaders for example, so that they are painted by your GPU instead of CPU
    • try to minimize the load on QML engine - less bindings, more C++ (than JS), less timers and animations

Log in to reply

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.