How to improve a QQuickItem's rendering performance?

88 views Asked by At

I am trying to develop a QML app that renders a lot of triangles.

Right now I'm trying to render 200000. My graphics card is RTX 2060, it should be able to render like millions of triangles at 60fps, yet my application struggles with 200000 triangles and I get like 10 fps.

I know it's GPU bound because my CPU usage is very low and GPU usage is at 100 percent all the time.

Here is the code I'm using:

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickWindow>
#include "DenemeClass.h"

int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
    QGuiApplication app(argc, argv);

    qmlRegisterType<DenemeClass>("com.deneme", 1, 0, "DenemeClass");

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
        &app, [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

DenemeClass.h

#ifndef DENEMECLASS_H
#define DENEMECLASS_H
#include <QQuickItem>

class DenemeClass : public QQuickItem
{
    Q_OBJECT
public:
    DenemeClass(QQuickItem* parent = nullptr);
    QSGNode* updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData* data) override;
    int64_t lastDraw;
};

#endif // DENEMECLASS_H

DenemeClass.cpp

#include "DenemeClass.h"
#include <QSGGeometryNode>
#include <QSGFlatColorMaterial>
#include <QSGGeometry>
#include <iostream>
DenemeClass::DenemeClass(QQuickItem* parent)
    : QQuickItem(parent)
{
    setFlag(ItemHasContents, true);
}

QSGNode* DenemeClass::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData* data){

    int64_t draw_t = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
    std::cout << (1000.0 / double(draw_t - lastDraw)) << "FPS" << std::endl;
    lastDraw = draw_t;

    const int rectCount = 100000;

    QSGGeometryNode* node = reinterpret_cast<QSGGeometryNode*>(oldNode);
    if(!node){
        node = new QSGGeometryNode();
        node->setFlag(QSGNode::OwnsMaterial, true);
        node->setFlag(QSGNode::OwnsGeometry, true);
        QSGFlatColorMaterial* material = new QSGFlatColorMaterial;
        material->setColor("#ff0000");
        node->setMaterial(material);

        QSGGeometry* geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), rectCount * 6, 0, QSGGeometry::UnsignedIntType);
        geometry->setDrawingMode(QSGGeometry::DrawTriangles);
        node->setGeometry(geometry);


        QSGGeometry::Point2D* pts = geometry->vertexDataAsPoint2D();

        for(int i = 0; i < rectCount; ++i){
            pts[i * 6 + 0].x = 0;
            pts[i * 6 + 0].y = 0;

            pts[i * 6 + 1].x = 0;
            pts[i * 6 + 1].y = height();

            pts[i * 6 + 2].x = width();
            pts[i * 6 + 2].y = height();

            pts[i * 6 + 3].x = width();
            pts[i * 6 + 3].y = height();

            pts[i * 6 + 4].x = width();
            pts[i * 6 + 4].y = 0;

            pts[i * 6 + 5].x = 0;
            pts[i * 6 + 5].y = 0;

        }
    }
    return node;
}


main.qml

import QtQuick 2.15
import QtQuick.Window 2.15
import com.deneme 1.0
Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    property double xx: 0
    NumberAnimation on xx{
        running: true
        loops: Animation.Infinite
        from: 0
        to: 100
        duration: 2000
    }

    Rectangle{
        anchors.fill: parent
        color: "yellow"
        anchors.margins: xx
    }

    DenemeClass{
        anchors.fill: parent
        anchors.margins: xx
    }
}

I tried changing OpenGL backend with QCoreApplication::setAttribute(Qt::AA_UseOpenGLES); but no luck.

What can I do to increase performance?

0

There are 0 answers