Memory management for volumes.

This commit is contained in:
David Williams 2009-03-26 22:22:04 +00:00
parent fab64488ee
commit 50b3ff407e
4 changed files with 89 additions and 30 deletions

View File

@ -50,10 +50,11 @@ namespace PolyVox
void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue); void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue);
void fill(VoxelType tValue); void fill(VoxelType tValue);
bool isHomogeneous(void);
private: private:
uint16 m_uSideLength; uint16 m_uSideLength;
uint8 m_uSideLengthPower; uint8 m_uSideLengthPower;
VoxelType* m_tData; VoxelType* m_tData;
}; };
} }

View File

@ -141,5 +141,23 @@ namespace PolyVox
{ {
memset(m_tData, tValue, m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType)); memset(m_tData, tValue, m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType));
} }
template <typename VoxelType>
bool BlockData<VoxelType>::isHomogeneous(void)
{
VoxelType currentVoxel = m_tData;
VoxelType firstVal = *currentVoxel;
uint32 uNoOfVoxels = m_uSideLength * m_uSideLength * m_uSideLength;
for(uint32 ct = 1; ct < uNoOfVoxels; ++ct)
{
++currentVoxel;
if(*currentVoxel != firstVoxel)
{
return false;
}
}
return true;
}
#pragma endregion #pragma endregion
} }

View File

@ -38,8 +38,18 @@ namespace PolyVox
public: public:
BlockData<VoxelType>* m_pBlockData; BlockData<VoxelType>* m_pBlockData;
VoxelType m_pHomogenousValue; VoxelType m_pHomogenousValue;
bool m_pIsShared; bool m_bIsShared;
bool m_pIsPotentiallySharable; bool m_bIsPotentiallySharable;
};
template <typename VoxelType>
class ReferenceCountedBlockData
{
public:
ReferenceCountedBlockData() : m_pBlockData(0), m_uReferenceCount(0) {}
BlockData<VoxelType>* m_pBlockData;
uint32 m_uReferenceCount;
}; };
template <typename VoxelType> template <typename VoxelType>
@ -69,14 +79,10 @@ namespace PolyVox
VolumeIterator<VoxelType> lastVoxel(void); VolumeIterator<VoxelType> lastVoxel(void);
private: private:
BlockData<VoxelType>* getHomogenousBlock(VoxelType tHomogenousValue) const; BlockData<VoxelType>* getHomogenousBlockData(VoxelType tHomogenousValue) const;
//Block<VoxelType>** m_pBlocks;
//bool* m_pIsShared;
//bool* m_pIsPotentiallySharable;
//VoxelType* m_pHomogenousValue;
Block<VoxelType>* m_pBlocks; Block<VoxelType>* m_pBlocks;
mutable std::map<VoxelType, BlockData<VoxelType>*> m_pHomogenousBlocks; mutable std::map<VoxelType, ReferenceCountedBlockData<VoxelType> > m_pHomogenousBlockData;
uint32 m_uNoOfBlocksInVolume; uint32 m_uNoOfBlocksInVolume;
uint16 m_uSideLengthInBlocks; uint16 m_uSideLengthInBlocks;

View File

@ -71,23 +71,23 @@ namespace PolyVox
//Create the blocks //Create the blocks
/*m_pBlocks = new Block<VoxelType>*[m_uNoOfBlocksInVolume]; /*m_pBlocks = new Block<VoxelType>*[m_uNoOfBlocksInVolume];
m_pIsShared = new bool[m_uNoOfBlocksInVolume]; m_bIsShared = new bool[m_uNoOfBlocksInVolume];
m_pIsPotentiallySharable = new bool[m_uNoOfBlocksInVolume]; m_bIsPotentiallySharable = new bool[m_uNoOfBlocksInVolume];
m_pHomogenousValue = new VoxelType[m_uNoOfBlocksInVolume]; m_pHomogenousValue = new VoxelType[m_uNoOfBlocksInVolume];
for(uint32 i = 0; i < m_uNoOfBlocksInVolume; ++i) for(uint32 i = 0; i < m_uNoOfBlocksInVolume; ++i)
{ {
m_pBlocks[i] = getHomogenousBlock(0); m_pBlocks[i] = getHomogenousBlock(0);
m_pIsShared[i] = true; m_bIsShared[i] = true;
m_pIsPotentiallySharable[i] = false; m_bIsPotentiallySharable[i] = false;
m_pHomogenousValue[i] = 0; m_pHomogenousValue[i] = 0;
}*/ }*/
m_pBlocks = new Block<VoxelType>[m_uNoOfBlocksInVolume]; m_pBlocks = new Block<VoxelType>[m_uNoOfBlocksInVolume];
for(uint32 i = 0; i < m_uNoOfBlocksInVolume; ++i) for(uint32 i = 0; i < m_uNoOfBlocksInVolume; ++i)
{ {
m_pBlocks[i].m_pBlockData = getHomogenousBlock(0); m_pBlocks[i].m_pBlockData = getHomogenousBlockData(0);
m_pBlocks[i].m_pIsShared = true; m_pBlocks[i].m_bIsShared = true;
m_pBlocks[i].m_pIsPotentiallySharable = false; m_pBlocks[i].m_bIsPotentiallySharable = false;
m_pBlocks[i].m_pHomogenousValue = 0; m_pBlocks[i].m_pHomogenousValue = 0;
} }
} }
@ -103,15 +103,15 @@ namespace PolyVox
{ {
for(uint32 i = 0; i < m_uNoOfBlocksInVolume; ++i) for(uint32 i = 0; i < m_uNoOfBlocksInVolume; ++i)
{ {
if(m_pBlocks[i].m_pIsShared == false) if(m_pBlocks[i].m_bIsShared == false)
{ {
delete m_pBlocks[i].m_pBlockData; delete m_pBlocks[i].m_pBlockData;
m_pBlocks[i].m_pBlockData = 0; m_pBlocks[i].m_pBlockData = 0;
} }
} }
delete[] m_pBlocks; delete[] m_pBlocks;
/*delete[] m_pIsShared; /*delete[] m_bIsShared;
delete[] m_pIsPotentiallySharable; delete[] m_bIsPotentiallySharable;
delete[] m_pHomogenousValue;*/ delete[] m_pHomogenousValue;*/
} }
#pragma endregion #pragma endregion
@ -190,14 +190,14 @@ namespace PolyVox
blockY * m_uSideLengthInBlocks + blockY * m_uSideLengthInBlocks +
blockZ * m_uSideLengthInBlocks * m_uSideLengthInBlocks; blockZ * m_uSideLengthInBlocks * m_uSideLengthInBlocks;
const bool bIsShared = m_pBlocks[uBlockIndex].m_pIsShared; const bool bIsShared = m_pBlocks[uBlockIndex].m_bIsShared;
if(bIsShared) if(bIsShared)
{ {
const VoxelType tHomogenousValue = m_pBlocks[uBlockIndex].m_pHomogenousValue; const VoxelType tHomogenousValue = m_pBlocks[uBlockIndex].m_pHomogenousValue;
if(tHomogenousValue != tValue) if(tHomogenousValue != tValue)
{ {
m_pBlocks[uBlockIndex].m_pBlockData = new BlockData<VoxelType>(m_uBlockSideLength); m_pBlocks[uBlockIndex].m_pBlockData = new BlockData<VoxelType>(m_uBlockSideLength);
m_pBlocks[uBlockIndex].m_pIsShared = false; m_pBlocks[uBlockIndex].m_bIsShared = false;
m_pBlocks[uBlockIndex].m_pBlockData->fill(tHomogenousValue); m_pBlocks[uBlockIndex].m_pBlockData->fill(tHomogenousValue);
m_pBlocks[uBlockIndex].m_pBlockData->setVoxelAt(xOffset,yOffset,zOffset, tValue); m_pBlocks[uBlockIndex].m_pBlockData->setVoxelAt(xOffset,yOffset,zOffset, tValue);
} }
@ -207,7 +207,7 @@ namespace PolyVox
m_pBlocks[uBlockIndex].m_pBlockData->setVoxelAt(xOffset,yOffset,zOffset, tValue); m_pBlocks[uBlockIndex].m_pBlockData->setVoxelAt(xOffset,yOffset,zOffset, tValue);
//There is a chance that setting this voxel makes the block homogenous and therefore shareable. But checking //There is a chance that setting this voxel makes the block homogenous and therefore shareable. But checking
//this will take some time, so for now just set a flag. //this will take some time, so for now just set a flag.
m_pBlocks[uBlockIndex].m_pIsPotentiallySharable = true; m_pBlocks[uBlockIndex].m_bIsPotentiallySharable = true;
} }
} }
@ -230,6 +230,34 @@ namespace PolyVox
template <typename VoxelType> template <typename VoxelType>
void Volume<VoxelType>::idle(uint32 uAmount) void Volume<VoxelType>::idle(uint32 uAmount)
{ {
//This function performs two roles. Firstly, it examines all of the blocks which are marked as
//'potentially sharable' to determine whether they really are sharable or not. For those which
//are sharable, it adjusts the pointer and deletes tho old data. Secondly, it determines which
//homogeneous regions are not actually being used (by thier reference count) and frees them.
for(uint32 i = 0; i < m_uNoOfBlocksInVolume; ++i)
{
Block block = m_pBlocks[i];
if(block.m_bIsPotentiallySharable)
{
bool isSharable = block.m_pBlockData->isHomogeneous();
if(isSharable)
{
VoxelType homogeneousValue = block.m_pBlockData->getVoxelAt(0,0,0);
delete block.m_pBlockData;
block.m_pBlockData = getHomogenousBlockData(homogeneousValue);
block.m_pHomogenousValue = homogeneousValue;
block.m_bIsShared = true;
}
//Either way, we have now determined whether the block was sharable. So it's not *potentially* sharable.
block.m_bIsPotentiallySharable = false;
}
}
//Note - this second step should probably happen immediatly, rather than in this function.
//Use of a shared pointer system would allow this.
} }
template <typename VoxelType> template <typename VoxelType>
@ -265,17 +293,23 @@ namespace PolyVox
#pragma region Private Implementation #pragma region Private Implementation
template <typename VoxelType> template <typename VoxelType>
BlockData<VoxelType>* Volume<VoxelType>::getHomogenousBlock(VoxelType tHomogenousValue) const BlockData<VoxelType>* Volume<VoxelType>::getHomogenousBlockData(VoxelType tHomogenousValue) const
{ {
typename std::map<VoxelType, BlockData<VoxelType>*>::iterator iterResult = m_pHomogenousBlocks.find(tHomogenousValue); typename std::map<VoxelType, ReferenceCountedBlockData<VoxelType> >::iterator iterResult = m_pHomogenousBlockData.find(tHomogenousValue);
if(iterResult == m_pHomogenousBlocks.end()) if(iterResult == m_pHomogenousBlockData.end())
{ {
BlockData<VoxelType>* pBlock = new BlockData<VoxelType>(m_uBlockSideLength); ReferenceCountedBlockData<VoxelType> referenceCountedBlockData;
pBlock->fill(tHomogenousValue); referenceCountedBlockData.m_pBlockData = new BlockData<VoxelType>(m_uBlockSideLength);
m_pHomogenousBlocks.insert(std::make_pair(tHomogenousValue, pBlock)); referenceCountedBlockData.m_uReferenceCount++;
return pBlock; referenceCountedBlockData.m_pBlockData->fill(tHomogenousValue);
m_pHomogenousBlockData.insert(std::make_pair(tHomogenousValue, referenceCountedBlockData));
return referenceCountedBlockData.m_pBlockData;
}
else
{
iterResult->second.m_uReferenceCount++;
return iterResult->second.m_pBlockData;
} }
return iterResult->second;
} }
#pragma endregion #pragma endregion
} }