diff --git a/examples/Paging/main.cpp b/examples/Paging/main.cpp index 07877405..117145b7 100644 --- a/examples/Paging/main.cpp +++ b/examples/Paging/main.cpp @@ -153,9 +153,8 @@ int main(int argc, char *argv[]) RLECompressor* compressor = new RLECompressor(); PerlinNoisePager* pager = new PerlinNoisePager(); LargeVolume volData(PolyVox::Region::MaxRegion, compressor, pager, 256); - //volData.setMaxNumberOfBlocksInMemory(4096); - //volData.setMaxNumberOfUncompressedBlocks(64); - volData.setTargetMemoryLimitInBytes(128 * 1024 * 1024); + volData.setMaxNumberOfBlocksInMemory(4096); + volData.setMaxNumberOfUncompressedBlocks(64); //volData.setMaxNumberOfUncompressedBlocks(4096); //createSphereInVolume(volData, 30); diff --git a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h index 499a5f91..e1786609 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h +++ b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h @@ -263,10 +263,10 @@ namespace PolyVox /// Gets a voxel at the position given by a 3D vector POLYVOX_DEPRECATED VoxelType getVoxelAt(const Vector3DInt32& v3dPos) const; - void setTargetMemoryLimitInBytes(uint32_t uTargetMemoryLimitInBytes); - /// Sets the number of blocks for which uncompressed data is stored void setMaxNumberOfUncompressedBlocks(uint32_t uMaxNumberOfUncompressedBlocks); + /// Sets the number of blocks which can be in memory before the paging system starts unloading them + void setMaxNumberOfBlocksInMemory(uint32_t uMaxNumberOfBlocksInMemory); /// Sets the voxel at the position given by x,y,z coordinates void setVoxel(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue, WrapMode eWrapMode = WrapModes::Validate); /// Sets the voxel at the position given by a 3D vector @@ -346,8 +346,7 @@ namespace PolyVox mutable Vector3DInt32 m_v3dLastAccessedBlockPos; mutable UncompressedBlock* m_pLastAccessedBlock; uint32_t m_uMaxNumberOfUncompressedBlocks; - - uint32_t m_uTargetMemoryLimitInBytes; + uint32_t m_uMaxNumberOfBlocksInMemory; // The size of the volume Region m_regValidRegionInBlocks; diff --git a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl index e174a578..04b68a6d 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl @@ -243,62 +243,6 @@ namespace PolyVox return getVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ()); } - template - void LargeVolume::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. - uint32_t uUncompressedBlockSizeInBytes = m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType); - - // When deciding how to split the memory between compressed and uncompressed blocks it is useful to know the dimensions of the - // volume in blocks. After sorting, the array below will hold the smallest dimension in [0] and the largest dimension in [2]. - 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); - - const uint32_t uLongestEdgeInBlocks = uSortedDimensionsInBlocks[2]; - const uint32_t uLargestFaceSizeInBlocks = uSortedDimensionsInBlocks[1] * uSortedDimensionsInBlocks[2]; - - // 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; - - if(uTargetMemoryLimitInBytes >= uIdealMemoryTarget) - { - logDebug() << "The target memory limit (" << uTargetMemoryLimitInBytes << "bytes) is plenty for a volume of this size)"; - - // 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)"; - - // 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)); - } - } - //////////////////////////////////////////////////////////////////////////////// /// Increasing the size of the block cache will increase memory but may improve performance. /// You may want to set this to a large value (e.g. 1024) when you are first loading your @@ -317,6 +261,21 @@ namespace PolyVox << ", which is " << m_uMaxNumberOfUncompressedBlocks * uUncompressedBlockSizeInBytes << " bytes"; } + //////////////////////////////////////////////////////////////////////////////// + /// Increasing the number of blocks in memory causes less paging to occur + /// \param uMaxNumberOfBlocksInMemory The number of blocks + //////////////////////////////////////////////////////////////////////////////// + template + void LargeVolume::setMaxNumberOfBlocksInMemory(uint32_t uMaxNumberOfBlocksInMemory) + { + if(m_pBlocks.size() > uMaxNumberOfBlocksInMemory) + { + flushAll(); + } + + m_uMaxNumberOfBlocksInMemory = uMaxNumberOfBlocksInMemory; + } + //////////////////////////////////////////////////////////////////////////////// /// \param uXPos the \c x position of the voxel /// \param uYPos the \c y position of the voxel diff --git a/tests/testvolume.cpp b/tests/testvolume.cpp index 2063e8e3..77ad1063 100644 --- a/tests/testvolume.cpp +++ b/tests/testvolume.cpp @@ -281,9 +281,8 @@ TestVolume::TestVolume() m_pSimpleVolume = new SimpleVolume(region); m_pLargeVolume = new LargeVolume(region, m_pCompressor, m_pFilePager, 32); - //m_pLargeVolume->setMaxNumberOfBlocksInMemory(32); - //m_pLargeVolume->setMaxNumberOfUncompressedBlocks(16); - m_pLargeVolume->setTargetMemoryLimitInBytes(4 * 1024 * 1024); + m_pLargeVolume->setMaxNumberOfBlocksInMemory(32); + m_pLargeVolume->setMaxNumberOfUncompressedBlocks(16); //Fill the volume with some data for(int z = region.getLowerZ(); z <= region.getUpperZ(); z++)