The original testcase can be simplified and corrected a bit. The end result is the following...
Code: Select all
#include <irrlicht.h>
using namespace irr;
#ifdef _MSC_VER
# pragma comment(lib, "Irrlicht.lib")
#endif
int main()
{
// let user select driver type
video::E_DRIVER_TYPE driverType = video::EDT_OPENGL;
IrrlichtDevice* device = createDevice(driverType,
core::dimension2d<u32>(800, 600));
if (!device)
return 1;
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(0,100.0f,5.2f);
camera->setFarValue(52000.0f);
for (u32 i = 0; i < 500; ++i)
{
scene::ISceneNode* node = smgr->addTerrainSceneNode(
"../../media/irrlichtlogo.jpg");
if (driver->beginScene(true, true, 0))
{
smgr->drawAll();
driver->endScene();
}
node->remove();
}
device->drop();
return 0;
}
I traced it down to the
drawMeshBuffer() call in
CTerrainSceneNode::render(). As it turns out, a
SHWBufferLink is getting allocated for the terrain mesh data and inserted into the
HWBufferMap. The entry is never removed from the
HWBufferMap.
There are several possible workarounds. The easiest is to remove the
SHWBufferLink entry for the terrain node when removing it from the scene. There is a chance that the buffer will be needed later if the
remove() call doesn't delete the node, but the
SHWBufferLink will be recreated if necessary.
Code: Select all
driver->removeHardwareBuffer(node->getRenderBuffer());
node->remove();
Another option would be to disable VBO for the terrain node render buffer. That would probably be bad for performance. The final option is to call
driver->updateAllHardwareBuffers() which will eventually deallocate buffers that have not been used for a while**.
It seems like the the mesh buffers that are VBO enabled need to be sure to remove themselves when they are being destroyed. Since the data is no longer valid, it makes no sense for the VBO entry to exist any longer. Unfortunately, this would require that each mesh buffer would need to keep track of the driver that contains the VBO. This is not a great solution. Another option would be to require all users of
IMeshBuffer be sure to remove the
SHWBufferLink for the buffers that have been dropped for the last time.
I'm not sure what the best fix is, but it seems that the design of the VBO requires the user to think more about cleaning up resources, and this is going to be problematic and frustrating for users.
Travis
** The
updateAllHardwareBuffers() function only cleans up meshes that have not been used more than 20000 calls to that function. That means that periodic calls to that function will fail to unload the VBO data in a reasonable amount of time (1 call per second would require the mesh to be unsed for 5.55 hours). IMO, this method should also take a parameter that is the maximum age of a VBO before it is deleted. There should also be a flag indicating that a VBO should never be removed automatically.