Граф сцены Qt Рендеринг определенных дочерних узлов - PullRequest
0 голосов
/ 17 сентября 2018

Я пытаюсь добиться рендеринга графа с использованием графа сцены Qt.При рендеринге графика всегда происходит обновление для определенного столбца пикселей (пикселей в одном вертикальном столбце), поэтому я создал n дочерних узлов (QSGNode) для корневого узла (здесь n - ширина области визуализации)и для каждого из этих дочерних узлов я создал 6 дочерних узлов (QSGGeometryNode в режиме рисования GL_LINES), по одному для каждого графика на экране.В основном, если ширина области рендеринга равна 100, корневой узел будет иметь в общей сложности 100 * 6 дочерних узлов.Обновление происходит только на небольшом количестве дочерних узлов, после обновления геометрии я помечаю узел как DirtyGeometry.

Выглядит хорошо для меня, пока здесь, но я вижу, что это занимает много процессора, поэтому я попытался отладить с помощью QSG_RENDERER_DEBUG = render, я вижу, что все дочерние узлы отрисовываются снова свызов updatePaintNode вместо определенных, которые я пометил как грязные.

Журнал выглядит следующим образом

Renderer::render() QSGAbstractRenderer(0xf9a5a0) "rebuild: none"
Rendering:
-> Opaque: 6145 nodes in 2 batches...
-> Alpha: 0 nodes in 0 batches...
- 0xf9a910 [  upload] [noclip] [opaque] [  merged]  Nodes: 6144  
Vertices: 12288  Indices: 12288  root: 0x0
- 0xf9a960 [retained] [noclip] [opaque] [  merged]  Nodes:    1  
Vertices:     4  Indices:     6  root: 0x0
-> times: build: 0, prepare(opaque/alpha): 0/0, sorting: 0, 
upload(opaque/alpha): 0/0, render: 0

Область рендеринга - 1024 * 624 (т.е. 1024 * 6 = 6144 дочерней QSGGeometryузлы).

QSGNode *QSGPlot::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
{
    QSGGeometry *geometry = nullptr;
    QSGNode* parentNode = nullptr;
    if (!oldNode)
    {
        Q_ASSERT (_wfGenerator == nullptr);
        float pixelWidth, pixelHeight;
        DisplayInfo::getPixelSize(pixelWidth,pixelHeight);
        const QRectF bounds = boundingRect();
        float speed = 50.0f;
        float gain = 10.0f;
        _wfGenerator = new WFGenerator(pixelWidth,pixelHeight, speed,gain,bounds.width(),bounds.height());
        parentNode = new QSGNode;
        for (size_t columnI = 0; columnI < bounds.width(); columnI++)
        {
            QSGNode *columnNode = new QSGNode;
            parentNode->appendChildNode(columnNode);
            createGeometryChildNodes(columnNode, Qt::green, 6);
        }
    }
    else
    {
        parentNode = static_cast<QSGGeometryNode*>(oldNode);
        Q_ASSERT (parentNode->childCount() == boundingRect().width());
    }

    size_t dirtyColumnCount = 0;
    _wfGenerator->generateWF(_columnBuffer, dirtyColumnCount);
    for (size_t dirtyColI = 0; dirtyColI < dirtyColumnCount; dirtyColI++)
    {
        size_t updateCol = _columnBuffer[dirtyColI].columnI;
        QSGNode *columnNode = static_cast<QSGNode*>(parentNode->childAtIndex(updateCol));

        if (_columnBuffer[dirtyColI].validDirtyYCoordinates != 0)
        {
            Q_ASSERT (columnNode->childCount() >= _columnBuffer[dirtyColI].validDirtyYCoordinates);
            for (auto rowI = 0; rowI < _columnBuffer[dirtyColI].validDirtyYCoordinates; rowI++)
            {
                QSGGeometryNode *rowNode = static_cast<QSGGeometryNode*>(columnNode->childAtIndex(rowI));
                geometry = rowNode->geometry();
                geometry->vertexDataAsPoint2D()[0].set(updateCol, _columnBuffer[dirtyColI].dirtyYCoordinates[rowI].y);
                geometry->vertexDataAsPoint2D()[1].set(updateCol, _columnBuffer[dirtyColI].dirtyYCoordinates[rowI].y1);
                rowNode->markDirty(QSGNode::DirtyGeometry);
            }
        }
        else
        {
            for (auto rowI = 0; rowI < columnNode->childCount(); rowI++)
            {
                QSGGeometryNode *rowNode = static_cast<QSGGeometryNode*>(columnNode->childAtIndex(rowI));
                geometry = rowNode->geometry();
                geometry->vertexDataAsPoint2D()[0].set(updateCol, 0);
                geometry->vertexDataAsPoint2D()[1].set(updateCol, 0);
                rowNode->markDirty(QSGNode::DirtyGeometry);
            }
        }
    }
    return parentNode;
}

void QSGPlot::createGeometryChildNodes(QSGNode *parent, const QColor &color, const size_t &childCount)
{
    for (size_t childI = 0; childI < childCount; childI++)
    {
        QSGGeometryNode *childNode = new QSGGeometryNode;
        QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 2);
        geometry->setLineWidth(1);
        geometry->setDrawingMode(GL_LINES);
        childNode->setGeometry(geometry);
        childNode->setFlag(QSGNode::OwnsGeometry);
        QSGFlatColorMaterial* material = new QSGFlatColorMaterial();
        material->setColor(color);
        childNode->setMaterial(material);
        childNode->setFlag(QSGNode::OwnsMaterial);
        parent->appendChildNode(childNode);
    }
}

Может кто-нибудь указать, что я делаю неправильно в этой реализации. Найти экранную запись приложения можно здесь.

...