From Peter Hrenka, "I implemented a free list reallocation scheme in
VertexBufferObject::compileBuffer(). The offsets of newly added Arrays were not properly calculated. This submission tries to find a matching empty slot when the total size of the VBO has not changed (e.g. when an array is replaced by another array of the same size). This fixes the overwriting issue that I showed in my posting "Bug in VertexBufferObject::compileBuffer" on OSG-Users. "
This commit is contained in:
parent
ca3fe5d352
commit
cf73a329b3
@ -400,6 +400,48 @@ void VertexBufferObject::compileBuffer(State& state) const
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::map<unsigned int,std::vector<unsigned int> > SizePosMap_t;
|
||||
SizePosMap_t freeList;
|
||||
if (copyAll == false)
|
||||
{
|
||||
unsigned int numNewArrays = 0;
|
||||
std::map<unsigned int,unsigned int> usedList;
|
||||
for(BufferEntryArrayPairs::const_iterator itr = _bufferEntryArrayPairs.begin();
|
||||
itr != _bufferEntryArrayPairs.end();
|
||||
++itr)
|
||||
{
|
||||
const BufferEntryArrayPair& bep = *itr;
|
||||
if (bep.second==NULL) continue;
|
||||
if (bep.first.dataSize == 0) continue;
|
||||
usedList[bep.first.offset] = bep.first.dataSize;
|
||||
}
|
||||
unsigned int numFreeBlocks = 0;
|
||||
unsigned int pos=0;
|
||||
|
||||
for (std::map<unsigned int,unsigned int>::const_iterator it=usedList.begin(); it!=usedList.end(); ++it)
|
||||
{
|
||||
unsigned int start = it->first;
|
||||
unsigned int length = it->second;
|
||||
if (pos < start)
|
||||
{
|
||||
freeList[start-pos].push_back(pos);
|
||||
++numFreeBlocks;
|
||||
}
|
||||
pos = start+length;
|
||||
}
|
||||
if (pos < totalSizeRequired)
|
||||
{
|
||||
freeList[totalSizeRequired-pos].push_back(pos);
|
||||
++numFreeBlocks;
|
||||
}
|
||||
if (numNewArrays < numFreeBlocks)
|
||||
{
|
||||
copyAll = true; // too fragmented, fallback to copyAll
|
||||
freeList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// osg::Timer_t start_tick = osg::Timer::instance()->tick();
|
||||
|
||||
|
||||
@ -418,19 +460,42 @@ void VertexBufferObject::compileBuffer(State& state) const
|
||||
const Array* de = bep.second;
|
||||
if (de)
|
||||
{
|
||||
const unsigned int arraySize = de->getTotalDataSize();
|
||||
if (copyAll ||
|
||||
bep.first.modifiedCount[contextID] != bep.second->getModifiedCount() ||
|
||||
bep.first.dataSize != bep.second->getTotalDataSize())
|
||||
bep.first.dataSize != arraySize)
|
||||
{
|
||||
// copy data across
|
||||
bep.first.dataSize = bep.second->getTotalDataSize();
|
||||
bep.first.modifiedCount[contextID] = de->getModifiedCount();
|
||||
unsigned int newOffset = bep.first.offset;
|
||||
if (copyAll)
|
||||
{
|
||||
bep.first.offset = offset;
|
||||
de->setVertexBufferObjectOffset((GLvoid*)offset);
|
||||
offset += bep.first.dataSize;
|
||||
newOffset = offset;
|
||||
offset += arraySize;
|
||||
}
|
||||
else if (bep.first.dataSize == 0)
|
||||
{
|
||||
SizePosMap_t::iterator findIt = freeList.lower_bound(arraySize);
|
||||
if (findIt==freeList.end())
|
||||
{
|
||||
osg::notify(osg::FATAL)<<"No suitable Memory in VBO found!"<<std::endl;
|
||||
continue;
|
||||
}
|
||||
const unsigned int oldOffset = findIt->second.back();
|
||||
newOffset = oldOffset;
|
||||
if (findIt->first > arraySize) // using larger block
|
||||
{
|
||||
freeList[findIt->first-arraySize].push_back(oldOffset+arraySize);
|
||||
}
|
||||
findIt->second.pop_back();
|
||||
if (findIt->second.empty())
|
||||
{
|
||||
freeList.erase(findIt);
|
||||
}
|
||||
}
|
||||
bep.first.dataSize = arraySize;
|
||||
bep.first.modifiedCount[contextID] = de->getModifiedCount();
|
||||
bep.first.offset = newOffset;
|
||||
de->setVertexBufferObjectOffset((GLvoid*)newOffset);
|
||||
|
||||
// osg::notify(osg::NOTICE)<<" copying vertex buffer data "<<bep.first.dataSize<<" bytes"<<std::endl;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user