Moving Chunk to be a nested class of PagedVolume.
This commit is contained in:
parent
71035029d1
commit
db9a74fdb4
@ -90,7 +90,7 @@ public:
|
||||
/// Destructor
|
||||
virtual ~PerlinNoisePager() {};
|
||||
|
||||
virtual void pageIn(const PolyVox::Region& region, Chunk<MaterialDensityPair44>* pChunk)
|
||||
virtual void pageIn(const PolyVox::Region& region, PagedVolume<MaterialDensityPair44>::Chunk* pChunk)
|
||||
{
|
||||
Perlin perlin(2,2,1,234);
|
||||
|
||||
@ -134,7 +134,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void pageOut(const PolyVox::Region& region, Chunk<MaterialDensityPair44>* /*pChunk*/)
|
||||
virtual void pageOut(const PolyVox::Region& region, PagedVolume<MaterialDensityPair44>::Chunk* /*pChunk*/)
|
||||
{
|
||||
std::cout << "warning unloading region: " << region.getLowerCorner() << " -> " << region.getUpperCorner() << std::endl;
|
||||
}
|
||||
|
@ -38,8 +38,6 @@ SET(CORE_INC_FILES
|
||||
include/PolyVoxCore/BaseVolume.h
|
||||
include/PolyVoxCore/BaseVolume.inl
|
||||
include/PolyVoxCore/BaseVolumeSampler.inl
|
||||
include/PolyVoxCore/Chunk.h
|
||||
include/PolyVoxCore/Chunk.inl
|
||||
include/PolyVoxCore/CubicSurfaceExtractor.h
|
||||
include/PolyVoxCore/CubicSurfaceExtractor.inl
|
||||
include/PolyVoxCore/DefaultIsQuadNeeded.h
|
||||
@ -62,6 +60,7 @@ SET(CORE_INC_FILES
|
||||
include/PolyVoxCore/Mesh.inl
|
||||
include/PolyVoxCore/PagedVolume.h
|
||||
include/PolyVoxCore/PagedVolume.inl
|
||||
include/PolyVoxCore/PagedVolumeChunk.inl
|
||||
include/PolyVoxCore/PagedVolumeSampler.inl
|
||||
include/PolyVoxCore/Pager.h
|
||||
include/PolyVoxCore/PolyVoxForwardDeclarations.h
|
||||
|
@ -1,77 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2005-2013 David Williams and Matthew Williams
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __PolyVox_Chunk_H__
|
||||
#define __PolyVox_Chunk_H__
|
||||
|
||||
#include "PolyVoxCore/PolyVoxForwardDeclarations.h"
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
class Chunk
|
||||
{
|
||||
friend class PagedVolume<VoxelType>;
|
||||
|
||||
public:
|
||||
Chunk(Vector3DInt32 v3dPosition, uint16_t uSideLength, Pager<VoxelType>* pPager = nullptr);
|
||||
~Chunk();
|
||||
|
||||
VoxelType* getData(void) const;
|
||||
uint32_t getDataSizeInBytes(void) const;
|
||||
|
||||
VoxelType getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const;
|
||||
VoxelType getVoxel(const Vector3DUint16& v3dPos) const;
|
||||
|
||||
void setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue);
|
||||
void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue);
|
||||
|
||||
private:
|
||||
/// Private copy constructor to prevent accisdental copying
|
||||
Chunk(const Chunk& /*rhs*/) {};
|
||||
|
||||
/// Private assignment operator to prevent accisdental copying
|
||||
Chunk& operator=(const Chunk& /*rhs*/) {};
|
||||
|
||||
// This is updated by the PagedVolume and used to discard the least recently used chunks.
|
||||
uint32_t m_uChunkLastAccessed;
|
||||
|
||||
// This is so we can tell whether a uncompressed chunk has to be recompressed and whether
|
||||
// a compressed chunk has to be paged back to disk, or whether they can just be discarded.
|
||||
bool m_bDataModified;
|
||||
|
||||
uint32_t calculateSizeInBytes(void);
|
||||
static uint32_t calculateSizeInBytes(uint32_t uSideLength);
|
||||
|
||||
VoxelType* m_tData;
|
||||
uint16_t m_uSideLength;
|
||||
uint8_t m_uSideLengthPower;
|
||||
Pager<VoxelType>* m_pPager;
|
||||
Vector3DInt32 m_v3dChunkSpacePosition;
|
||||
};
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/Chunk.inl"
|
||||
|
||||
#endif
|
@ -76,10 +76,10 @@ namespace PolyVox
|
||||
m_vecCreatedFiles.clear();
|
||||
}
|
||||
|
||||
virtual void pageIn(const Region& region, Chunk<VoxelType>* pChunk)
|
||||
virtual void pageIn(const Region& region, typename PagedVolume<VoxelType>::Chunk* pChunk)
|
||||
{
|
||||
POLYVOX_ASSERT(pChunk, "Attempting to page in NULL chunk");
|
||||
POLYVOX_ASSERT(pChunk->getData() == false, "Chunk must have valid data");
|
||||
POLYVOX_ASSERT(pChunk->getData(), "Chunk must have valid data");
|
||||
|
||||
std::stringstream ssFilename;
|
||||
ssFilename << m_strFolderName << "/" << m_strRandomPrefix << "-"
|
||||
@ -120,10 +120,10 @@ namespace PolyVox
|
||||
}
|
||||
}
|
||||
|
||||
virtual void pageOut(const Region& region, Chunk<VoxelType>* pChunk)
|
||||
virtual void pageOut(const Region& region, typename PagedVolume<VoxelType>::Chunk* pChunk)
|
||||
{
|
||||
POLYVOX_ASSERT(pChunk, "Attempting to page out NULL chunk");
|
||||
POLYVOX_ASSERT(pChunk->getData() == false, "Chunk must have valid data");
|
||||
POLYVOX_ASSERT(pChunk->getData(), "Chunk must have valid data");
|
||||
|
||||
POLYVOX_LOG_TRACE("Paging out data for " << region);
|
||||
|
||||
|
@ -27,7 +27,6 @@ freely, subject to the following restrictions:
|
||||
#include "PolyVoxCore/BaseVolume.h"
|
||||
#include "PolyVoxCore/Pager.h"
|
||||
#include "PolyVoxCore/Region.h"
|
||||
#include "PolyVoxCore/Chunk.h"
|
||||
#include "PolyVoxCore/Vector.h"
|
||||
|
||||
#include <limits>
|
||||
@ -157,6 +156,46 @@ namespace PolyVox
|
||||
class PagedVolume : public BaseVolume<VoxelType>
|
||||
{
|
||||
public:
|
||||
|
||||
class Chunk
|
||||
{
|
||||
public:
|
||||
Chunk(Vector3DInt32 v3dPosition, uint16_t uSideLength, Pager<VoxelType>* pPager = nullptr);
|
||||
~Chunk();
|
||||
|
||||
VoxelType* getData(void) const;
|
||||
uint32_t getDataSizeInBytes(void) const;
|
||||
|
||||
VoxelType getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const;
|
||||
VoxelType getVoxel(const Vector3DUint16& v3dPos) const;
|
||||
|
||||
void setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue);
|
||||
void setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue);
|
||||
|
||||
public:
|
||||
/// Private copy constructor to prevent accisdental copying
|
||||
Chunk(const Chunk& /*rhs*/) {};
|
||||
|
||||
/// Private assignment operator to prevent accisdental copying
|
||||
Chunk& operator=(const Chunk& /*rhs*/) {};
|
||||
|
||||
// This is updated by the PagedVolume and used to discard the least recently used chunks.
|
||||
uint32_t m_uChunkLastAccessed;
|
||||
|
||||
// This is so we can tell whether a uncompressed chunk has to be recompressed and whether
|
||||
// a compressed chunk has to be paged back to disk, or whether they can just be discarded.
|
||||
bool m_bDataModified;
|
||||
|
||||
uint32_t calculateSizeInBytes(void);
|
||||
static uint32_t calculateSizeInBytes(uint32_t uSideLength);
|
||||
|
||||
VoxelType* m_tData;
|
||||
uint16_t m_uSideLength;
|
||||
uint8_t m_uSideLengthPower;
|
||||
Pager<VoxelType>* m_pPager;
|
||||
Vector3DInt32 m_v3dChunkSpacePosition;
|
||||
};
|
||||
|
||||
//There seems to be some descrepency between Visual Studio and GCC about how the following class should be declared.
|
||||
//There is a work around (see also See http://goo.gl/qu1wn) given below which appears to work on VS2010 and GCC, but
|
||||
//which seems to cause internal compiler errors on VS2008 when building with the /Gm 'Enable Minimal Rebuild' compiler
|
||||
@ -285,8 +324,8 @@ namespace PolyVox
|
||||
|
||||
private:
|
||||
|
||||
typedef std::unordered_map<Vector3DInt32, std::shared_ptr< Chunk<VoxelType> > > SharedPtrChunkMap;
|
||||
typedef std::unordered_map<Vector3DInt32, std::weak_ptr< Chunk<VoxelType> > > WeakPtrChunkMap;
|
||||
typedef std::unordered_map<Vector3DInt32, std::shared_ptr< Chunk > > SharedPtrChunkMap;
|
||||
typedef std::unordered_map<Vector3DInt32, std::weak_ptr< Chunk > > WeakPtrChunkMap;
|
||||
|
||||
void initialise();
|
||||
|
||||
@ -298,7 +337,7 @@ namespace PolyVox
|
||||
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::Border>, VoxelType tBorder) const;
|
||||
VoxelType getVoxelImpl(int32_t uXPos, int32_t uYPos, int32_t uZPos, WrapModeType<WrapModes::AssumeValid>, VoxelType tBorder) const;
|
||||
|
||||
std::shared_ptr< Chunk<VoxelType> > getChunk(int32_t uChunkX, int32_t uChunkY, int32_t uChunkZ) const;
|
||||
std::shared_ptr<Chunk> getChunk(int32_t uChunkX, int32_t uChunkY, int32_t uChunkZ) const;
|
||||
|
||||
void purgeNullPtrsFromAllChunks(void) const;
|
||||
|
||||
@ -308,7 +347,7 @@ namespace PolyVox
|
||||
|
||||
mutable uint32_t m_uTimestamper;
|
||||
mutable Vector3DInt32 m_v3dLastAccessedChunkPos;
|
||||
mutable std::shared_ptr< Chunk<VoxelType> > m_pLastAccessedChunk;
|
||||
mutable std::shared_ptr<Chunk> m_pLastAccessedChunk;
|
||||
uint32_t m_uChunkCountLimit;
|
||||
|
||||
// The size of the volume
|
||||
@ -328,6 +367,7 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
#include "PolyVoxCore/PagedVolume.inl"
|
||||
#include "PolyVoxCore/PagedVolumeChunk.inl"
|
||||
#include "PolyVoxCore/PagedVolumeSampler.inl"
|
||||
|
||||
#endif //__PolyVox_PagedVolume_H__
|
||||
|
@ -81,7 +81,7 @@ namespace PolyVox
|
||||
m_uChunkCountLimit = (std::max)(m_uChunkCountLimit, uMinPracticalNoOfChunks);
|
||||
m_uChunkCountLimit = (std::min)(m_uChunkCountLimit, uMaxPracticalNoOfChunks);
|
||||
|
||||
uint32_t uChunkSizeInBytes = Chunk<VoxelType>::calculateSizeInBytes(m_uChunkSideLength);
|
||||
uint32_t uChunkSizeInBytes = PagedVolume<VoxelType>::Chunk::calculateSizeInBytes(m_uChunkSideLength);
|
||||
POLYVOX_LOG_DEBUG("Memory usage limit for volume initially set to " << (m_uChunkCountLimit * uChunkSizeInBytes) / (1024 * 1024)
|
||||
<< "Mb (" << m_uChunkCountLimit << " chunks of " << uChunkSizeInBytes / 1024 << "Kb each).");
|
||||
|
||||
@ -254,7 +254,7 @@ namespace PolyVox
|
||||
POLYVOX_THROW_IF(!m_pPager, invalid_operation, "You cannot limit the memory usage of the volume because it was created without a pager attached.");
|
||||
|
||||
// Calculate the number of chunks based on the memory limit and the size of each chunk.
|
||||
uint32_t uChunkSizeInBytes = Chunk<VoxelType>::calculateSizeInBytes(m_uChunkSideLength);
|
||||
uint32_t uChunkSizeInBytes = PagedVolume<VoxelType>::Chunk::calculateSizeInBytes(m_uChunkSideLength);
|
||||
m_uChunkCountLimit = uMemoryUsageInBytes / uChunkSizeInBytes;
|
||||
|
||||
// We need at least a few chunks available to avoid thrashing, and in pratice there will probably be hundreds.
|
||||
@ -506,7 +506,7 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
std::shared_ptr< Chunk<VoxelType> > PagedVolume<VoxelType>::getChunk(int32_t uChunkX, int32_t uChunkY, int32_t uChunkZ) const
|
||||
std::shared_ptr<typename PagedVolume<VoxelType>::Chunk> PagedVolume<VoxelType>::getChunk(int32_t uChunkX, int32_t uChunkY, int32_t uChunkZ) const
|
||||
{
|
||||
Vector3DInt32 v3dChunkPos(uChunkX, uChunkY, uChunkZ);
|
||||
|
||||
@ -520,7 +520,7 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
// The chunk was not the same as last time, but we can now hope it is in the set of most recently used chunks.
|
||||
std::shared_ptr< Chunk<VoxelType> > pChunk = nullptr;
|
||||
std::shared_ptr<typename PagedVolume<VoxelType>::Chunk> pChunk = nullptr;
|
||||
typename SharedPtrChunkMap::iterator itChunk = m_pRecentlyUsedChunks.find(v3dChunkPos);
|
||||
|
||||
// Check whether the chunk was found.
|
||||
@ -548,7 +548,7 @@ namespace PolyVox
|
||||
else
|
||||
{
|
||||
// The chunk is valid. We know it's not in the recently used list (we checked earlier) so it should be added.
|
||||
pChunk = std::shared_ptr< Chunk<VoxelType> >(itWeakChunk->second);
|
||||
pChunk = std::shared_ptr< PagedVolume<VoxelType>::Chunk >(itWeakChunk->second);
|
||||
m_pRecentlyUsedChunks.insert(std::make_pair(v3dChunkPos, pChunk));
|
||||
}
|
||||
}
|
||||
@ -558,7 +558,7 @@ namespace PolyVox
|
||||
if (!pChunk)
|
||||
{
|
||||
// The chunk was not found so we will create a new one.
|
||||
pChunk = std::make_shared< Chunk<VoxelType> >(v3dChunkPos, m_uChunkSideLength, m_pPager);
|
||||
pChunk = std::make_shared< PagedVolume<VoxelType>::Chunk >(v3dChunkPos, m_uChunkSideLength, m_pPager);
|
||||
|
||||
// As we are loading a new chunk we should try to ensure we don't go over our target memory usage.
|
||||
bool erasedChunk = false;
|
||||
@ -613,7 +613,7 @@ namespace PolyVox
|
||||
|
||||
// Note: We disregard the size of the other class members as they are likely to be very small compared to the size of the
|
||||
// allocated voxel data. This also keeps the reported size as a power of two, which makes other memory calculations easier.
|
||||
return Chunk<VoxelType>::calculateSizeInBytes(m_uChunkSideLength) * m_pAllChunks.size();
|
||||
return PagedVolume<VoxelType>::Chunk::calculateSizeInBytes(m_uChunkSideLength) * m_pAllChunks.size();
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
|
@ -26,7 +26,7 @@ freely, subject to the following restrictions:
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
Chunk<VoxelType>::Chunk(Vector3DInt32 v3dPosition, uint16_t uSideLength, Pager<VoxelType>* pPager)
|
||||
PagedVolume<VoxelType>::Chunk::Chunk(Vector3DInt32 v3dPosition, uint16_t uSideLength, Pager<VoxelType>* pPager)
|
||||
:m_uChunkLastAccessed(0)
|
||||
,m_bDataModified(true)
|
||||
,m_tData(0)
|
||||
@ -65,7 +65,7 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
Chunk<VoxelType>::~Chunk()
|
||||
PagedVolume<VoxelType>::Chunk::~Chunk()
|
||||
{
|
||||
if (m_pPager && m_bDataModified)
|
||||
{
|
||||
@ -82,19 +82,19 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType* Chunk<VoxelType>::getData(void) const
|
||||
VoxelType* PagedVolume<VoxelType>::Chunk::getData(void) const
|
||||
{
|
||||
return m_tData;
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
uint32_t Chunk<VoxelType>::getDataSizeInBytes(void) const
|
||||
uint32_t PagedVolume<VoxelType>::Chunk::getDataSizeInBytes(void) const
|
||||
{
|
||||
return m_uSideLength * m_uSideLength * m_uSideLength * sizeof(VoxelType);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType Chunk<VoxelType>::getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const
|
||||
VoxelType PagedVolume<VoxelType>::Chunk::getVoxel(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos) const
|
||||
{
|
||||
// This code is not usually expected to be called by the user, with the exception of when implementing paging
|
||||
// of uncompressed data. It's a performance critical code path so we use asserts rather than exceptions.
|
||||
@ -112,13 +112,13 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
VoxelType Chunk<VoxelType>::getVoxel(const Vector3DUint16& v3dPos) const
|
||||
VoxelType PagedVolume<VoxelType>::Chunk::getVoxel(const Vector3DUint16& v3dPos) const
|
||||
{
|
||||
return getVoxel(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ());
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void Chunk<VoxelType>::setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue)
|
||||
void PagedVolume<VoxelType>::Chunk::setVoxelAt(uint16_t uXPos, uint16_t uYPos, uint16_t uZPos, VoxelType tValue)
|
||||
{
|
||||
// This code is not usually expected to be called by the user, with the exception of when implementing paging
|
||||
// of uncompressed data. It's a performance critical code path so we use asserts rather than exceptions.
|
||||
@ -138,20 +138,20 @@ namespace PolyVox
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void Chunk<VoxelType>::setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue)
|
||||
void PagedVolume<VoxelType>::Chunk::setVoxelAt(const Vector3DUint16& v3dPos, VoxelType tValue)
|
||||
{
|
||||
setVoxelAt(v3dPos.getX(), v3dPos.getY(), v3dPos.getZ(), tValue);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
uint32_t Chunk<VoxelType>::calculateSizeInBytes(void)
|
||||
uint32_t PagedVolume<VoxelType>::Chunk::calculateSizeInBytes(void)
|
||||
{
|
||||
// Call through to the static version
|
||||
return calculateSizeInBytes(m_uSideLength);
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
uint32_t Chunk<VoxelType>::calculateSizeInBytes(uint32_t uSideLength)
|
||||
uint32_t PagedVolume<VoxelType>::Chunk::calculateSizeInBytes(uint32_t uSideLength)
|
||||
{
|
||||
// Note: We disregard the size of the other class members as they are likely to be very small compared to the size of the
|
||||
// allocated voxel data. This also keeps the reported size as a power of two, which makes other memory calculations easier.
|
@ -24,7 +24,7 @@ freely, subject to the following restrictions:
|
||||
#ifndef __PolyVox_Pager_H__
|
||||
#define __PolyVox_Pager_H__
|
||||
|
||||
#include "PolyVoxCore/Chunk.h"
|
||||
#include "PolyVoxCore/PagedVolume.h"
|
||||
#include "PolyVoxCore/Impl/TypeDef.h"
|
||||
|
||||
#include <memory>
|
||||
@ -43,8 +43,8 @@ namespace PolyVox
|
||||
/// Destructor
|
||||
virtual ~Pager() {};
|
||||
|
||||
virtual void pageIn(const Region& region, Chunk<VoxelType>* pChunk) = 0;
|
||||
virtual void pageOut(const Region& region, Chunk<VoxelType>* pChunk) = 0;
|
||||
virtual void pageIn(const Region& region, typename PagedVolume<VoxelType>::Chunk* pChunk) = 0;
|
||||
virtual void pageOut(const Region& region, typename PagedVolume<VoxelType>::Chunk* pChunk) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user