Как использовать QSGGeometryNode без утечки памяти и обеспечить правильную очистку

Я использую QSGGeometry, QSGVertexColorMaterial & QSGGeometryNode нарисовать что-то в реальном времени на моем QQuickItem производный класс, который MyQuickItem Вот.

Следующее мое updatePaintNode метод, в котором заключается суть логики перекраски.

QSGNode * MyQuickItem::updatePaintNode(QSGNode * oldNode, UpdatePaintNodeData * updatePaintNodeData) {

if (!oldNode) {
oldNode = new QSGNode;
}

oldNode->removeAllChildNodes();

QSGGeometry * geometry = GetMyGeometry();
QSGVertexColorMaterial * material = new QSGVertexColorMaterial;
QSGGeometryNode * child_node = new QSGGeometryNode;

child_node->setGeometry(geometry);
child_node->setMaterial(material);
child_node->setFlag(QSGNode::OwnsMaterial);
oldNode->appendChildNode(child_node);

return oldNode;
}

Выпуск:
Выше логика работает отлично. Нет проблем с функциональностью вообще. Также нет проблем с производительностью. Но я переживаю, что вызываю утечки памяти. Посмотрите на следующие две строки в вышеупомянутом методе updatePaintNode где я размещаю сырые указатели.

QSGVertexColorMaterial * material = new QSGVertexColorMaterial;
QSGGeometryNode * child_node = new QSGGeometryNode;

Я выделяю их & Я не удаляю их. Это потому, что точка, где они должны быть удалены, после updatePaintNode отделки. И это не под моим контролем.

Вопрос:
Как я могу убедиться, что 2 указателя material & child_node правильно очищены из памяти?
Делает child_node->setFlag(QSGNode::OwnsMaterial) как я делаю выше, устанавливает владение указателями в QtSceneGraph & освободить меня от бремени удаления указателей?

Вторичный вопрос:
я использую oldNode->removeAllChildNodes() очистить данные, нарисованные в предыдущем кадре. Это хороший способ очистить предыдущие данные на экране, прежде чем рисовать новые данные?

PS:
Я повторяю: у этой реализации нет проблем с производительностью. Я просто хочу быть уверен, что я не вызываю никаких утечек памяти. Я пытался использовать material & child_node как умные указатели вроде так:

auto material = std::make_shared<QSGVertexColorMaterial>();
auto child_node = new std::make_shared<QSGGeometryNode>();

Но это вызывает сбой, когда material & child_node автоматически удаляются из памяти на более позднем этапе.

5

Решение

Да, в вашем примере кода вы можете рассчитывать на автоматическую очистку узлов. Вы не пропускаете память из updatePaintNode.

oldnode и child_node

oldnode возвращаемый из QQuickItem :: updatePaintNode () автоматически удаляется в нужном потоке в нужное время. Деревья экземпляров QSGNode управляются с помощью QSGNode :: OwnedByParent, который устанавливается по умолчанию.

материал

Потому что вы установили флаг QSGNode :: OwnsMaterial для вашего child_node material удаляется при удалении child_node.

Второй вопрос: Это хороший способ?

Ответ — нет. Нет смысла создавать и удалять узлы каждый раз при рендеринге сцены. Вместо этого вы должны повторно использовать узел / узлы. В приведенном ниже примере кода я предполагаю, что геометрия изменяется, но материал не меняется в течение времени жизни QQuickItem. Если материал изменится, вам может потребоваться позвонить node-> markDirty (QSGNode :: DirtyMaterial). Обратите внимание, что создается только один узел, и он создается только один раз (если, например, окно не скрыто, а затем возвращено в fg или что-то еще).

QSGNode * MyQuickItem::updatePaintNode(QSGNode * oldNode, UpdatePaintNodeData * updatePaintNodeData) {

QSGGeometryNode *node = static_cast<QSGGeometryNode *>(oldNode);
if (!node) {
node = new QSGGeometryNode;

QSGVertexColorMaterial * material = new QSGVertexColorMaterial;
node->setMaterial(material);
node->setFlag(QSGNode::OwnsMaterial);
}

// if GetMyGeometry returns every time a new dynamically allocated object then you should
// call node->setFlag(QSGNode::OwnsGeometry) to not leak memory here:
QSGGeometry * geometry = GetMyGeometry();
node->setGeometry(geometry);
// No need to call node->markDirty(QSGNode::DirtyGeometry) because setGeometry is called.

return node;
}
4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]