重置场景时OpenSceneGraph内存使用情况

OpenSceneGraph memory usage when resetting scene

本文关键字:内存 用情 情况 OpenSceneGraph      更新时间:2023-10-16

我花了很多时间试图弄清楚OSG的内存管理。我有一个包含几个子对象的场景图(实际上是基于八叉树的LOD)。

然而,当我需要重置我的场景时(我只想从场景中擦除所有节点,同时也擦除内存),我使用

// Clear main osg::Group root node
m_rootNode->removeChildren(0, m_rootNode->getNumChildren());
m_rootNode->dirtyBound();
// Clear Main view scene data from osg::Viewer
m_viewer->setSceneData(nullptr);

在我这样做之前,我用NodeVisitor模式检查了我的所有节点,发现所有节点的引用计数都为1,也就是说,在将它们从场景中清除后,我希望我的内存能够被释放。然而,这并没有发生:我的场景实际上被重置了,所有节点都从查看器中消失了,但内存仍然被占用。

尽管如此,当我将另一个场景加载到查看器时,内存会以某种方式被重写(即,内存使用量不会增加,因此没有内存泄漏,但使用的内存始终相同)

我不能有这种行为,因为我需要严格控制内存的使用。我该怎么做?

看起来OSG会将数据的缓存实例保存为CPU端或GPU端对象。

您可以首先查看osgDB禁用缓存的选项(CACHE_NONECACHE_ALL & ~CACHE_ARCHIVES),但这实际上会增加内存消耗,因为数据可能不会被多次重复使用和加载。

您可以指示osg::Texture在上传到OpenGL后释放CPU端的纹理数据,以防您不再需要它。这可以通过osgUtil::Optimizer::TextureVisitor方便地完成,您希望设置它来将每个纹理的AutoUnref更改为true。我认为,使用OPTIMIZE_TEXTURE_SETTINGS运行osgUtil::Optimizer可以达到同样的效果。

然后,在关闭你的场景后,就像你在Question的代码中所做的那样,你可以明确地指示OSG的数据库寻呼机擦除它的缓存:

for( osgViewer::View v in AllYourViews )
{
    v->getDatabasePager()->cancel();
    v->getDatabasePager()->clear();
}

为了最终消除所有预先分配的GPU端对象及其CPU端表示,您需要销毁视图和GLContext。