Further work on new VertexBufferObject/ElementsBufferObject support

This commit is contained in:
Robert Osfield
2007-04-29 08:12:29 +00:00
parent 47598ce1a9
commit 921eb0fdd0
6 changed files with 299 additions and 61 deletions

View File

@@ -244,6 +244,8 @@ class OSG_EXPORT VertexBufferObject : public BufferObject
Array* getArray(unsigned int i) { return _bufferEntryArrayPairs[i].second; }
const Array* getArray(unsigned int i) const { return _bufferEntryArrayPairs[i].second; }
const GLvoid* getOffset(unsigned int i) const { return (const GLvoid*)(_bufferEntryArrayPairs[i].first.offset); }
virtual bool needsCompile(unsigned int contextID) const;
virtual void compileBuffer(State& state) const;
@@ -276,6 +278,8 @@ class OSG_EXPORT ElementsBufferObject : public BufferObject
DrawElements* getDrawElements(unsigned int i) { return _bufferEntryDrawElementsPairs[i].second; }
const DrawElements* getDrawElements(unsigned int i) const { return _bufferEntryDrawElementsPairs[i].second; }
const GLvoid* getOffset(unsigned int i) const { return (const GLvoid*)(_bufferEntryDrawElementsPairs[i].first.offset); }
virtual bool needsCompile(unsigned int contextID) const;
virtual void compileBuffer(State& state) const;

View File

@@ -286,6 +286,8 @@ VertexBufferObject::VertexBufferObject()
{
_target = GL_ARRAY_BUFFER_ARB;
_usage = GL_STATIC_DRAW_ARB;
// _usage = GL_DYNAMIC_DRAW_ARB;
// _usage = GL_STREAM_DRAW_ARB;
}
VertexBufferObject::VertexBufferObject(const VertexBufferObject& vbo,const CopyOp& copyop):
@@ -320,6 +322,8 @@ void VertexBufferObject::setArray(unsigned int i, Array* array)
bool VertexBufferObject::needsCompile(unsigned int contextID) const
{
// return true;
unsigned int numValidArray = 0;
for(BufferEntryArrayPairs::const_iterator itr = _bufferEntryArrayPairs.begin();
itr != _bufferEntryArrayPairs.end();
@@ -356,6 +360,8 @@ void VertexBufferObject::compileBuffer(State& state) const
Extensions* extensions = getExtensions(contextID,true);
osg::notify(osg::NOTICE)<<"VertexBufferObject::compileBuffer frameNumber="<<state.getFrameStamp()->getFrameNumber()<<std::endl;
unsigned int totalSizeRequired = 0;
unsigned int numModified = 0;
unsigned int numNotModified = 0;
@@ -425,14 +431,15 @@ void VertexBufferObject::compileBuffer(State& state) const
{
// copy data across
bep.first.dataSize = bep.second->getTotalDataSize();
bep.first.modifiedCount[contextID] = de->getModifiedCount();
if (copyAll)
{
bep.first.modifiedCount[contextID] != de->getModifiedCount();
bep.first.offset = offset;
offset += bep.first.dataSize;
}
// osg::notify(osg::NOTICE)<<" copying vertex buffer data "<<bep.first.dataSize<<" bytes"<<std::endl;
if (vboMemory)
memcpy((char*)vboMemory + bep.first.offset, de->getDataPointer(), bep.first.dataSize);
else
@@ -493,6 +500,7 @@ void ElementsBufferObject::setDrawElements(unsigned int i, DrawElements* drawEle
bool ElementsBufferObject::needsCompile(unsigned int contextID) const
{
#if 1
unsigned int numValidDrawElements = 0;
for(BufferEntryDrawElementsPairs::const_iterator itr = _bufferEntryDrawElementsPairs.begin();
itr != _bufferEntryDrawElementsPairs.end();
@@ -516,6 +524,7 @@ bool ElementsBufferObject::needsCompile(unsigned int contextID) const
}
if (numValidDrawElements==0) return false;
#endif
if (_bufferObjectList[contextID]==0) return true;
@@ -526,6 +535,8 @@ void ElementsBufferObject::compileBuffer(State& state) const
{
unsigned int contextID = state.getContextID();
if (!needsCompile(contextID)) return;
osg::notify(osg::NOTICE)<<"ElementsBufferObject::compile"<<std::endl;
Extensions* extensions = getExtensions(contextID,true);
@@ -598,12 +609,11 @@ void ElementsBufferObject::compileBuffer(State& state) const
{
// copy data across
bep.first.dataSize = bep.second->getTotalDataSize();
bep.first.modifiedCount[contextID] = de->getModifiedCount();
if (copyAll)
{
bep.first.modifiedCount[contextID] != de->getModifiedCount();
bep.first.offset = offset;
offset += bep.first.dataSize;
}
if (eboMemory)

View File

@@ -603,7 +603,7 @@ void Drawable::setUseDisplayList(bool flag)
void Drawable::setUseVertexBufferObjects(bool flag)
{
osg::notify(osg::NOTICE)<<"Drawable::setUseVertexBufferObjects("<<flag<<")"<<std::endl;
// osg::notify(osg::NOTICE)<<"Drawable::setUseVertexBufferObjects("<<flag<<")"<<std::endl;
// if value unchanged simply return.
if (_useVertexBufferObjects==flag) return;

View File

@@ -682,7 +682,10 @@ void Geometry::setTexCoordArray(unsigned int unit,Array* array)
computeFastPathsUsed();
dirtyDisplayList();
if (_useVertexBufferObjects && array) addVertexBufferObjectIfRequired(array);
if (_useVertexBufferObjects && array)
{
addVertexBufferObjectIfRequired(array);
}
}
Array* Geometry::getTexCoordArray(unsigned int unit)
@@ -1011,14 +1014,14 @@ unsigned int Geometry::getGLObjectSizeHint() const
}
}
for(PrimitiveSetList::const_iterator itr=_primitives.begin();
itr!=_primitives.end();
++itr)
{
for(PrimitiveSetList::const_iterator itr=_primitives.begin();
itr!=_primitives.end();
++itr)
{
totalSize += 4*(*itr)->getNumIndices();
totalSize += 4*(*itr)->getNumIndices();
}
}
// do a very simply mapping of display list size proportional to vertex datasize.
@@ -1035,6 +1038,18 @@ bool Geometry::getArrayList(ArrayList& arrayList)
if (_secondaryColorData.array.valid()) arrayList.push_back(_secondaryColorData.array.get());
if (_fogCoordData.array.valid()) arrayList.push_back(_fogCoordData.array.get());
for(unsigned int unit=0;unit<_texCoordList.size();++unit)
{
Array* array = _texCoordList[unit].array.get();
if (array) arrayList.push_back(array);
}
for(unsigned int index = 0; index < _vertexAttribList.size(); ++index )
{
Array* array = _vertexAttribList[index].array.get();
if (array) arrayList.push_back(array);
}
return arrayList.size()!=startSize;
}
@@ -1120,14 +1135,12 @@ osg::ElementsBufferObject* Geometry::getOrCreateElementsBufferObject()
void Geometry::setUseVertexBufferObjects(bool flag)
{
osg::notify(osg::NOTICE)<<"Geometry::setUseVertexBufferObjects("<<flag<<")"<<std::endl;
// osg::notify(osg::NOTICE)<<"Geometry::setUseVertexBufferObjects("<<flag<<")"<<std::endl;
if (_useVertexBufferObjects==flag) return;
Drawable::setUseVertexBufferObjects(flag);
osg::notify(osg::NOTICE)<<" setting up"<<std::endl;
ArrayList arrayList;
getArrayList(arrayList);
@@ -1217,11 +1230,96 @@ void Geometry::dirtyDisplayList()
Drawable::dirtyDisplayList();
}
#define SETARRAYPOINTER(vertexData, setVertexPointer, disableVertexPointer) \
if( vertexData.array.valid() ) \
{ \
new_vbo = vertexData.array.valid() ? vertexData.array->getVertexBufferObject() : 0; \
if (new_vbo) \
{ \
if (new_vbo!=prev_vbo) new_vbo->bindBuffer(contextID); \
prev_vbo = new_vbo; \
setVertexPointer(vertexData.array->getDataSize(),vertexData.array->getDataType(),0,new_vbo->getOffset(vertexData.array->getVertexBufferObjectIndex())); \
} \
else \
{ \
extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB,0); \
prev_vbo = 0; \
setVertexPointer(vertexData.array->getDataSize(),vertexData.array->getDataType(),0,vertexData.array->getDataPointer()); \
} \
} \
else \
disableVertexPointer();
#define SETNORMALPOINTER_IFPERVERTEXBINDING(vertexData, setVertexPointer, disableVertexPointer) \
if( vertexData.array.valid() && vertexData.binding==BIND_PER_VERTEX) \
{ \
new_vbo = vertexData.array.valid() ? vertexData.array->getVertexBufferObject() : 0; \
if (new_vbo) \
{ \
if (new_vbo!=prev_vbo) new_vbo->bindBuffer(contextID); \
prev_vbo = new_vbo; \
setVertexPointer(vertexData.array->getDataType(),0,new_vbo->getOffset(vertexData.array->getVertexBufferObjectIndex())); \
} \
else \
{ \
extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB,0); \
prev_vbo = 0; \
setVertexPointer(vertexData.array->getDataType(),0,vertexData.array->getDataPointer()); \
} \
} \
else \
disableVertexPointer();
#define SETARRAYPOINTER_IFPERVERTEXBINDING(vertexData, setVertexPointer, disableVertexPointer) \
if( vertexData.array.valid() && vertexData.binding==BIND_PER_VERTEX) \
{ \
new_vbo = vertexData.array.valid() ? vertexData.array->getVertexBufferObject() : 0; \
if (new_vbo) \
{ \
if (new_vbo!=prev_vbo) new_vbo->bindBuffer(contextID); \
prev_vbo = new_vbo; \
setVertexPointer(vertexData.array->getDataSize(),vertexData.array->getDataType(),0,new_vbo->getOffset(vertexData.array->getVertexBufferObjectIndex())); \
} \
else \
{ \
extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB,0); \
prev_vbo = 0; \
setVertexPointer(vertexData.array->getDataSize(),vertexData.array->getDataType(),0,vertexData.array->getDataPointer()); \
} \
} \
else \
disableVertexPointer();
#define SETARRAYUNITPOINTER_IFPERVERTEXBINDING(vertexData, unit, setVertexPointer, disableVertexPointer) \
if( vertexData.array.valid() && vertexData.binding==BIND_PER_VERTEX) \
{ \
new_vbo = vertexData.array.valid() ? vertexData.array->getVertexBufferObject() : 0; \
if (new_vbo) \
{ \
if (new_vbo!=prev_vbo) new_vbo->bindBuffer(contextID); \
prev_vbo = new_vbo; \
setVertexPointer(unit, vertexData.array->getDataSize(),vertexData.array->getDataType(),0,new_vbo->getOffset(vertexData.array->getVertexBufferObjectIndex())); \
} \
else \
{ \
extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB,0); \
prev_vbo = 0; \
setVertexPointer(unit, vertexData.array->getDataSize(),vertexData.array->getDataType(),0,vertexData.array->getDataPointer()); \
} \
} \
else \
disableVertexPointer();
void Geometry::drawImplementation(RenderInfo& renderInfo) const
{
State& state = *renderInfo.getState();
unsigned int contextID = state.getContextID();
// osg::notify(osg::NOTICE)<<"Geometry::drawImplementation"<<std::endl;
if (_internalOptimizedGeometry.valid())
@@ -1311,69 +1409,134 @@ void Geometry::drawImplementation(RenderInfo& renderInfo) const
if (usingVertexBufferObjects)
{
// first up lets check for new VBO support:
unsigned int numArraysWithVBO = 0;
unsigned int numArraysWithoutVBO = 0;
if (_vertexData.array.valid())
{
if (_vertexData.array->getVertexBufferObject())
++numArraysWithVBO;
else
++numArraysWithoutVBO;
}
//
// Vertex Buffer Object path for defining vertex arrays.
//
#if 1
if (_normalData.array.valid())
{
if (_normalData.array->getVertexBufferObject())
++numArraysWithVBO;
else
++numArraysWithoutVBO;
}
// first compile the VBO's
const VertexBufferObject* prev_vbo = 0;
const VertexBufferObject* new_vbo = 0;
new_vbo = _vertexData.array.valid() ? _vertexData.array->getVertexBufferObject() : 0;
if (new_vbo && new_vbo!=prev_vbo) { new_vbo->compileBuffer(state); prev_vbo = new_vbo; }
new_vbo = (_normalData.binding==BIND_PER_VERTEX && _normalData.array.valid()) ? _normalData.array->getVertexBufferObject() : 0;
if (new_vbo && new_vbo!=prev_vbo) { new_vbo->compileBuffer(state); prev_vbo = new_vbo; }
new_vbo = (_colorData.binding==BIND_PER_VERTEX && _colorData.array.valid()) ? _colorData.array->getVertexBufferObject() : 0;
if (new_vbo && new_vbo!=prev_vbo) { new_vbo->compileBuffer(state); prev_vbo = new_vbo; }
if (_colorData.array.valid())
{
if (_colorData.array->getVertexBufferObject())
++numArraysWithVBO;
else
++numArraysWithoutVBO;
}
new_vbo = (_secondaryColorData.binding==BIND_PER_VERTEX && _secondaryColorData.array.valid()) ? _secondaryColorData.array->getVertexBufferObject() : 0;
if (new_vbo && new_vbo!=prev_vbo) { new_vbo->compileBuffer(state); prev_vbo = new_vbo; }
new_vbo = (_fogCoordData.binding==BIND_PER_VERTEX && _fogCoordData.array.valid()) ? _fogCoordData.array->getVertexBufferObject() : 0;
if (new_vbo && new_vbo!=prev_vbo) { new_vbo->compileBuffer(state); prev_vbo = new_vbo; }
unsigned int unit;
for(unit=0;unit<_texCoordList.size();++unit)
{
if (_texCoordList[unit].array.valid())
{
if (_texCoordList[unit].array->getVertexBufferObject())
++numArraysWithVBO;
else
++numArraysWithoutVBO;
}
const Array* array = _texCoordList[unit].array.get();
new_vbo = array ? array->getVertexBufferObject() : 0;
if (new_vbo && new_vbo!=prev_vbo) { new_vbo->compileBuffer(state); prev_vbo = new_vbo; }
}
if( handleVertexAttributes )
{
for(unit=0;unit<_vertexAttribList.size();++unit)
unsigned int index;
for( index = 0; index < _vertexAttribList.size(); ++index )
{
if (_vertexAttribList[unit].array.valid())
const Array* array = _vertexAttribList[index].array.get();
new_vbo = (_vertexAttribList[index].binding==BIND_PER_VERTEX && array) ? array->getVertexBufferObject() : 0;
if (new_vbo && new_vbo!=prev_vbo) { new_vbo->compileBuffer(state); prev_vbo = new_vbo; }
}
}
prev_vbo = 0;
SETNORMALPOINTER_IFPERVERTEXBINDING(_normalData, state.setNormalPointer, state.disableNormalPointer)
SETARRAYPOINTER_IFPERVERTEXBINDING(_colorData, state.setColorPointer, state.disableColorPointer)
SETARRAYPOINTER_IFPERVERTEXBINDING(_secondaryColorData, state.setSecondaryColorPointer, state.disableSecondaryColorPointer)
SETNORMALPOINTER_IFPERVERTEXBINDING(_fogCoordData, state.setFogCoordPointer, state.disableFogCoordPointer)
for(unit=0;unit<_texCoordList.size();++unit)
{
SETARRAYUNITPOINTER_IFPERVERTEXBINDING(_texCoordList[unit], unit, state.setTexCoordPointer, state.disableVertexPointer)
}
state.disableTexCoordPointersAboveAndIncluding(unit);
if( handleVertexAttributes )
{
unsigned int index;
for( index = 0; index < _vertexAttribList.size(); ++index )
{
const Array* array = _vertexAttribList[index].array.get();
const AttributeBinding ab = _vertexAttribList[index].binding;
if(array && ab==BIND_PER_VERTEX)
{
if (_vertexAttribList[unit].array->getVertexBufferObject())
++numArraysWithVBO;
new_vbo = array->getVertexBufferObject();
if (new_vbo)
{
if (new_vbo!=prev_vbo) new_vbo->bindBuffer(contextID);
prev_vbo = new_vbo;
state.setVertexAttribPointer(index, array->getDataSize(),array->getDataType(),_vertexAttribList[index].normalize, 0,new_vbo->getOffset(array->getVertexBufferObjectIndex()));
}
else
++numArraysWithoutVBO;
{
extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB,0);
prev_vbo = 0;
state.setVertexAttribPointer(index, array->getDataSize(),array->getDataType(),_vertexAttribList[index].normalize, 0,array->getDataPointer());
}
}
else
state.disableVertexAttribPointer(index);
if(array && ab!=BIND_PER_VERTEX)
{
const IndexArray* indexArray = _vertexAttribList[index].indices.get();
if( indexArray && indexArray->getNumElements() > 0 )
{
drawVertexAttribMap[ab].push_back(
new DrawVertexAttrib(extensions,index,_vertexAttribList[index].normalize,array,indexArray) );
}
else
{
drawVertexAttribMap[ab].push_back(
new DrawVertexAttrib(extensions,index,_vertexAttribList[index].normalize,array,0) );
}
}
}
state.disableVertexAttribPointersAboveAndIncluding( index );
}
else if (vertexVertexAttributesSupported)
{
state.disableVertexAttribPointersAboveAndIncluding( 0 );
}
SETARRAYPOINTER(_vertexData, state.setVertexPointer, state.disableVertexPointer)
const osg::ElementsBufferObject* prev_ebo = 0;
const osg::ElementsBufferObject* new_ebo = 0;
for(PrimitiveSetList::const_iterator itr=_primitives.begin();
itr!=_primitives.end();
++itr)
{
const DrawElements* de = (*itr)->getDrawElements();
if (de)
{
new_ebo = de->getElementsBufferObject();
if (new_ebo && new_ebo!=prev_ebo)
{
new_ebo->compileBuffer(state);
prev_ebo = new_ebo;
}
}
}
osg::notify(osg::NOTICE)<<"Geometry::drawImplementation "<<std::endl;
osg::notify(osg::NOTICE)<<" numArraysWithVBO = "<<numArraysWithVBO<<std::endl;
osg::notify(osg::NOTICE)<<" numArraysWithoutVBO = "<<numArraysWithoutVBO<<std::endl;
//
// Vertex Buffer Object path for defining vertex arrays.
//
#else
GLuint& buffer = _vboList[state.getContextID()];
if (!buffer)
{
@@ -1559,7 +1722,7 @@ void Geometry::drawImplementation(RenderInfo& renderInfo) const
{
state.disableVertexAttribPointersAboveAndIncluding( 0 );
}
#endif
}
else

View File

@@ -154,6 +154,25 @@ void DrawElementsUByte::draw(State& state, bool useVertexBufferObjects) const
{
if (useVertexBufferObjects)
{
#if 1
unsigned int contextID = state.getContextID();
const BufferObject::Extensions* extensions = BufferObject::getExtensions(contextID, true);
const ElementsBufferObject* ebo = getElementsBufferObject();
if (ebo)
{
//ebo->compileBuffer(state);
ebo->bindBuffer(contextID);
glDrawElements(_mode, size(), GL_UNSIGNED_BYTE, ebo->getOffset(getElementsBufferObjectIndex()));
extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
}
else
{
glDrawElements(_mode, size(), GL_UNSIGNED_INT, &front());
}
#else
unsigned int contextID = state.getContextID();
const BufferObject::Extensions* extensions = BufferObject::getExtensions(contextID, true);
@@ -181,6 +200,7 @@ void DrawElementsUByte::draw(State& state, bool useVertexBufferObjects) const
glDrawElements(_mode, size(), GL_UNSIGNED_BYTE, 0);
extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
#endif
}
else
{
@@ -247,6 +267,25 @@ void DrawElementsUShort::draw(State& state, bool useVertexBufferObjects) const
{
if (useVertexBufferObjects)
{
#if 1
unsigned int contextID = state.getContextID();
const BufferObject::Extensions* extensions = BufferObject::getExtensions(contextID, true);
const ElementsBufferObject* ebo = getElementsBufferObject();
if (ebo)
{
//ebo->compileBuffer(state);
ebo->bindBuffer(contextID);
glDrawElements(_mode, size(), GL_UNSIGNED_SHORT, ebo->getOffset(getElementsBufferObjectIndex()));
extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
}
else
{
glDrawElements(_mode, size(), GL_UNSIGNED_INT, &front());
}
#else
unsigned int contextID = state.getContextID();
const BufferObject::Extensions* extensions = BufferObject::getExtensions(contextID, true);
@@ -275,6 +314,7 @@ void DrawElementsUShort::draw(State& state, bool useVertexBufferObjects) const
glDrawElements(_mode, size(), GL_UNSIGNED_SHORT, 0);
extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
#endif
}
else
{
@@ -341,6 +381,25 @@ void DrawElementsUInt::draw(State& state, bool useVertexBufferObjects) const
{
if (useVertexBufferObjects)
{
#if 1
unsigned int contextID = state.getContextID();
const BufferObject::Extensions* extensions = BufferObject::getExtensions(contextID, true);
const ElementsBufferObject* ebo = getElementsBufferObject();
if (ebo)
{
//ebo->compileBuffer(state);
ebo->bindBuffer(contextID);
glDrawElements(_mode, size(), GL_UNSIGNED_INT, ebo->getOffset(getElementsBufferObjectIndex()));
extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
}
else
{
glDrawElements(_mode, size(), GL_UNSIGNED_INT, &front());
}
#else
unsigned int contextID = state.getContextID();
const BufferObject::Extensions* extensions = BufferObject::getExtensions(contextID, true);
@@ -369,6 +428,7 @@ void DrawElementsUInt::draw(State& state, bool useVertexBufferObjects) const
glDrawElements(_mode, size(), GL_UNSIGNED_INT, 0);
extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
#endif
}
else
{

View File

@@ -344,6 +344,7 @@ void GeometryTechnique::init()
}
// if (_terrainGeometry.valid()) _terrainGeometry->setUseDisplayList(false);
if (_geometry.valid()) _geometry->setUseVertexBufferObjects(true);
if (_geometry.valid())
{