I have narrowed down the general cause of the problem:
- The multiple submeshes of my mesh all share a common vertex buffer and the deletion logic is attempting to destroy the same vertex buffer more than once (which ends badly)
In my app, I need to create the mesh and its submeshes on the fly because the vertices and materials change based on data that is created within my app.
I would welcome any advice regarding how I can share a single set of vertices between submeshes. Below is a description of how the crash occurs.
At the end of this post is code showing how I allocate my submeshes.
The crash occurs as follows
In my code, I call unload to delete the mesh.
Code: Select all
pMyMesh->unload();
Which leads to a call to Mesh::unloadImpl()
Mesh::unloadImpl has a loop to delete my submeshes
Code: Select all
void Mesh::unloadImpl()
{
// Teardown submeshes
..
while( itor != end )
OGRE_DELETE *itor++;
The destructor for SubMesh calls destroyVaos
Code: Select all
//-----------------------------------------------------------------------
SubMesh::~SubMesh()
{
destroyShadowMappingVaos();
destroyVaos( mVao[VpNormal], mParent->mVaoManager );
}
I stepped through the loop and it appears to work fine for the first submesh. Both the vertex buffer and the index buffer for the first submesh are deleted.
Code: Select all
void SubMesh::destroyVaos( VertexArrayObjectArray &vaos, VaoManager *vaoManager,
bool destroyIndexBuffer )
{
But, on return from the first call to destroyVaos, the next call to OGRE_DELETE *itor++; in the mesh destructor leads to a second call to destroyVaos which leads to second call to destroy the same vertex buffer. The vertex buffer has already been deleted, which leads to a crash. The SubMesh:destroyVaos logic has a vector to keep track of buffers that have already been deleted within that submesh. But, in my case, I have a mesh that contains multiple submeshes which share a vertex buffer, so this logic does not kick in.
Below is a description of how I allocate the mesh
My mesh uses a single big set of vertices in a vertex buffer, which I create with the following calls:
Code: Select all
// Create a single big list of vertices that will be shared by all submeshes
MeshVertexWithColor *cubeVertices = reinterpret_cast<MeshVertexWithColor*>(OGRE_MALLOC_SIMD(
sizeof(MeshVertexWithColor) * NumVerticies,
Ogre::MEMCATEGORY_GEOMETRY));
.. code to copy vertex values into cubeVertices
//Create the actual vertex buffer.
vertexBuffer = vaoManager->createVertexBuffer(vertexElements, NumVerticies,
partialMesh ? Ogre::BT_DEFAULT :
Ogre::BT_IMMUTABLE,
cubeVertices, false);
Code: Select all
Ogre::SubMesh *subMesh;
subMesh = pTheMesh->createSubMesh();
//Now the Vao
Ogre::VertexBufferPackedVec vertexBuffers;
vertexBuffers.push_back(vertexBuffer);
Ogre::IndexBufferPacked *indexBuffer = createIndexBuffer(*SubMeshIndexList); //Create the actual index buffer
Ogre::VertexArrayObject *vao = vaoManager->createVertexArrayObject(
vertexBuffers, indexBuffer, Ogre::OT_TRIANGLE_LIST);
//Each Vao pushed to the vector refers to an LOD level.
//Must be in sync with mesh->mLodValues & mesh->mNumLods if you use more than one level
subMesh->mVao[Ogre::VpNormal].push_back(vao);
//Use the same geometry for shadow casting.
subMesh->mVao[Ogre::VpShadow].push_back(vao);
subMesh->setMaterialName(MaterialNa