繁体   English   中英

如何使用QSGGeometryNode而不会导致内存泄漏并确保正确清理

[英]How to use QSGGeometryNode without causing a memory leak and ensure correct clean up

我使用QSGGeometryQSGVertexColorMaterialQSGGeometryNode在我的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个指针materialchild_node
像我上面那样做一个child_node->setFlag(QSGNode::OwnsMaterial)是否设置了指向 QtSceneGraph 的指针所有权并减轻了删除指针的负担?

次要问题:
我使用oldNode->removeAllChildNodes()来清除前一帧中绘制的数据。 这是在绘制新数据之前清除屏幕上先前数据的好方法吗?

PS:
我重申:此实现没有性能问题。 我只是想确定我没有造成任何内存泄漏。 我尝试使用materialchild_node作为智能指针,如下所示:

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

但是,当稍后从内存中自动清除materialchild_node时,这会导致崩溃。

是的,在您的示例代码中,您可以依赖节点的自动清理。 您没有从updatePaintNode泄漏内存。

oldnode和child_node

oldnode从QQuickItem :: updatePaintNode()在正确的时间正确的线程上自动删除返回。 通过使用默认设置的QSGNode :: OwnedByParent来管理QSGNode实例的树。

材料

因为已为child_node设置了标志QSGNode :: OwnsMaterial,所以删除child_node时将删除该material

第二个问题 :这是一个好方法吗?

答案是不。 每次渲染场景时都没有创建和删除节点的意义。 相反,您应该重用节点/节点。 在下面的示例代码中,我假设几何体发生了变化,但材料在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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM