Starting to split Block class into CompressedBlock and UncompressedBlock.

This commit is contained in:
David Williams 2013-07-11 16:17:48 +02:00
parent 9ff95f7061
commit 0d92bc6c8c
5 changed files with 16 additions and 169 deletions

View File

@ -93,7 +93,7 @@ public:
virtual void pageIn(const PolyVox::Region& region, Block<MaterialDensityPair44>* 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<MaterialDensityPair44>* /*pBlockData*/)

View File

@ -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:

View File

@ -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 <typename VoxelType>
@ -127,7 +127,7 @@ namespace PolyVox
template <typename VoxelType>
void Block<VoxelType>::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 <typename VoxelType>
void Block<VoxelType>::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<void*>(m_tUncompressedData);
uint32_t uSrcLength = m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType);
uint8_t tempBuffer[10000];
void* pDstData = reinterpret_cast<void*>( 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<void*>( 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 <typename VoxelType>
void Block<VoxelType>::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<void*>(m_pCompressedData);
void* pDstData = reinterpret_cast<void*>(m_tUncompressedData);
uint32_t uSrcLength = m_uCompressedDataLength;
uint32_t uDstLength = m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType);
//MinizCompressor compressor;
//RLECompressor<VoxelType, uint16_t> 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<VoxelType*>(uncompressedResult.ptr);
m_bIsUncompressedDataModified = false;
}
template <typename VoxelType>
uint32_t Block<VoxelType>::calculateSizeInBytes(void)
{

View File

@ -337,11 +337,6 @@ namespace PolyVox
mutable std::map<Vector3DInt32, VoxelType*, BlockPositionCompare> m_pUncompressedBlockCache;
mutable std::map<Vector3DInt32, Block<VoxelType>, 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<VoxelType>* > m_vecBlocksWithUncompressedData;
mutable uint32_t m_uTimestamper;
mutable Vector3DInt32 m_v3dLastAccessedBlockPos;
mutable VoxelType* m_pLastAccessedBlock;

View File

@ -102,7 +102,7 @@ namespace PolyVox
template <typename VoxelType>
LargeVolume<VoxelType>::~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 <typename VoxelType>
void LargeVolume<VoxelType>::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 <typename VoxelType>
void LargeVolume<VoxelType>::eraseBlock(typename std::map<Vector3DInt32, Block<VoxelType>, 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<uint32_t>::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<VoxelType>);
uSizeInBytes += m_vecBlocksWithUncompressedData.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
//uSizeInBytes += m_vecBlocksWithUncompressedData.capacity() * sizeof(Block<VoxelType>);
//uSizeInBytes += m_vecBlocksWithUncompressedData.size() * m_uBlockSideLength * m_uBlockSideLength * m_uBlockSideLength * sizeof(VoxelType);
return uSizeInBytes;
}