Work on code which computes how the memory should be split between compressed and uncompressed data.
This commit is contained in:
@ -347,7 +347,7 @@ namespace PolyVox
|
|||||||
mutable UncompressedBlock<VoxelType>* m_pLastAccessedBlock;
|
mutable UncompressedBlock<VoxelType>* m_pLastAccessedBlock;
|
||||||
uint32_t m_uMaxNumberOfUncompressedBlocks;
|
uint32_t m_uMaxNumberOfUncompressedBlocks;
|
||||||
|
|
||||||
uint32_t m_uCompressedBlockMemoryLimitInBytes;
|
uint32_t m_uTargetMemoryLimitInBytes;
|
||||||
|
|
||||||
// The size of the volume
|
// The size of the volume
|
||||||
Region m_regValidRegionInBlocks;
|
Region m_regValidRegionInBlocks;
|
||||||
|
@ -246,23 +246,57 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
void LargeVolume<VoxelType>::setTargetMemoryLimitInBytes(uint32_t uTargetMemoryLimitInBytes)
|
void LargeVolume<VoxelType>::setTargetMemoryLimitInBytes(uint32_t uTargetMemoryLimitInBytes)
|
||||||
{
|
{
|
||||||
|
// Set the limit, and then work out how big the uncompressed cache should be.
|
||||||
|
m_uTargetMemoryLimitInBytes = uTargetMemoryLimitInBytes;
|
||||||
|
|
||||||
// The size of a single uncompressed block of data.
|
// The size of a single uncompressed block of data.
|
||||||
uint32_t uUncompressedBlockSizeInBytes = m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
|
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
|
// When deciding how to split the memory between compressed and uncompressed blocks it is useful to know the dimensions of the
|
||||||
// rationale is that it should let us iterate along any edge without data being pushed out of the cache.
|
// volume in blocks. After sorting, the array below will hold the smallest dimension in [0] and the largest dimension in [2].
|
||||||
uint32_t uIdealNoOfUncompressedBlocks = m_regValidRegionInBlocks.getWidthInVoxels() + m_regValidRegionInBlocks.getHeightInVoxels() * m_regValidRegionInBlocks.getDepthInVoxels();
|
const uint32_t uNoOfDimensions = 3;
|
||||||
|
uint32_t uSortedDimensionsInBlocks[uNoOfDimensions];
|
||||||
|
uSortedDimensionsInBlocks[0] = (getEnclosingRegion().getWidthInVoxels() >> m_uBlockSideLengthPower) + 1;
|
||||||
|
uSortedDimensionsInBlocks[1] = (getEnclosingRegion().getHeightInVoxels() >> m_uBlockSideLengthPower) + 1;
|
||||||
|
uSortedDimensionsInBlocks[2] = (getEnclosingRegion().getDepthInVoxels() >> m_uBlockSideLengthPower) + 1;
|
||||||
|
std::sort(uSortedDimensionsInBlocks, uSortedDimensionsInBlocks + uNoOfDimensions);
|
||||||
|
|
||||||
// Let's (arbitrarily?) say that we should never use more than half the available memory for the uncompressed block cache.
|
const uint32_t uLongestEdgeInBlocks = uSortedDimensionsInBlocks[2];
|
||||||
uint32_t uMaxMemoryForUncompressedBlocks = uTargetMemoryLimitInBytes / 2;
|
const uint32_t uLargestFaceSizeInBlocks = uSortedDimensionsInBlocks[1] * uSortedDimensionsInBlocks[2];
|
||||||
|
|
||||||
uint32_t uMaxFittableNoOfUncompressedBlocks = uMaxMemoryForUncompressedBlocks / uUncompressedBlockSizeInBytes;
|
// In the ideal situation we will be able to keep an entire face of blocks decompressed in the cache, and still have significant memory
|
||||||
|
// left for storing a large number of compressed block. Failing this, we would at least like to be able to keep enough blocks decompressed
|
||||||
|
// to iterate over the longest edge. Otherwise we will find that excessive compression and decompresion occurs. In both cases we multiply
|
||||||
|
// by an extra factor make sure there is space for storing some compressed data as well.
|
||||||
|
const uint32_t uFactor = 2; // Just to make sure we leave some space for compressed data as well
|
||||||
|
const uint32_t uIdealMemoryTarget = uLargestFaceSizeInBlocks * uUncompressedBlockSizeInBytes * uFactor;
|
||||||
|
const uint32_t uAcceptableMemoryTarget = uLongestEdgeInBlocks * uUncompressedBlockSizeInBytes * uFactor;
|
||||||
|
|
||||||
setMaxNumberOfUncompressedBlocks((std::min)(uIdealNoOfUncompressedBlocks, uMaxFittableNoOfUncompressedBlocks));
|
if(uTargetMemoryLimitInBytes >= uIdealMemoryTarget)
|
||||||
|
{
|
||||||
|
logDebug() << "The target memory limit (" << uTargetMemoryLimitInBytes << "bytes) is plenty for a volume of this size)";
|
||||||
|
|
||||||
uint32_t uUncompressedBlockCacheSizeInBytes = m_uMaxNumberOfUncompressedBlocks * uUncompressedBlockSizeInBytes;
|
// The added value below is just some extra 'grace' space.
|
||||||
|
setMaxNumberOfUncompressedBlocks(uLargestFaceSizeInBlocks + uSortedDimensionsInBlocks[1]);
|
||||||
|
}
|
||||||
|
else if(uTargetMemoryLimitInBytes >= uAcceptableMemoryTarget)
|
||||||
|
{
|
||||||
|
logDebug() << "The target memory limit (" << uTargetMemoryLimitInBytes << "bytes) should be acceptable for a volume of this size)";
|
||||||
|
|
||||||
m_uCompressedBlockMemoryLimitInBytes = uTargetMemoryLimitInBytes - uUncompressedBlockCacheSizeInBytes;
|
// Let's (arbitrarily) use 1/4 of the available memory for the cache, while making sure that it is as long as the longest side.
|
||||||
|
uint32_t uMaxFittableUncompressedBlocks = uTargetMemoryLimitInBytes / uUncompressedBlockSizeInBytes;
|
||||||
|
setMaxNumberOfUncompressedBlocks((std::max)(uMaxFittableUncompressedBlocks / 4, uLongestEdgeInBlocks));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logWarning() << "The target memory limit (" << uTargetMemoryLimitInBytes << "bytes) is too low for a volume of this size)";
|
||||||
|
logWarning() << "Excessive block thrashing may occur and the target memory limit may not be honored";
|
||||||
|
|
||||||
|
// We still have to do something. Let's still use 1/4 of the memory for the cache, but also set a minimum size.
|
||||||
|
const uint32_t uMinNoOfUncompressedBlocks = 8; // Chosen because it just feels about right.
|
||||||
|
uint32_t uMaxFittableUncompressedBlocks = uTargetMemoryLimitInBytes / uUncompressedBlockSizeInBytes;
|
||||||
|
setMaxNumberOfUncompressedBlocks((std::max)(uMaxFittableUncompressedBlocks / 4, uMinNoOfUncompressedBlocks));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -277,6 +311,10 @@ namespace PolyVox
|
|||||||
clearBlockCache();
|
clearBlockCache();
|
||||||
|
|
||||||
m_uMaxNumberOfUncompressedBlocks = uMaxNumberOfUncompressedBlocks;
|
m_uMaxNumberOfUncompressedBlocks = uMaxNumberOfUncompressedBlocks;
|
||||||
|
|
||||||
|
uint32_t uUncompressedBlockSizeInBytes = m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
|
||||||
|
logDebug() << "The maximum number of uncompresed blocks has been set to " << m_uMaxNumberOfUncompressedBlocks
|
||||||
|
<< ", which is " << m_uMaxNumberOfUncompressedBlocks * uUncompressedBlockSizeInBytes << " bytes";
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -781,7 +819,7 @@ namespace PolyVox
|
|||||||
//uint32_t uMemoryToReclaim = uMemoryUsedForCompressedBlocks - m_uCompressedBlockMemoryLimitInBytes;
|
//uint32_t uMemoryToReclaim = uMemoryUsedForCompressedBlocks - m_uCompressedBlockMemoryLimitInBytes;
|
||||||
|
|
||||||
//while(uMemoryToReclaim > 0)
|
//while(uMemoryToReclaim > 0)
|
||||||
while(calculateBlockMemoryUsage() > m_uCompressedBlockMemoryLimitInBytes) //FIXME - This calculation of size is slow and should be outside the loop.
|
/*while(calculateBlockMemoryUsage() > m_uCompressedBlockMemoryLimitInBytes) //FIXME - This calculation of size is slow and should be outside the loop.
|
||||||
{
|
{
|
||||||
// find the least recently used block
|
// find the least recently used block
|
||||||
typename CompressedBlockMap::iterator i;
|
typename CompressedBlockMap::iterator i;
|
||||||
@ -799,7 +837,7 @@ namespace PolyVox
|
|||||||
//uMemoryToReclaim -= itUnloadBlock->second->calculateSizeInBytes();
|
//uMemoryToReclaim -= itUnloadBlock->second->calculateSizeInBytes();
|
||||||
|
|
||||||
eraseBlock(itUnloadBlock);
|
eraseBlock(itUnloadBlock);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
|
Reference in New Issue
Block a user