More flush/prefetch work from ker.
This commit is contained in:
parent
78c5884303
commit
a364f6d72c
@ -29,6 +29,7 @@ freely, subject to the following restrictions:
|
|||||||
#include "SurfaceExtractor.h"
|
#include "SurfaceExtractor.h"
|
||||||
#include "SurfaceMesh.h"
|
#include "SurfaceMesh.h"
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
#include "Filters.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
@ -249,18 +250,17 @@ int main(int argc, char *argv[])
|
|||||||
OpenGLWidget openGLWidget(0);
|
OpenGLWidget openGLWidget(0);
|
||||||
openGLWidget.show();
|
openGLWidget.show();
|
||||||
|
|
||||||
//Create an empty volume and then place a sphere in it
|
//If these lines don't compile, please try commenting them out and using the two lines after
|
||||||
|
//(you will need Boost for this). If you have to do this then please let us know in the forums as
|
||||||
|
//we rely on community feedback to keep the Boost version running.
|
||||||
Volume<MaterialDensityPair44> volData(&load, &unload, 256);
|
Volume<MaterialDensityPair44> volData(&load, &unload, 256);
|
||||||
|
//Volume<MaterialDensityPair44> volData(polyvox_bind(&load, polyvox_placeholder_1, polyvox_placeholder_2),
|
||||||
|
// polyvox_bind(&unload, polyvox_placeholder_1, polyvox_placeholder_2), 256);
|
||||||
volData.setMaxNumberOfBlocksInMemory(4096);
|
volData.setMaxNumberOfBlocksInMemory(4096);
|
||||||
volData.setMaxNumberOfUncompressedBlocks(64);
|
volData.setMaxNumberOfUncompressedBlocks(64);
|
||||||
|
|
||||||
//If these two lines don't compile, please try commenting them out and using the two lines after
|
|
||||||
//(you will need Boost for this). If you have to do this then please let us know in the forums as
|
|
||||||
//we rely on community feedback to keep the Boost version running.
|
|
||||||
//volData.dataRequiredHandler = &load;
|
//volData.dataRequiredHandler = &load;
|
||||||
//volData.dataOverflowHandler = &unload;
|
//volData.dataOverflowHandler = &unload;
|
||||||
//volData.dataRequiredHandler = polyvox_bind(&load, polyvox_placeholder_1, polyvox_placeholder_2);
|
|
||||||
//volData.dataOverflowHandler = polyvox_bind(&unload, polyvox_placeholder_1, polyvox_placeholder_2);
|
|
||||||
|
|
||||||
//volData.setMaxNumberOfUncompressedBlocks(4096);
|
//volData.setMaxNumberOfUncompressedBlocks(4096);
|
||||||
//createSphereInVolume(volData, 30);
|
//createSphereInVolume(volData, 30);
|
||||||
@ -271,30 +271,38 @@ int main(int argc, char *argv[])
|
|||||||
//volData.setBlockCacheSize(64);
|
//volData.setBlockCacheSize(64);
|
||||||
PolyVox::Region reg(Vector3DInt32(-255,0,0), Vector3DInt32(255,1024,255));
|
PolyVox::Region reg(Vector3DInt32(-255,0,0), Vector3DInt32(255,1024,255));
|
||||||
std::cout << "Prefetching region: " << reg.getLowerCorner() << " -> " << reg.getUpperCorner() << std::endl;
|
std::cout << "Prefetching region: " << reg.getLowerCorner() << " -> " << reg.getUpperCorner() << std::endl;
|
||||||
volData.prefetchRegion(reg);
|
volData.prefetch(reg);
|
||||||
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
||||||
std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
||||||
PolyVox::Region reg2(Vector3DInt32(0,0,0), Vector3DInt32(500,500,500));
|
PolyVox::Region reg2(Vector3DInt32(0,0,0), Vector3DInt32(500,500,500));
|
||||||
std::cout << "Flushing region: " << reg2.getLowerCorner() << " -> " << reg2.getUpperCorner() << std::endl;
|
std::cout << "Flushing region: " << reg2.getLowerCorner() << " -> " << reg2.getUpperCorner() << std::endl;
|
||||||
uint32_t voxelsFlushed = volData.flushRegion(reg2);
|
volData.flush(reg2);
|
||||||
Vector3DInt32 size = reg2.getUpperCorner() - reg2.getLowerCorner() + Vector3DInt32(1,1,1);
|
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
||||||
uint32_t voxelsFlushed2 = size.getX()*size.getY()*size.getZ();
|
std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
||||||
std::cout << voxelsFlushed << " Voxels were unloaded, while " << voxelsFlushed2 << " should have been unloaded" << std::endl;
|
std::cout << "Flushing entire volume" << std::endl;
|
||||||
|
volData.flushAll();
|
||||||
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
std::cout << "Memory usage: " << (volData.calculateSizeInBytes()/1024.0/1024.0) << "MB" << std::endl;
|
||||||
std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl;
|
||||||
|
|
||||||
/*srand(12345);
|
srand(12345);
|
||||||
for(int ct = 0; ct < 1000; ct++)
|
for(int ct = 0; ct < 100; ct++)
|
||||||
{
|
{
|
||||||
std::cout << ct << std::endl;
|
std::cout << ct << std::endl;
|
||||||
int x = rand() % volData.getWidth();
|
int x = rand() % 256;
|
||||||
int y = rand() % volData.getHeight();
|
int y = rand() % 256;
|
||||||
int z = rand() % volData.getDepth();
|
int z = rand() % 256;
|
||||||
|
|
||||||
int r = rand() % 20;
|
int r = rand() % 20;
|
||||||
|
|
||||||
createSphereInVolume(volData, Vector3DFloat(x,y,z), r);
|
createSphereInVolume(volData, Vector3DFloat(x,y,z), r);
|
||||||
}*/
|
}
|
||||||
|
|
||||||
|
smoothRegion(volData, PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(128,256,256)));
|
||||||
|
smoothRegion(volData, PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(128,256,256)));
|
||||||
|
smoothRegion(volData, PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(128,256,256)));
|
||||||
|
smoothRegion(volData, PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(256,128,256)));
|
||||||
|
smoothRegion(volData, PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(256,128,256)));
|
||||||
|
smoothRegion(volData, PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(256,128,256)));
|
||||||
|
|
||||||
//Extract the surface
|
//Extract the surface
|
||||||
SurfaceMesh<PositionMaterialNormal> mesh;
|
SurfaceMesh<PositionMaterialNormal> mesh;
|
||||||
|
@ -186,17 +186,18 @@ namespace PolyVox
|
|||||||
bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue);
|
bool setVoxelAt(int32_t uXPos, int32_t uYPos, int32_t uZPos, VoxelType tValue);
|
||||||
/// Sets the voxel at a 3D vector position
|
/// Sets the voxel at a 3D vector position
|
||||||
bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue);
|
bool setVoxelAt(const Vector3DInt32& v3dPos, VoxelType tValue);
|
||||||
/// makes sure all the voxels in the given region are loaded
|
/// tries to load all voxels inside the given region
|
||||||
/// if MaxNumberOfBlocksInMemory is not large enough to support the region
|
/// if MaxNumberOfBlocksInMemory is not large enough to support the region
|
||||||
/// this function will return false and the volume is unchanged
|
/// this function will only load part of the region. it is undefined which parts will actually be loaded
|
||||||
/// if all the voxels in the given region are already loaded, this function will not do anything but still return true.
|
/// if all the voxels in the given region are already loaded, this function will not do anything
|
||||||
/// other blocks might be unloaded to make space for the new blocks
|
/// other blocks might be unloaded to make space for the new blocks
|
||||||
bool prefetchRegion(Region regPrefetch);
|
void prefetch(Region regPrefetch);
|
||||||
/// attempts to unload all the voxels in the given region.
|
/// attempts to unload all the voxels in the given region.
|
||||||
/// there is no guarantee that any voxels are unloaded
|
/// there is no guarantee that any voxels are unloaded
|
||||||
/// try unloading a region whose sidelengths are multiples of BlockSideLength
|
/// try unloading a region whose sidelengths are multiples of BlockSideLength
|
||||||
/// returns the number of voxels that were actually unloaded
|
void flush(Region regFlush);
|
||||||
uint32_t flushRegion(Region regFlush);
|
/// unloads all data
|
||||||
|
void flushAll();
|
||||||
|
|
||||||
void clearBlockCache(void);
|
void clearBlockCache(void);
|
||||||
float calculateCompressionRatio(void);
|
float calculateCompressionRatio(void);
|
||||||
|
@ -129,10 +129,7 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
Volume<VoxelType>::~Volume()
|
Volume<VoxelType>::~Volume()
|
||||||
{
|
{
|
||||||
typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
|
flushAll();
|
||||||
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i = m_pBlocks.begin()) {
|
|
||||||
eraseBlock(i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -302,25 +299,9 @@ namespace PolyVox
|
|||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
void Volume<VoxelType>::setMaxNumberOfBlocksInMemory(uint16_t uMaxNumberOfBlocksInMemory)
|
void Volume<VoxelType>::setMaxNumberOfBlocksInMemory(uint16_t uMaxNumberOfBlocksInMemory)
|
||||||
{
|
{
|
||||||
//FIXME? - I'm concerned about the logic in here... particularly the
|
|
||||||
//way timestamps are handled. Perhaps extract all timestamps, sort them,
|
|
||||||
//identify the cut-off point, and then discard those above it?
|
|
||||||
if(m_pBlocks.size() > uMaxNumberOfBlocksInMemory)
|
if(m_pBlocks.size() > uMaxNumberOfBlocksInMemory)
|
||||||
{
|
{
|
||||||
// we need to unload some blocks
|
flushAll();
|
||||||
for(int j = 0; j < m_pBlocks.size() - uMaxNumberOfBlocksInMemory; j++)
|
|
||||||
{
|
|
||||||
typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
|
|
||||||
typename std::map<Vector3DInt32, LoadedBlock >::iterator itUnloadBlock = m_pBlocks.begin();
|
|
||||||
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
|
|
||||||
{
|
|
||||||
if(i->second.timestamp < itUnloadBlock->second.timestamp)
|
|
||||||
{
|
|
||||||
itUnloadBlock = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
eraseBlock(itUnloadBlock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m_uMaxNumberOfBlocksInMemory = uMaxNumberOfBlocksInMemory;
|
m_uMaxNumberOfBlocksInMemory = uMaxNumberOfBlocksInMemory;
|
||||||
}
|
}
|
||||||
@ -376,60 +357,106 @@ namespace PolyVox
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
bool Volume<VoxelType>::prefetchRegion(Region regPrefetch)
|
void Volume<VoxelType>::prefetch(Region regPrefetch)
|
||||||
{
|
{
|
||||||
Vector3DInt32 start;
|
Vector3DInt32 v3dStart;
|
||||||
for(int i = 0; i < 3; i++) start.setElement(i, regPrefetch.getLowerCorner().getElement(i) >> m_uBlockSideLengthPower);
|
for(int i = 0; i < 3; i++)
|
||||||
Vector3DInt32 end;
|
{
|
||||||
for(int i = 0; i < 3; i++) end.setElement(i, regPrefetch.getUpperCorner().getElement(i) >> m_uBlockSideLengthPower);
|
v3dStart.setElement(i, regPrefetch.getLowerCorner().getElement(i) >> m_uBlockSideLengthPower);
|
||||||
Vector3DInt32 size = end-start + Vector3DInt32(1,1,1);
|
|
||||||
int32_t numblocks = size.getX() * size.getY() * size.getZ();
|
|
||||||
if(numblocks > m_uMaxNumberOfBlocksInMemory) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if(numblocks > (m_uMaxNumberOfBlocksInMemory - m_pBlocks.size())) {
|
|
||||||
// TODO: unload enough blocks to support the blocks that will be loaded.
|
Vector3DInt32 v3dEnd;
|
||||||
|
for(int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
v3dEnd.setElement(i, regPrefetch.getUpperCorner().getElement(i) >> m_uBlockSideLengthPower);
|
||||||
}
|
}
|
||||||
for(int32_t x = start.getX(); x <= end.getX(); x++) {
|
|
||||||
for(int32_t y = start.getY(); y <= end.getY(); y++) {
|
Vector3DInt32 v3dSize = v3dEnd - v3dStart + Vector3DInt32(1,1,1);
|
||||||
for(int32_t z = start.getZ(); z <= end.getZ(); z++) {
|
int32_t numblocks = v3dSize.getX() * v3dSize.getY() * v3dSize.getZ();
|
||||||
|
if(numblocks > m_uMaxNumberOfBlocksInMemory)
|
||||||
|
{
|
||||||
|
// cannot support the amount of blocks... so only load the maximum possible
|
||||||
|
numblocks = m_uMaxNumberOfBlocksInMemory;
|
||||||
|
}
|
||||||
|
for(int32_t x = v3dStart.getX(); x <= v3dEnd.getX(); x++)
|
||||||
|
{
|
||||||
|
for(int32_t y = v3dStart.getY(); y <= v3dEnd.getY(); y++)
|
||||||
|
{
|
||||||
|
for(int32_t z = v3dStart.getZ(); z <= v3dEnd.getZ(); z++)
|
||||||
|
{
|
||||||
|
Vector3DInt32 pos(x,y,z);
|
||||||
|
typename std::map<Vector3DInt32, LoadedBlock>::iterator itBlock = m_pBlocks.find(pos);
|
||||||
|
|
||||||
|
// If the block is already loaded then we don't load it again. This means it does not get uncompressed,
|
||||||
|
// whereas if we were to call getUncompressedBlock() regardless then it would also get uncompressed.
|
||||||
|
// This might be nice, but on the prefetch region could be bigger than the uncompressed cache size.
|
||||||
|
// This would limit the amount of prefetching we could do.
|
||||||
|
if(itBlock != m_pBlocks.end())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(numblocks == 0)
|
||||||
|
{
|
||||||
|
// Loading any more blocks would attempt to overflow the memory and therefore erase blocks
|
||||||
|
// we loaded in the beginning. This wouldn't cause logic problems but would be wasteful.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// load a block
|
||||||
|
numblocks--;
|
||||||
Block<VoxelType>* block = getUncompressedBlock(x,y,z);
|
Block<VoxelType>* block = getUncompressedBlock(x,y,z);
|
||||||
}
|
} // for z
|
||||||
}
|
} // for y
|
||||||
}
|
} // for x
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
uint32_t Volume<VoxelType>::flushRegion(Region regFlush)
|
void Volume<VoxelType>::flushAll()
|
||||||
{
|
{
|
||||||
Vector3DInt32 start;
|
typename std::map<Vector3DInt32, LoadedBlock >::iterator i;
|
||||||
for(int i = 0; i < 3; i++) start.setElement(i, regFlush.getLowerCorner().getElement(i) >> m_uBlockSideLengthPower);
|
for(i = m_pBlocks.begin(); i != m_pBlocks.end(); i++)
|
||||||
Vector3DInt32 end;
|
{
|
||||||
for(int i = 0; i < 3; i++) end.setElement(i, regFlush.getUpperCorner().getElement(i) >> m_uBlockSideLengthPower);
|
eraseBlock(i);
|
||||||
uint32_t count = 0;
|
}
|
||||||
for(int32_t x = start.getX(); x <= end.getX(); x++) {
|
}
|
||||||
for(int32_t y = start.getY(); y <= end.getY(); y++) {
|
|
||||||
for(int32_t z = start.getZ(); z <= end.getZ(); z++) {
|
template <typename VoxelType>
|
||||||
|
void Volume<VoxelType>::flush(Region regFlush)
|
||||||
|
{
|
||||||
|
Vector3DInt32 v3dStart;
|
||||||
|
for(int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
v3dStart.setElement(i, regFlush.getLowerCorner().getElement(i) >> m_uBlockSideLengthPower);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3DInt32 v3dEnd;
|
||||||
|
for(int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
v3dEnd.setElement(i, regFlush.getUpperCorner().getElement(i) >> m_uBlockSideLengthPower);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int32_t x = v3dStart.getX(); x <= v3dEnd.getX(); x++)
|
||||||
|
{
|
||||||
|
for(int32_t y = v3dStart.getY(); y <= v3dEnd.getY(); y++)
|
||||||
|
{
|
||||||
|
for(int32_t z = v3dStart.getZ(); z <= v3dEnd.getZ(); z++)
|
||||||
|
{
|
||||||
Vector3DInt32 pos(x,y,z);
|
Vector3DInt32 pos(x,y,z);
|
||||||
if(m_v3dLastAccessedBlockPos == pos) {
|
|
||||||
m_pLastAccessedBlock = NULL;
|
|
||||||
}
|
|
||||||
typename std::map<Vector3DInt32, LoadedBlock>::iterator itBlock = m_pBlocks.find(pos);
|
typename std::map<Vector3DInt32, LoadedBlock>::iterator itBlock = m_pBlocks.find(pos);
|
||||||
if(itBlock == m_pBlocks.end()) {
|
if(itBlock == m_pBlocks.end())
|
||||||
|
{
|
||||||
// not loaded, not unloading
|
// not loaded, not unloading
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
eraseBlock(itBlock);
|
eraseBlock(itBlock);
|
||||||
count++;
|
// eraseBlock might cause a call to getUncompressedBlock, which again sets m_pLastAccessedBlock
|
||||||
}
|
if(m_v3dLastAccessedBlockPos == pos)
|
||||||
}
|
{
|
||||||
}
|
m_pLastAccessedBlock = 0;
|
||||||
if(count > ((std::numeric_limits<uint32_t>::max)() >> (m_uBlockSideLengthPower*3))) {
|
}
|
||||||
// eh, this will overflow... I have no idea what to do here
|
} // for z
|
||||||
return (std::numeric_limits<uint32_t>::max)();
|
} // for y
|
||||||
}
|
} // for x
|
||||||
return count << (m_uBlockSideLengthPower*3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename VoxelType>
|
template <typename VoxelType>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user