Qt 5.10 QML Shape testing
When implementing component into QtQuick UI which needs something more than rectangles, images and texts, pure declarative QML hasn't been enough. Popular choices to use for items with some sort of vector drawing are QML Canvas, QQuickPaintedItem or QNanoPainter.
But with Qt 5.10 there will be supports for new Shape element with paths that contain lines, quads, arcs etc. so I decided to install Qt 5.10 beta3 and implement all tests of "qnanopainter_vs_qpainter_demo" with also QML + Shape elements. (This kinda makes it "qnanopainter_vs_qpainter_vs_qmlshape_demo" but not renaming now). So here is in all glory the same UI implemented with QNanoPainter (left), QQuickPaintedItem (center), and QML+Shape (right):
Hard to spot the differences right? If only there would be a way to prove this, some way to x-ray into these UIs... like QSG_VISUALIZE=overdraw to visualize what Qt Quick Scene Graph Renderer sees?
Here you can see that scene graph sees QNanoPainter and QQuickPaintedItem as just big unknown rectangles, while QML+Shape it sees into as that is composed of native scene graph nodes. But proof is in the pudding as they say, what looks the same doesn't perform the same. Here's a video showing all 3 running with two different Android devices:
As different rendering components can be enabled/disabled and settings changed, this demo is quite nice for doing performance comparisons of both exact drawing methods or combining all methods. But those will have to wait for another blog post and for non-beta Qt 5.10 to get fair results. In the mean time, feel free to pull latest sources from github, test yourself and provide patches or comments!
But with Qt 5.10 there will be supports for new Shape element with paths that contain lines, quads, arcs etc. so I decided to install Qt 5.10 beta3 and implement all tests of "qnanopainter_vs_qpainter_demo" with also QML + Shape elements. (This kinda makes it "qnanopainter_vs_qpainter_vs_qmlshape_demo" but not renaming now). So here is in all glory the same UI implemented with QNanoPainter (left), QQuickPaintedItem (center), and QML+Shape (right):
Hard to spot the differences right? If only there would be a way to prove this, some way to x-ray into these UIs... like QSG_VISUALIZE=overdraw to visualize what Qt Quick Scene Graph Renderer sees?
Here you can see that scene graph sees QNanoPainter and QQuickPaintedItem as just big unknown rectangles, while QML+Shape it sees into as that is composed of native scene graph nodes. But proof is in the pudding as they say, what looks the same doesn't perform the same. Here's a video showing all 3 running with two different Android devices:
As different rendering components can be enabled/disabled and settings changed, this demo is quite nice for doing performance comparisons of both exact drawing methods or combining all methods. But those will have to wait for another blog post and for non-beta Qt 5.10 to get fair results. In the mean time, feel free to pull latest sources from github, test yourself and provide patches or comments!
Comments
But as said that's content for another blog post or curious ones to experiment themselves :)
The problem with the qpainter and qnanopainter fbo mode is, that you cannot easily mix with other quickitems. But if you do, making lots of QNanopainter items or QPaintedItems, it is becoming a lot slower. The other problem with QNanoPainter is, that it is missing a lot of features like Dashes Lines, MultiStop Gradients, no nonzero fillrule for pathes etc. which makes rendering SVG hard.
Based on my earlier experiments (see http://kgronholm.blogspot.fi/2017/03/qnanopainter-with-qt-58-and.html), QSGRenderNode performance is very similar to QQuickFramebufferObject so rendering through FBO wouldn't have big affect. But if you or anyone else have UI with many separate items and/or hardware which suffers more from FBOs, please test building QNanoPainter with QNANO_USE_RENDERNODE enabled.
And yes QNanoPainter (and NanoVG) API doesn't contain everything that QPainter (or Cairo, or Skia) has, which can be considered also a strength to keep rendering performant on OpenGL. Dashed lines with round caps e.g. can potentially multiply vertices count and shaders complexity. Multi-stop gradients on the other hand might be coming soonish, see https://github.com/memononen/nanovg/pull/430
About QML API for QNanoPainter: No I haven't tried to implement anything like that. It would have some overhead from JavaScript, shouldn't be too much. But many use cases contain some graphs or similar where getting related data into QML side would also add some overhead. Instead of moving drawing coding into QML/JavaScript I would rather improve productivity in other ways and keep final code as performant C++ as possible.
But this does give me some fresh thoughts, thanks for commenting!
Keep up the good work.
For QPainter (raster paint engine) it must be noted that the results are heavily dependent on the size of the backing QQuickPaintedItem, e.g. in a quick test on Windows the test app dropped from 32 fps to 8 fps when maximizing the window (on a 1080p screen). The other two approaches are a lot more immune to this.
It would be interesting to see results from other platforms and devices. I tried the test app on Windows (debug build and ANGLE, none of which is ideal), and the results were somewhat different when it comes to Shapes vs. QNanoPainter, see here: https://github.com/QUItCoding/qnanopainter/issues/19
BTW is there a way to get QNanoPainter use OpenGL proper on Windows (which would need going through some GL function resolver in NanoVG)? Right now things seem to be hardcoded to link to libGLESv2 from ANGLE directly.
@Laszlo Thanks for testing! As said I personally haven't really been testing on Windows side, so maybe someone else can help there. But I plan to blog about results on different platforms, probably once 5.10 RC is out.
After going through the demo a bit, it seems that the default setup is not quite fair in the sense that "antialiasing" maps to NVG_ANTIALIAS for NanoVG (just enables feather-based AA, still a normal FBO), while for Shapes it toggles the heavyweight 4x MSAA. On high resolution screens this won't be acceptable with middle-low HW.
Full story in https://bugreports.qt.io/browse/QTBUG-64951
I will write some comment also into bug report, thanks!
Cheers,
Laszlo