Can't clear Ogre Scene and reclaim memory

Problems building or running the engine, queries about how to use features etc.
Post Reply
supadenz
Halfling
Posts: 41
Joined: Sat Feb 16, 2013 2:18 am
x 1

Can't clear Ogre Scene and reclaim memory

Post by supadenz »

In my application, I need to load a scene, create materials, etc etc, then *completely* remove everything to reclaim memory, then load another one. I am having a surprising amount of difficulty doing this. Basically, ogre seems to grow unbounded and I can't seem to check it.

Here is a short summation of what I am doing in my application.

1. Create a generic scene manager and set it up. This consists of something like the following (pseudocode)

Code: Select all

    sceneMgr = root->createSceneManager(ST_GENERIC, "SceneManager");
    for (int i = 0; i < resourceLocations.size(); ++i) {
        Ogre::ResourceGroupManager::getSingleton().addResourceLocation(...);
    }
    Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
2. Create a camera and viewport

Code: Select all

void createCamera(Ogre::SceneManager *sceneMgr, Ogre::RenderWindow *renderWindow)
{
        Ogre::Camera *camera = sceneMgr->createCamera(CAM_NAME);
        Ogre::Viewport *viewport = renderWindow->addViewport(camera);
        viewport->setCamera(camera);
        viewport->setBackgroundColour(Ogre::ColourValue(0.0f, 0.0f, 0.0f, 0.0f));
        viewport->setClearEveryFrame(true);

        Ogre::SceneNode* sceneNode = sceneMgr->getRootSceneNode()->createChildSceneNode();
        sceneNode->attachObject(camera);

        // ... set up camera orientaion, fov, etc etc
}
3. Read in a specific set of materials using parseScript

Code: Select all

void parseSingleMaterial(Ogre::String materialFile)
{
    Ogre::DataStreamPtr streamPtr = Ogre::ResourceGroupManager::getSingleton().openResource(materialFile);
    if (not streamPtr.isNull()) {
        Ogre::MaterialManager::getSingleton().parseScript(streamPtr, Ogre::String("MyResourceGroup"));
        streamPtr->close();
    }
}
4. Create entities with meshes, skeletons, etc. read off of .skeleton and .mesh files on disk

Code: Select all

void createSingleEntity(Ogre::SceneManager *sceneMgr, Ogre::String entityName, Ogre::String meshName)
{
    Ogre::SceneNode* sceneNode = sceneMgr->getRootSceneNode()->createChildSceneNode();
    Ogre::Entity* entity = sceneMgr->createEntity(entityName, meshName);
    sceneNode->attachObject(entity);
}
At this point things are loaded, the app is doing what i want it to do. Things are good. Now, I want to unload the scene and reclaim any memory that the scene was using to be used by other parts of the application. So..
Here is my unload code, which I have tried to make pretty boiler plate, but with no luck. Note I'm using RTSS in GLES 2.0 on iOS so I need to do the call to remove shader based techniques.

Code: Select all

   
void clearOgreScene(Ogre::SceneManager *sceneMgr, Ogre::Viewport *viewport, , Ogre::RenderWindow *renderWindow, std::vector<Ogre::Entity *>entities)
{
    Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr();
    Ogre::MaterialManager *matMgr = Ogre::MaterialManager::getSingletonPtr();
    Ogre::MeshManager *meshMgr = Ogre::MeshManager::getSingletonPtr();
    Ogre::TextureManager *textureMgr = Ogre::TextureManager::getSingletonPtr();

    // to remove an entity, detach it from it's scene node, destroy it from the scene manager, then destroy the scene node
    for (int i = 0; i < entities.size(); ++i) {
        Ogre::Entity *entity = m_entities[i];
        Ogre::SceneNode* parent = entity->getParentSceneNode();
        if (parent) {
            parent->detachObject(entity);
        }
        sceneMgr->destroyEntity(entity);
        if (parent) {
            sceneMgr->destroySceneNode(parent);
        }
    }
        
    // deal with the various managers
    skelMgr->removeAll();
    skelMgr->destroyAllResourcePools();

    meshMgr->removeAll();
    meshMgr->destroyAllResourcePools();
    
    matMgr->removeAll();
    matMgr->destroyAllResourcePools();
    
    // without this, we crash on next render
    Ogre::RTShader::ShaderGenerator::getSingleton().removeAllShaderBasedTechniques();

    textureMgr->unloadAll();
    textureMgr->removeAll();
    textureMgr->destroyAllResourcePools();

    // first, clear the render buffer without doing a frame update
    if (viewport) {
        // remove the camera as we did the entities
        Ogre::Camera *camera = viewport->getCamera();
        Ogre::SceneNode* parent = camera->getParentSceneNode();
        if (parent) {
            parent->detachObject(camera);
        }
        sceneMgr->destroyCamera(camera);
        if (parent) {
            sceneMgr->destroySceneNode(parent);
        }

        // remove the viewport
        viewport->getTarget()->removeAllListeners();
        viewport->getTarget()->removeAllViewports();
        renderWindow->removeAllViewports();
    }
    
    sceneMgr->clearScene();

    if (Ogre::ResourceGroupManager::getSingleton().resourceGroupExists("MyResourceGroup")) {
        Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup("MyResourceGroup");
    }

}    

I would expect that at some point after calling clearScene, I would be able to reclaim the memory on my system. But this is not the case. All of this, by the way, is taking place on iOS with GLES2 and RTSS, using the generic scene manager. The code to load and clear scenes is being called from:

Code: Select all

virtual bool frameEnded (const Ogre::FrameEvent &evt);
in a subclass of Ogre::FrameListener.

Let's say that my app after initializing ogre and before loading the scene is using some baseline amount of memory, call it 0.

I create the camera and viewport, parse all my materials, and rip through my entity list creating and attaching each one, per the code above. Then my app grows to +62mb.

I then call clearScene, expecting it to drop down to 0 again, but it stays at +62. Yikes. I then load the same scene, the same way, and end up at +106. clear, reload, and I'm +150. So my memory footprint grows by 62m the first time I load, and even after a clear, another 44m each consecutive time.

Do I have to destroy ResourceGroups? Root Nodes? How do I reclaim the memory ogre is using? At this point, my application is dead in the water. Can anyone provide some insight? Also, am I alone in being completely shocked that there is no single call to tear down all your resources in Ogre?
supadenz
Halfling
Posts: 41
Joined: Sat Feb 16, 2013 2:18 am
x 1

Re: Can't clear Ogre Scene and reclaim memory

Post by supadenz »

Update:

calling Ogre::Root::getSingleton().destroyRenderTarget("myTarget");

seems to cause memory to be reclaimed. However, I don't actually want to destroy the render target and set another one up again. Does anyone have any insight about something a little lighter weight I can do that will trigger the same deletion?
Lucas Ives
Gnoblar
Posts: 4
Joined: Thu Dec 05, 2013 1:14 am

Re: Can't clear Ogre Scene and reclaim memory

Post by Lucas Ives »

I'd be super-interested in the answer to this question, too -- having the same problem.
loath
Platinum Sponsor
Platinum Sponsor
Posts: 290
Joined: Tue Jan 17, 2012 5:18 am
x 67

Re: Can't clear Ogre Scene and reclaim memory

Post by loath »

any luck on this? i'd like to know as well.

thanks!
User avatar
c6burns
Beholder
Posts: 1512
Joined: Fri Feb 22, 2013 4:44 am
Location: Deep behind enemy lines
x 138

Re: Can't clear Ogre Scene and reclaim memory

Post by c6burns »

I just call SceneManager::clearScene and unload my resource groups. I haven't tested with valgrind yet, but if I'm leaking then it's not by much. Granted I have not yet checked memory usage on Android or iOS which is what the OP is asking about.
loath
Platinum Sponsor
Platinum Sponsor
Posts: 290
Joined: Tue Jan 17, 2012 5:18 am
x 67

Re: Can't clear Ogre Scene and reclaim memory

Post by loath »

c6burns wrote:I just call SceneManager::clearScene and unload my resource groups. I haven't tested with valgrind yet, but if I'm leaking then it's not by much. Granted I have not yet checked memory usage on Android or iOS which is what the OP is asking about.
thanks for pointing me in the right direction! this was a huge help.
Post Reply