From 0c5593824282d7e192d2ce428e1c4311ff59f23c Mon Sep 17 00:00:00 2001 From: Daviw Williams Date: Fri, 5 Jul 2013 15:41:16 +0200 Subject: [PATCH] Work on the code that frees up memory in LargeVolume. --- .../include/PolyVoxCore/LargeVolume.h | 8 +++- .../include/PolyVoxCore/LargeVolume.inl | 46 +++++++++++++++++-- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h index f46562d7..cd773156 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h +++ b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h @@ -312,11 +312,15 @@ namespace PolyVox } return false; } - }; - void initialise(); + }; uint32_t calculateBlockMemoryUsage(void) const; + void flushOldestExcessiveBlocks(void) const; + void flushExcessiveCacheEntries(void) const; + + void initialise(); + // A trick to implement specialization of template member functions in template classes. See http://stackoverflow.com/a/4951057 template VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const; diff --git a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl index b50ef2bf..c46549af 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl @@ -246,11 +246,14 @@ namespace PolyVox template void LargeVolume::setTargetMemoryLimitInBytes(uint32_t uTargetMemoryLimitInBytes) { + // The size of a single uncompressed block of data. uint32_t uUncompressedBlockSizeInBytes = m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType); + // The idea number of uncompressed blocks is chosen by gut feeling as much as anything. Part of the + // rationale is that it should let us iterate along any edge without data being pushed out of the cache. uint32_t uIdealNoOfUncompressedBlocks = m_regValidRegionInBlocks.getWidthInVoxels() + m_regValidRegionInBlocks.getHeightInVoxels() * m_regValidRegionInBlocks.getDepthInVoxels(); - // Let's say that we should never use more than half the available memory for the uncompressed block cache. + // Let's (arbitrarily?) say that we should never use more than half the available memory for the uncompressed block cache. uint32_t uMaxMemoryForUncompressedBlocks = uTargetMemoryLimitInBytes / 2; uint32_t uMaxFittableNoOfUncompressedBlocks = uMaxMemoryForUncompressedBlocks / uUncompressedBlockSizeInBytes; @@ -607,9 +610,9 @@ namespace PolyVox //The block is not in the map, so we will have to create a new block and add it. //Before we do so, we might want to dump some existing data to make space. We //Only do this if paging is enabled. - if(m_pPager) + /*if(m_pPager) { - // check wether another block needs to be unloaded before this one can be loaded + // check whether another block needs to be unloaded before this one can be loaded while(calculateBlockMemoryUsage() > m_uCompressedBlockMemoryLimitInBytes) //FIXME - This calculation of size is slow and should be outside the loop. { // find the least recently used block @@ -624,7 +627,9 @@ namespace PolyVox } eraseBlock(itUnloadBlock); } - } + }*/ + + flushOldestExcessiveBlocks(); // create the new block Block newBlock(m_uBlockSideLength, m_pCompressor); @@ -746,6 +751,39 @@ namespace PolyVox return uMemoryUsage; } + template + void LargeVolume::flushOldestExcessiveBlocks(void) const + { + const uint32_t uMemoryUsedForCompressedBlocks = calculateBlockMemoryUsage(); + uint32_t uMemoryToReclaim = uMemoryUsedForCompressedBlocks - m_uCompressedBlockMemoryLimitInBytes; + + //while(uMemoryToReclaim > 0) + while(calculateBlockMemoryUsage() > m_uCompressedBlockMemoryLimitInBytes) //FIXME - This calculation of size is slow and should be outside the loop. + { + // find the least recently used block + typename std::map, BlockPositionCompare>::iterator i; + typename std::map, BlockPositionCompare>::iterator itUnloadBlock = m_pBlocks.begin(); + for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++) + { + if(i->second.timestamp < itUnloadBlock->second.timestamp) + { + itUnloadBlock = i; + } + } + + //POLYVOX_ASSERT(itUnloadBlock->second.hasUncompressedData() == false, "This function should never flush blocks with uncompressed data."); + + uMemoryToReclaim -= itUnloadBlock->second.calculateSizeInBytes(); + + eraseBlock(itUnloadBlock); + } + } + + template + void LargeVolume::flushExcessiveCacheEntries(void) const + { + } + template template VoxelType LargeVolume::getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType, VoxelType tBorder) const