Производительность шкалы QSGImageNode - PullRequest
0 голосов
/ 17 мая 2018

Я пытаюсь создать компонент QML, который бы выводил в реальном времени и масштабировал изображение 2000x2000 при 60 кадрах в секунду.

Я закончил с пользовательским QQuickItem, так как QQuickImageProvider, похоже, предназначен для других целей, а QQuickPaintedItem не дал мне желаемой производительности.

Итак, у меня есть:

MyQuickItem.cpp

MyQuickItem::MyQuickItem(QQuickItem *parent)
    : QQuickItem(parent)
{
    setFlag(ItemHasContents, true);
}

void MyQuickItem::setImage(QImage image)
{
    if (!image.isNull()) {
        currentImg = image;
        update();
    }
}

QSGNode* MyQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
{
    QSGImageNode * node;
    if (!oldNode) {
        node = window()->createImageNode();
        oldNode = node;
    } else {
        node = static_cast<QSGImageNode *>(oldNode);
    }

    QSGTexture *texture = window()->createTextureFromImage(currentImg);

    node->setRect(boundingRect());
    node->setSourceRect(QRectF(QPointF(0.0, 0.0), texture->textureSize()));
    node->setTexture(texture);
    node->setOwnsTexture(true);

    return node;
}

Регистрация этого как

qmlRegisterType<MyQuickItem>("MyItem", 1, 0, "MyItem");

QQmlComponent* component = new QQmlComponent(engine, ":/test.qml");
MyQuickItem* myItem = quickItem->findChild<MyQuickItem*>("myItem");
if (myItem ) {
    connect(this, &ImageGenerator::newFrame, radarItem, &MyQuickItem::setImage);
}

и создание в QML:

import MyItem1.0
import QtQuick 2.3

Item {
    MyItem{
        id: myImage
        objectName: "myItem"
        visible: true
        anchors.fill: parent
        anchors.centerIn: parent
    }

    Rectangle {
        id: boundingRect
        border.color: "blue"
        border.width: 3
        color: "transparent"
        anchors.fill: parent
    }
    anchors.fill: parent
}

У меня это работает. ImageGenerator создает 2000x2000 QImage и отправляет его в MyItem, который является MyQuickItem.

И это все еще очень медленно. Он потребляет около 30% от i5-4460 и «замораживает» другие компоненты пользовательского интерфейса.

Исследование:

Изменение QSGImageNode на QSGRectangleNode со сплошным цветом, но все еще выполняется

QSGTexture *texture = window()->createTextureFromImage(currentImg);

уменьшить загрузку процессора до 1-3%.

Но как только я добавлю

texture->bind();

снова 30% процессорного времени.

Итак, одна проблема в том, что изображение 2000x2000 слишком медленно для загрузки в графический процессор.

С другой стороны

QSGTexture *texture = window()->createTextureFromImage(currentImg.scaled(boundingRect().size().toSize())); 

без и с bind () дает те же 30% ЦП.

другая проблема в том, что масштабирование 2000x2000 для соответствия размеру компонента QML на ЦП слишком медленное.

Есть ли возможность уменьшить это отвратительное потребление ресурсов процессора?

P.S. Я не могу сгенерировать QImage с другим размером, но могу использовать указатель для буфера, чтобы сгенерировать изображение.

Первоначально этот генератор изображений использовался в QWidget, и таких проблем не было: QImage был создан 2000x2000 и установлен в качестве изображения для QWidget. Такое же потребление ресурсов процессора составило 2-3%.

1 Ответ

0 голосов
/ 18 мая 2018

TL: DR;

Частичное решение:

создайте QImage как

m_pImage = new QImage( width, height, QImage::Format_ARGB32_Premultiplied );

и заполните его соответствующим образом умноженным ARGB

Исследование:

Анализ выходных данных с помощью QSG_RENDER_TIMING = 1 набор переменных среды. Я обнаружил, что поток графического интерфейса пользователя блокировался на 60 мс каждый кадр, просто ожидая синхронизации.Время преобразования изображения составляло 45 мс, а загрузка - всего 15 мс.

Здесь Я обнаружил, что если исходное изображение не является Format_RGB32 или Format_ARGB32_Premultiplied, оно будет преобразовано в Format_ARGB32_Premultiplied.

Послеизменив исходное изображение на Format_ARGB32_Premultiplied У меня поток графического интерфейса заблокирован только на 1 мс, конвертировать 0 мс и загрузить за те же 15 мс.

Он по-прежнему потребляет 30% ресурсов ЦП (почему IDK), но по крайней мере у меня его больше нет, это зависает на элементах пользовательского интерфейса.

...