PsoCacheHelper

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


Arth
Gnoblar
Posts: 12
Joined: Sun Dec 22, 2013 9:42 am
x 2

PsoCacheHelper

Post by Arth »

Hello,

i'm currently looking at the CEGUI-OgreRenderer and dedected problem with PsoCacheHelper (i'm using Ogre 2.1 branch but i have not found any updates to it in later branches which could solve this issue).

CEGUI uses the PsoCacheHelper like in the example in OgrePsoCacheHelper.h:

Code: Select all

Usage (example) "OK":
            PsoCacheHelper psoCache( renderSystem ); //Save this variable (i.e. per class)

            void render()
            {
                psoCache.clearState();
                psoCache.setRenderTarget( renderTarget );
                for( int i=0; i<numMaterials; ++i )
                {
                    psoCache.setMacroblock( material[i].macroblock );
                    psoCache.setBlendblock( material[i].blendblock );
                    psoCache.setVertexShader( material[i].vertexShader );
                    psoCache.setPixelShader( material[i].pixelShader );
                    for( int j=0; j<numThingsToRenderPerMaterial; ++j )
                    {
                        v1::RenderOperation renderOp = renderables[j].renderOp;
                        //Consider caching 'vertexElements' somewhere as
                        //convertToV2 involves allocations
                        VertexElement2VecVec vertexElements = renderOp.vertexData->
                                vertexDeclaration->convertToV2();
                        psoCache.setVertexFormat( vertexElements,
                                                  renderOp.operationType,
                                                  enablePrimitiveRestart );

                        HlmsPso *pso = psoCache.getPso();
                        renderSystem->_setPipelineStateObject( pso );
                    }
                }
            }
The problem is that everytime "HlmsPso* PsoCacheHelper::getPso(void)" is called to get a cached Pso and PsoCacheHelper::mLastPso was set to NULL because of a change to current state (i.e. by calling PsoCacheHelper::setRenderTarget),
"uint32 PsoCacheHelper::getRenderableHash(void)" fails to find an already used "setting/state" and incorrectly creates a new entry.
After some runtime of the application this issue causes an extremly large amount of pso created and cached, causing an extreme slowdown and in the end a crash of the application because the memory is full.

If i update "getRenderableHash" as following the issue seams to be solved and only in total 1 entry in mRenderableCache is created during runtime:

Code: Select all

uint32 PsoCacheHelper::getRenderableHash(void)
{
        RenderableCacheEntry entry;
        entry.psoRenderableKey = mCurrentState;
       
	RenderableCacheEntryVec::iterator itor;
	for(itor = mRenderableCache.begin(); itor != mRenderableCache.end(); ++itor)
	{
		if(entry.psoRenderableKey.equalExcludePassData(itor->psoRenderableKey))
			return itor->hashToMainCache;
	}
	//nothing found in cache, create new entry
	entry.hashToMainCache = mRenderableHashCounter++;
	const size_t idx = itor - mRenderableCache.begin();
	mRenderableCache.insert(itor, 1u, entry);
	itor = mRenderableCache.begin() + idx;
	return itor->hashToMainCache;
}
This is the actual Ogre 2.1 code (which makes the problem):

Code: Select all

uint32 PsoCacheHelper::getRenderableHash(void)
    {
        RenderableCacheEntry entry;
        entry.psoRenderableKey = mCurrentState;
       
	RenderableCacheEntryVec::iterator itor = std::lower_bound( mRenderableCache.begin(),
                                                                  mRenderableCache.end(), entry );

	if(itor == mRenderableCache.end() ||
		itor->psoRenderableKey.equalExcludePassData(entry.psoRenderableKey))  
	{
		entry.hashToMainCache = mRenderableHashCounter++;
		const size_t idx = itor - mRenderableCache.begin();
		mRenderableCache.insert(itor, 1u, entry);
		itor = mRenderableCache.begin() + idx;
	}
	return itor->hashToMainCache;
    }

Any idea? Have i missed a later fix for this which can be back-ported? or is this really a bug?