Производительность масштабирования QSGImageNode

Я пытаюсь сделать компонент 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 генерирует QImage 2000x2000 и отправляет его в MyItem, который является MyQuickItem.

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

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

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

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

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

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

texture->bind();

привет 30% ЦП снова.

Таким образом, одна проблема заключается в том, что изображение размером 2000x2000 слишком медленно загружается в GPU.

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

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

без и с bind() дает одинаковые 30% ЦП.

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

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

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

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


person ElDorado    schedule 17.05.2018    source источник


Ответы (1)


TL:DR;

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

построить QImage как

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

и заполнить его соответственно предварительно умноженным ARGB

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

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

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

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

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

person ElDorado    schedule 18.05.2018