重置场景时OpenSceneGraph内存使用情况
OpenSceneGraph memory usage when resetting scene
我花了很多时间试图弄清楚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_NONE
、CACHE_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。
- 任务管理器 - C/C++ 应用程序 - 分配的地址空间与已用内存
- 针对某些特定用例的C++原子内存排序
- 用C++压缩内存中的位图
- 用c++防止内存泄漏
- 内存浪费?如果main()应该只返回0或1,那么为什么main是用int而不是短int甚至char声明的
- 大约"circular reference",我用了weak_ptr但仍然发生内存泄漏
- 你能用内存反序列化字节吗?
- 使用重载的 new 和 delete 运算符跟踪已用内存
- 用C 和Marshall分配给C#的内存
- 当我用clang编译代码时,GCOV会出现内存错误
- 用多个传感器克服Arduino内存限制
- 在闭包中,如何通过存储在内存中的指针或引用类型捕获可变性或用现代函数式语言进行处理?
- CUDA:共享内存的超载以用多个数组实现还原方法
- 我可以动态分配以前分配的内存,但用不同的指针分配
- 从多个线程写入内存区域是否会导致争用?
- 用valgrind分析c++字符内存泄漏
- 为什么用空函数运行std::线程会花费大量内存
- 用new分配4k int后的内存覆盖
- 定义一个C宏并将内存地址设置为用C和C++编写的结构成员
- 除了内存管理,QObject的父级是做什么用的?