Patch Notes:
Updated to using a reference based system instead that keeps track of all active and inactive depth buffers.
When the reference is 0, the texture is destroyed as are entries
Because stencil buffers are most of the time the same as the depth buffer, this also increments, but we control all the decrementing
in the destroyRenderPassDescriptor() and the notifyRecreate()
As mentioned in the ticket i have created a function called _cleanupDepthBuffers which is called in the root _updateAllRenderTargets().
I have tested on many different nodes through post processors, workspace refreshes and many scenes and it seems to work.
There may be other areas in code that you think might need to be included but i have done the most obvious.
Anyway, patch notes here for you to test.
++ marks the spot
OgreRenderSystem.cpp
Code: Select all
...
// function - Shutdown()
void RenderSystem::shutdown(void)
{
...
destroyAllRenderPassDescriptors();
++ _dereferenceAllDepthBuffer();
++ _cleanupDepthBuffers();
}
...
// Line 512
++ //---------------------------------------------------------------------
++ void RenderSystem::destroyDepthBuffer(TextureGpu *depthBuffer)
++ {
++ TextureGpuVec& bufferVec = mDepthBufferPool2[depthBuffer->getDepthBufferPoolID()];
++ TextureGpuVec::iterator itor = std::find(bufferVec.begin(), bufferVec.end(), depthBuffer);
++ if (itor != bufferVec.end()) {
++ bufferVec.erase(itor);
++ mTextureGpuManager->destroyTexture(depthBuffer);
++ }
++ }
++ //---------------------------------------------------------------------
++ void RenderSystem::_cleanupDepthBuffers(void)
++ {
++ DepthBufferRefMap2::iterator itor = mDepthBufferReferences.begin();
++ DepthBufferRefMap2::iterator end = mDepthBufferReferences.end();
++ while (itor != end){
++ if (itor->second <= 0) {
++ destroyDepthBuffer(itor->first);
++ itor = mDepthBufferReferences.erase(itor);
++ end = mDepthBufferReferences.end();
++ }else {
++ itor++;
++ }
++ }
++ }
++ //---------------------------------------------------------------------
++ void RenderSystem::_dereferenceDepthBuffer( TextureGpu* depthBuffer)
++ {
++ if (!depthBuffer) return;
++ mDepthBufferReferences[depthBuffer]--;
++ mDepthBufferReferences[depthBuffer] = mDepthBufferReferences[depthBuffer] <= 0 ? 0 : mDepthBufferReferences[depthBuffer];
++ }
++ //---------------------------------------------------------------------
++ void RenderSystem::_dereferenceAllDepthBuffer()
++ {
++ DepthBufferRefMap2::iterator itor = mDepthBufferReferences.begin();
++ DepthBufferRefMap2::iterator end = mDepthBufferReferences.end();
++ while (itor != end) {
++ itor->second = 0;
++ itor++;
++ }
++ }
++ //---------------------------------------------------------------------
++ void RenderSystem::_referenceDepthBuffer( TextureGpu* depthBuffer )
++ {
++ if (!depthBuffer) return;
++ mDepthBufferReferences[depthBuffer]++;
++
++ }
...
// GetDepthBuffersFor() -- i have added the full function as it will be easier to see change.
TextureGpu* RenderSystem::getDepthBufferFor( TextureGpu *colourTexture, uint16 poolId,
bool preferDepthTexture,
PixelFormatGpu depthBufferFormat )
{
if( poolId == DepthBuffer::POOL_NO_DEPTH || depthBufferFormat == PFG_NULL )
return 0; //RenderTarget explicitly requested no depth buffer
if( colourTexture->isRenderWindowSpecific() )
{
Window *window;
colourTexture->getCustomAttribute( "Window", &window );
return window->getDepthBuffer();
}
if( poolId == DepthBuffer::POOL_NON_SHAREABLE )
{
TextureGpu *retVal = createDepthBufferFor( colourTexture, preferDepthTexture,
depthBufferFormat );
++ retVal->setDepthBufferPoolID(poolId); // Unused but at least the texture knows where it belongs
++ _referenceDepthBuffer(retVal);
return retVal;
}
//Find a depth buffer in the pool
TextureGpuVec::const_iterator itor = mDepthBufferPool2[poolId].begin();
TextureGpuVec::const_iterator end = mDepthBufferPool2[poolId].end();
TextureGpu *retVal = 0;
while( itor != end && !retVal )
{
if( preferDepthTexture == (*itor)->isTexture() &&
(depthBufferFormat == PFG_UNKNOWN ||
depthBufferFormat == (*itor)->getPixelFormat()) &&
(*itor)->supportsAsDepthBufferFor( colourTexture ) )
{
retVal = *itor;
++ _referenceDepthBuffer(retVal);
}
else
{
retVal = 0;
}
++itor;
}
//Not found yet? Create a new one!
if( !retVal )
{
retVal = createDepthBufferFor( colourTexture, preferDepthTexture, depthBufferFormat );
++ retVal->setDepthBufferPoolID(poolId); // Unused but at least the texture knows where it belongs
++ _referenceDepthBuffer(retVal);
mDepthBufferPool2[poolId].push_back( retVal );
if( !retVal )
{
LogManager::getSingleton().logMessage( "WARNING: Couldn't create a suited "
"DepthBuffer for RTT: " +
colourTexture->getNameStr(), LML_CRITICAL );
}
}
return retVal;
}
...
// destoryRenderPassDescriptor() - same again, full function
void RenderSystem::destroyRenderPassDescriptor( RenderPassDescriptor *renderPassDesc )
{
RenderPassDescriptorSet::iterator itor = mRenderPassDescs.find( renderPassDesc );
assert( itor != mRenderPassDescs.end() && "Already destroyed?" );
if( itor != mRenderPassDescs.end() )
mRenderPassDescs.erase( itor );
++
++ if (renderPassDesc->mDepth.texture) {
++ _dereferenceDepthBuffer(renderPassDesc->mDepth.texture);
++
++ if (renderPassDesc->mStencil.texture && renderPassDesc->mStencil.texture == renderPassDesc->mDepth.texture) {
++ _dereferenceDepthBuffer(renderPassDesc->mDepth.texture);
++ }
++ }
delete renderPassDesc;
}
OgreRenderSystem.h
Code: Select all
...
// line 56
typedef vector<TextureGpu*>::type TextureGpuVec;
typedef map< uint16, TextureGpuVec >::type DepthBufferMap2;
++ typedef map< TextureGpu*, int16 >::type DepthBufferRefMap2;
...
// line 762
++ /** Internal use only, detroys a depth buffer associated in the pool. If no texture is found
++ the it skips. Useful for clearing the renderwindow depth and stencil buffer.
++ */
++ void destroyDepthBuffer( TextureGpu *depthTexture );
++ void _cleanupDepthBuffers(void);
++ void _dereferenceDepthBuffer( TextureGpu* depthBuffer );
++ void _dereferenceAllDepthBuffer();
++ void _referenceDepthBuffer( TextureGpu* depthBuffer );
//line 1404
DepthBufferMap2 mDepthBufferPool2;
++ DepthBufferRefMap2 mDepthBufferReferences;
OgreCompositorPass.cpp
Code: Select all
...
// notifyRecreated()
bool CompositorPass::notifyRecreated( const TextureGpu *channel )
{
...
if( usedByUs )
{
mNumPassesLeft = mDefinition->mNumInitialPasses;
//Reset texture pointers and setup RenderPassDescriptor again
++ RenderSystem *renderSystem = mParentNode->getRenderSystem();
++ //renderSystem->_dereferenceDepthBuffer(mRenderPassDesc->mDepth.texture);
++ if (mRenderPassDesc->mDepth.texture) {
++ renderSystem->_dereferenceDepthBuffer(mRenderPassDesc->mDepth.texture);
++
++ if (mRenderPassDesc->mStencil.texture && mRenderPassDesc->mStencil.texture == mRenderPassDesc->mDepth.texture) {
++ renderSystem->_dereferenceDepthBuffer(mRenderPassDesc->mDepth.texture);
++ }
++ }
mRenderPassDesc->mDepth.texture = 0;
mRenderPassDesc->mStencil.texture = 0;
...
}
...
}
...
OgreRoot.cpp -- full function
Code: Select all
//-----------------------------------------------------------------------
bool Root::_updateAllRenderTargets(void)
{
...
for (SceneManagerEnumerator::SceneManagerIterator it = getSceneManagerIterator(); it.hasMoreElements(); it.moveNext())
it.peekNextValue()->_handleLodEvents();
++
++ // Release all the depth buffers which are no longer in use
++ mActiveRenderer->_cleanupDepthBuffers();
return ret;
}
OgreTextureGpu.cpp
Code: Select all
// Line 68 - constructor
-- mTexturePool( 0 )
++ mTexturePool( 0 ),
++ mDepthBufferPoolId( 0 )
...
// With the other
++ //-----------------------------------------------------------------------------------
++ // Skyline tweak - setter and getter for a depth buffer texture to retrieve its slot in the depth buffer map
++ void TextureGpu::setDepthBufferPoolID(uint16 id) { mDepthBufferPoolId = id; }
++ //-----------------------------------------------------------------------------------
++ uint16 TextureGpu::getDepthBufferPoolID(void) const { return mDepthBufferPoolId; }
++ //-----------------------------------------------------------------------------------
OgreTextureGpu.h
Code: Select all
//Line 330:
++ // Skyline tweak - setter and getter for a depth buffer texture to retrieve its slot in the depth buffer map
++ void setDepthBufferPoolID(uint16 id);
++ uint16 getDepthBufferPoolID(void) const;
// Line 230
/// See TextureFlags::TextureFlags
uint32 mTextureFlags;
/// Used if hasAutomaticBatching() == true
uint32 mPoolId;
++ /// Not used for anything but the depth buffers to identify the depth buffer pool they belong too. As its quicker than searching all depth buffers.
++ uint32 mDepthBufferPoolId;
If there is something missing, it will be obvious enough for you to write up
Hope this is accepatable and avoids the dangling pointer.
Edit: Just removed some log bits. refresh post