I apologize for my bad english =).
Earlier, I drew attention to the UB's with multi-scene manageres.
But now, I have used only one scene and periodically my app crashes. I understand what is the actual cause of crash, I think..
Look at Ogree::OgrePass.cpp
Code: Select all
Pass& Pass::operator=(const Pass& oth)
{
mName = oth.mName;
mHash = oth.mHash; // <---------- it's very interesting (that hide UB)
mAmbient = oth.mAmbient;
//
// bla-bla-bal
//
_dirtyHash(); // <----------- it's very interesting to, but does not matter =) (hash was changed earlier and see below)
return *this;
}
Suppose in the previous frame, an object was placed in one of QueuedRenderableCollection :: mGruped and has not been marked as dirty (give it a some name - pass1)
Next frame starts executing my listner frameStarted which comprises the following code
Code: Select all
// bla-bla-bal
auto pass2 = someMaterial->getBestTechnique(0)->getPass(0) ;
*pass1 = *pass2;
// bla-bla-bal
I walked around this problem with the following code:
Code: Select all
void _forceClearWorkGroupFromDirtyPasses()
{
Ogre::Root* m_Root = Ogre::Root::getSingletonPtr();
if (m_Root && (!Ogre::Pass::getDirtyHashList().empty() || !Ogre::Pass::getPassGraveyard().empty()))
{
Ogre::SceneManagerEnumerator::SceneManagerIterator scenesIter = m_Root->getSceneManagerIterator();
while (scenesIter.hasMoreElements())
{
Ogre::SceneManager* pScene = scenesIter.getNext();
if (pScene)
{
Ogre::RenderQueue* pQueue = pScene->getRenderQueue();
if (pQueue)
{
Ogre::RenderQueue::QueueGroupIterator groupIter = pQueue->_getQueueGroupIterator();
while (groupIter.hasMoreElements())
{
Ogre::RenderQueueGroup* pGroup = groupIter.getNext();
if (pGroup)
pGroup->clear(false);
}
}
}
}
}
}
void assignmentOgrePasses(Ogre::Pass * _lPass, Ogre::Pass * _rPass)
{
assert(_lPass && _rPass);
// prepare passes for re-calculate hash
_lPass->_dirtyHash();
_rPass->_dirtyHash();
_forceClearWorkGroupFromDirtyPasses();
// assign
*_lPass = *_rPass;
// call recalculate dirty hashes
Ogre::Pass::processPendingPassUpdates();
}
//
// bla-bla-bal ....
//
auto pass2 = someMaterial->getBestTechnique(0)->getPass(0) ;
assignmentOgrePasses(pass1 , pass2)
// bla-bla-bal