[英]How to use QSGGeometryNode without causing a memory leak and ensure correct clean up
我使用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
时,这会导致崩溃。
是的,在您的示例代码中,您可以依赖节点的自动清理。 您没有从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.