[SOLVED] Crash on "new game"

Jules Robichaud Gagnon

22-11-2007 15:05:57

09:48:49: OGRE EXCEPTION(4:ItemIdentityException): Resource with the name SpriteFade_vp already exists. in ResourceManager::add at d:\documents and settings\jules\bureau\ogre-win32-v1-4-5\ogrenew\ogremain\src\ogreresourcemanager.cpp (line 113)


Line 165 in StaticBillboardSet.cpp

I call the destructor of Paged Geometry properly but on the 2nd run it dies here.

HighLevelGpuProgramPtr vertexShader2 = HighLevelGpuProgramManager::getSingleton()
.createProgram("SpriteFade_vp",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_VERTEX_PROGRAM);
vertexShader2->setSource(vertexProg2);
vertexShader2->setParameter("profiles", "vs_1_1 arbvp1");
vertexShader2->setParameter("entry_point", "SpriteFade_vp");
vertexShader2->load();



I use Ogre 1.4.5.




if (--selfInstances == 0){
//Delete fade materials
fadedMaterialMap.clear();

//Remove vertex shaders
HighLevelGpuProgramManager::getSingleton().remove("Sprite_vp");
HighLevelGpuProgramManager::getSingleton().remove("SpriteFade_vp");
}


This code is called but it does not seem to really destroy it.

Jules Robichaud Gagnon

22-11-2007 15:29:59

I tried to replace the creation by this but it never goes in the "if".

HighLevelGpuProgramPtr vertexShader2;
if ( HighLevelGpuProgramManager::getSingleton().resourceExists( "SpriteFade_vp" ) )
{
vertexShader2 = HighLevelGpuProgramManager::getSingleton().getByName( "SpriteFade_vp" );
}
else
{

vertexShader2 = HighLevelGpuProgramManager::getSingleton()
.createProgram("SpriteFade_vp",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_VERTEX_PROGRAM);
vertexShader2->setSource(vertexProg2);
vertexShader2->setParameter("profiles", "vs_1_1 arbvp1");
vertexShader2->setParameter("entry_point", "SpriteFade_vp");
vertexShader2->load();
}


It will crash at this line.

vertexShader2->load();

Jules Robichaud Gagnon

22-11-2007 18:07:49


//Update material reference list
if (!materialPtr.isNull()) SBMaterialRef::removeMaterialRef(materialPtr);
if (!fadeMaterialPtr.isNull()) SBMaterialRef::removeMaterialRef(fadeMaterialPtr);


in ~StaticBillboardSet

I believe it should be more something like clearAllMaterialRef because it may not have only 1 left.

The problem stops if i set the "fade" transition to 0.

Jules Robichaud Gagnon

22-11-2007 18:12:37

I also noticed SBMaterialRef::addMaterialRef ...

} else {
//Material does not exist in selfList - add it
matRef = new SBMaterialRef(mat);
selfList[mat] = matRef;
}

... and SBMaterialRef::removeMaterialRef ...
if (--matRef->refCount == 0){
delete matRef;
selfList.erase(it);
}


... are called every frame several times. Is that normal?

JohnJ

23-11-2007 15:29:16

(Sorry I was away yesterday.) I'll check it out now and try to find what's going wrong with the material references.

JohnJ

23-11-2007 16:24:12

Ok, try the CVS, it should be fixed now.

This is what I think was happening: When destroying PagedGeometry, it of course deletes all ImpostorPage's, which deletes all StaticBillboardSet objects. When ImpostorPage deletes it's StaticBillboardSet instance(s), the materials and shaders are still in use, as far as Ogre knows, so the shaders can't be deleted. The problem was that StaticBillboardSet assumed that calling HighLevelGpuProgramManager::remove() would always delete the shaders, which was wrong. Consequently, the next time a StaticBillboardSet object was created, the refCount indicated that it needed to reload the shaders, which was also wrong, causing the error which reported that the shaders already exist.

I fixed the problem by simply changing the shader loader to check if the shader exists before attempting to load it. I also found that for some reason there were issues even after I added this code because the calls to HighLevelGpuProgramManager::remove() were somehow causing a state where Ogre would report that a shader doesn't exist, yet trying to load it would throw an exception which reports the shader does already exist. That was easily solved by removing the calls to HighLevelGpuProgramManager::remove(); there's really no reason to force Ogre to unload the shaders prematurely anyway.

P.S. Regarding addMaterialRef() and removeMaterialRef() being called every frame, I found that this is because impostors have their materials swapped often (in the case of a new impostor tile being selected, or when entering/exiting a fade zone), and every time a StaticBillboardSet has a new material applied, it has to remove one reference count of the old one and add one reference count of the new one.

I wish I could avoid this, but some way or another a set of all materials which use the billboard shaders is needed in order for their shader parameters to be updated each frame.

Jules Robichaud Gagnon

23-11-2007 18:05:54

Geez, thanks. That was fast. :shock:

You could make an "Example" with a new game button where it flush everything and reload it again. Would be easier for other people to cause that kind of bug. For us, it is essential everything works again on a 2nd run. :lol:

Jules Robichaud Gagnon

23-11-2007 18:11:10

I just finished to try it. It works. :D