From 0d92bc6c8cfb1c0db967d31581510455fbf423e1 Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 11 Jul 2013 16:17:48 +0200 Subject: [PATCH] Starting to split Block class into CompressedBlock and UncompressedBlock. --- examples/Paging/main.cpp | 4 +- .../include/PolyVoxCore/Impl/Block.h | 3 - .../include/PolyVoxCore/Impl/Block.inl | 109 +----------------- .../include/PolyVoxCore/LargeVolume.h | 5 - .../include/PolyVoxCore/LargeVolume.inl | 64 ++-------- 5 files changed, 16 insertions(+), 169 deletions(-) diff --git a/examples/Paging/main.cpp b/examples/Paging/main.cpp index f172a214..c497a255 100644 --- a/examples/Paging/main.cpp +++ b/examples/Paging/main.cpp @@ -93,7 +93,7 @@ public: virtual void pageIn(const PolyVox::Region& region, Block* pBlockData) { - pBlockData->createUncompressedData(); + /*pBlockData->createUncompressedData(); Perlin perlin(2,2,1,234); @@ -134,7 +134,7 @@ public: pBlockData->setVoxelAt(x - region.getLowerX(), y - region.getLowerY(), z - region.getLowerZ(), voxel); } } - } + }*/ } virtual void pageOut(const PolyVox::Region& region, Block* /*pBlockData*/) diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.h b/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.h index 06963f7c..509b2dce 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.h @@ -52,9 +52,6 @@ namespace PolyVox void setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue); void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue); - void createUncompressedData(void); - void destroyUncompressedData(void); - uint32_t calculateSizeInBytes(void); public: diff --git a/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.inl b/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.inl index bebcfb35..bdba78f9 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/Impl/Block.inl @@ -66,12 +66,12 @@ namespace PolyVox //Temporarily create the block data. This is just so we can compress it an discard it. // FIXME - this is a temporary solution. - const uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength; + /*const uint32_t uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength; m_tUncompressedData = new VoxelType[uNoOfVoxels]; std::fill(m_tUncompressedData, m_tUncompressedData + uNoOfVoxels, VoxelType()); m_bIsUncompressedDataModified = true; - destroyUncompressedData(); + destroyUncompressedData();*/ } template @@ -127,7 +127,7 @@ namespace PolyVox template void Block::setCompressedData(const uint8_t* const data, uint32_t dataLength) { - POLYVOX_ASSERT(m_pCompressedData, "Compressed data is NULL"); + //POLYVOX_ASSERT(m_pCompressedData, "Compressed data is NULL"); POLYVOX_ASSERT(m_pCompressedData != data, "Attempting to copy data onto itself"); delete[] m_pCompressedData; @@ -163,109 +163,6 @@ namespace PolyVox setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue); } - template - void Block::destroyUncompressedData() - { - if(!hasUncompressedData()) - { - POLYVOX_THROW(invalid_operation, "No uncompressed data to compress."); - } - - POLYVOX_ASSERT(m_tUncompressedData != 0, "No uncompressed data is present."); - - //If the uncompressed data hasn't actually been - //modified then we don't need to redo the compression. - if(m_bIsUncompressedDataModified) - { - // Delete the old compressed data as we'll create a new one - delete[] m_pCompressedData; - m_pCompressedData = 0; - - void* pSrcData = reinterpret_cast(m_tUncompressedData); - uint32_t uSrcLength = m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType); - - uint8_t tempBuffer[10000]; - void* pDstData = reinterpret_cast( tempBuffer ); - uint32_t uDstLength = 10000; - - uint32_t uCompressedLength = 0; - - try - { - uCompressedLength = m_pCompressor->compress(pSrcData, uSrcLength, pDstData, uDstLength); - - // Create new compressed data and copy across - m_pCompressedData = new uint8_t[uCompressedLength]; - memcpy(m_pCompressedData, pDstData, uCompressedLength); - m_uCompressedDataLength = uCompressedLength; - } - catch(std::exception&) - { - // It is possible for the compression to fail. A common cause for this would be if the destination - // buffer is not big enough. So now we try again using a buffer that is definitely big enough. - // Note that ideally we will choose our earlier buffer size so that this almost never happens. - logWarning() << "The compressor failed to compress the block, proabaly due to the buffer being too small."; - logWarning() << "The compression will be tried again with a larger buffer"; - uint32_t uMaxCompressedSize = m_pCompressor->getMaxCompressedSize(uSrcLength); - uint8_t* buffer = new uint8_t[ uMaxCompressedSize ]; - - pDstData = reinterpret_cast( buffer ); - uDstLength = uMaxCompressedSize; - - try - { - uCompressedLength = m_pCompressor->compress(pSrcData, uSrcLength, pDstData, uDstLength); - - // Create new compressed data and copy across - m_pCompressedData = new uint8_t[uCompressedLength]; - memcpy(m_pCompressedData, pDstData, uCompressedLength); - m_uCompressedDataLength = uCompressedLength; - } - catch(std::exception&) - { - // At this point it didn't work even with a bigger buffer. - // Not much more we can do so just rethrow the exception. - delete[] buffer; - POLYVOX_THROW(std::runtime_error, "Failed to compress block data"); - } - - delete[] buffer; - } - } - - //Flag the uncompressed data as no longer being used. - delete[] m_tUncompressedData; - m_tUncompressedData = 0; - } - - template - void Block::createUncompressedData() - { - if(hasUncompressedData()) - { - POLYVOX_THROW(invalid_operation, "Uncompressed data already exists."); - } - - POLYVOX_ASSERT(m_tUncompressedData == 0, "Uncompressed data already exists."); - - m_tUncompressedData = new VoxelType[m_uSideLength * m_uSideLength * m_uSideLength]; - - void* pSrcData = reinterpret_cast(m_pCompressedData); - void* pDstData = reinterpret_cast(m_tUncompressedData); - uint32_t uSrcLength = m_uCompressedDataLength; - uint32_t uDstLength = m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType); - - //MinizCompressor compressor; - //RLECompressor compressor; - uint32_t uUncompressedLength = m_pCompressor->decompress(pSrcData, uSrcLength, pDstData, uDstLength); - - POLYVOX_ASSERT(uUncompressedLength == m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType), "Destination length has changed."); - - //m_tUncompressedData = reinterpret_cast(uncompressedResult.ptr); - - m_bIsUncompressedDataModified = false; - } - template uint32_t Block::calculateSizeInBytes(void) { diff --git a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h index 03b4ac01..86e36381 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h +++ b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.h @@ -337,11 +337,6 @@ namespace PolyVox mutable std::map m_pUncompressedBlockCache; mutable std::map, BlockPositionCompare> m_pBlocks; - // The cache of uncompressed blocks. The uncompressed block data and the timestamps are stored here rather - // than in the Block class. This is so that in the future each VolumeIterator might to maintain its own cache - // of blocks. However, this could mean the same block data is uncompressed and modified in more than one - // location in memory... could be messy with threading. - mutable std::vector< Block* > m_vecBlocksWithUncompressedData; mutable uint32_t m_uTimestamper; mutable Vector3DInt32 m_v3dLastAccessedBlockPos; mutable VoxelType* m_pLastAccessedBlock; diff --git a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl index e8194b2f..770c94ee 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/LargeVolume.inl @@ -102,7 +102,7 @@ namespace PolyVox template LargeVolume::~LargeVolume() { - flushAll(); + //flushAll(); // Only delete the compressor if it was created by us (in the constructor), not by the user. if(m_bIsOurCompressor) @@ -509,11 +509,6 @@ namespace PolyVox template void LargeVolume::clearBlockCache(void) { - for(uint32_t ct = 0; ct < m_vecBlocksWithUncompressedData.size(); ct++) - { - m_vecBlocksWithUncompressedData[ct]->destroyUncompressedData(); - } - m_vecBlocksWithUncompressedData.clear(); } //////////////////////////////////////////////////////////////////////////////// @@ -571,7 +566,9 @@ namespace PolyVox template void LargeVolume::eraseBlock(typename std::map, BlockPositionCompare>::iterator itBlock) const { - if(itBlock->second.hasUncompressedData()) + POLYVOX_ASSERT(false, "This function has not been implemented properly"); + + /*if(itBlock->second.hasUncompressedData()) { itBlock->second.destroyUncompressedData(); } @@ -585,9 +582,11 @@ namespace PolyVox Region reg(v3dLower, v3dUpper); m_pPager->pageOut(reg, &(itBlock->second)); - } + }*/ + - for(uint32_t ct = 0; ct < m_vecBlocksWithUncompressedData.size(); ct++) + // FIXME - the code below used to make sure the uncompressed version of the data was removed. Reinstate something similar. + /*for(uint32_t ct = 0; ct < m_vecBlocksWithUncompressedData.size(); ct++) { // find the block in the uncompressed cache if(m_vecBlocksWithUncompressedData[ct] == &(itBlock->second)) @@ -598,7 +597,7 @@ namespace PolyVox m_vecBlocksWithUncompressedData.resize(m_vecBlocksWithUncompressedData.size()-1); break; } - } + }*/ m_pBlocks.erase(itBlock); } @@ -676,47 +675,6 @@ namespace PolyVox m_v3dLastAccessedBlockPos = v3dBlockPos; return m_pLastAccessedBlock; - - if(block->hasUncompressedData()) - { - return block->m_tUncompressedData; - } - - //If we are allowed to compress then check whether we need to - if(m_vecBlocksWithUncompressedData.size() == m_uMaxNumberOfUncompressedBlocks) - { - int32_t leastRecentlyUsedBlockIndex = -1; - uint32_t uLeastRecentTimestamp = (std::numeric_limits::max)(); - - //Currently we find the oldest block by iterating over the whole array. Of course we could store the blocks sorted by - //timestamp (set, priority_queue, etc) but then we'll need to move them around as the timestamp changes. Can come back - //to this if it proves to be a bottleneck (compraed to the cost of actually doing the compression/decompression). - for(uint32_t ct = 0; ct < m_vecBlocksWithUncompressedData.size(); ct++) - { - if(m_vecBlocksWithUncompressedData[ct]->timestamp < uLeastRecentTimestamp) - { - uLeastRecentTimestamp = m_vecBlocksWithUncompressedData[ct]->timestamp; - leastRecentlyUsedBlockIndex = ct; - } - } - - //Compress the least recently used block. - m_vecBlocksWithUncompressedData[leastRecentlyUsedBlockIndex]->destroyUncompressedData(); - - //We don't actually remove any elements from this vector, we - //simply change the pointer to point at the new uncompressed bloack. - m_vecBlocksWithUncompressedData[leastRecentlyUsedBlockIndex] = block; - } - else - { - m_vecBlocksWithUncompressedData.push_back(block); - } - - block->createUncompressedData(); - - m_pLastAccessedBlock = block->m_tUncompressedData; - POLYVOX_ASSERT(m_pLastAccessedBlock, "Block has no uncompressed data"); - return m_pLastAccessedBlock; } //////////////////////////////////////////////////////////////////////////////// @@ -747,8 +705,8 @@ namespace PolyVox } //Memory used by the block cache. - uSizeInBytes += m_vecBlocksWithUncompressedData.capacity() * sizeof(Block); - uSizeInBytes += m_vecBlocksWithUncompressedData.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType); + //uSizeInBytes += m_vecBlocksWithUncompressedData.capacity() * sizeof(Block); + //uSizeInBytes += m_vecBlocksWithUncompressedData.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType); return uSizeInBytes; }