We had a post about this previously as well: viewtopic.php?p=552818#p552818
It is a very complicated issue and it sometimes still comes up in my game, where I have to make special user code to fix it again.
When you have destroyed all your user content (entitys, manual objects, custom/cloned materials, etc), and that you only have the resource managers left to unload, first use this code:
Code: Select all
#define FIND_DIRECT3D11_DEBUG_RESOURCE_CRASH
#ifdef FIND_DIRECT3D11_DEBUG_RESOURCE_CRASH
// https://forums.ogre3d.org/viewtopic.php?p=552818#p552818
// Get all resources into a list
CList<ResourcePtr> tmpResources;
ResourceManager::ResourceMapIterator tmpResourceIterator = MaterialManager::getSingleton().getResourceIterator();
while (tmpResourceIterator.hasMoreElements())
{
ResourcePtr tmpResourcePtr = tmpResourceIterator.getNext();
tmpResources.Add(tmpResourcePtr);
}
ResourceManager::ResourceMapIterator tmpItr = GpuProgramManager::getSingleton().getResourceIterator();
if (tmpItr.begin() == tmpItr.end())
tmpItr = HighLevelGpuProgramManager::getSingleton().getResourceIterator();
for (ResourceManager::ResourceMapIterator::const_iterator i = tmpItr.begin(); i != tmpItr.end(); ++i)
{
const ResourcePtr tmpResourcePtr = i->second;
tmpResources.Add(tmpResourcePtr);
}
#endif
Also, make sure that all your custom meshes (that you have cloned or that you have created manually) that you have created should also before the code above be destroyed correctly, with this code to reset their materials:
Code: Select all
// Clear the material of the mesh (otherwise it can actually stay as a referense, making Direct3D11 crash on debug on exit)
for (size_t n = 0; n < resource->getNumSubMeshes(); n++)
{
SubMesh* tmpSubMesh = resource->getSubMesh(n);
tmpSubMesh->setMaterial(NULL);
}
When you have destroyed the resource groups (which should now in theory make ALL your content be unloaded), use this code:
Code: Select all
#ifdef FIND_DIRECT3D11_DEBUG_RESOURCE_CRASH
// Remove all resources with only one use count
for (int i = 0; i < tmpResources.Size(); i++)
{
ResourcePtr& tmpResource = tmpResources[i];
if (tmpResource.use_count() == 1 ||
tmpResource->getGroup() == "OgreInternal")
tmpResources.Remove(i--);
}
// The resources left here will only be the ones still in D3D11DeviceResourceManager::(~)D3D11DeviceResourceManager.
// Find them in your user code and fix them.
tmpResources.Clear(); // Debug this line here.
#endif
Debug the line where it says "Debug this line here" and see what resources are still used somewhere in your application/user code.
The CList class is only a wrapper of std::vector, and its "Add" function is the same as "push_back" and its "Remove" function is defined as this:
Code: Select all
// Removes a list element
template <class T>
void CList<T>::Remove(int listNum)
{
// Delete the list object
std::vector<T>::iterator del = m_list.begin();
del += listNum;
m_list.erase( del );
}
If I were you, I would go through the list and maybe post them here in case it might help you get rid of the RTShader resources that you mentioned were left in the other post.