From 921eb0fdd08b1a10036833c75daaba563800c814 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sun, 29 Apr 2007 08:12:29 +0000 Subject: [PATCH] Further work on new VertexBufferObject/ElementsBufferObject support --- include/osg/BufferObject | 4 + src/osg/BufferObject.cpp | 18 +- src/osg/Drawable.cpp | 2 +- src/osg/Geometry.cpp | 275 +++++++++++++++++++++------ src/osg/PrimitiveSet.cpp | 60 ++++++ src/osgTerrain/GeometryTechnique.cpp | 1 + 6 files changed, 299 insertions(+), 61 deletions(-) diff --git a/include/osg/BufferObject b/include/osg/BufferObject index 6ab2f1330..1fbbaaa45 100644 --- a/include/osg/BufferObject +++ b/include/osg/BufferObject @@ -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; diff --git a/src/osg/BufferObject.cpp b/src/osg/BufferObject.cpp index 41096eaf2..c6c3b4d72 100644 --- a/src/osg/BufferObject.cpp +++ b/src/osg/BufferObject.cpp @@ -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="<getFrameNumber()<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 "<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"<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) diff --git a/src/osg/Drawable.cpp b/src/osg/Drawable.cpp index 046b1aadd..039928713 100644 --- a/src/osg/Drawable.cpp +++ b/src/osg/Drawable.cpp @@ -603,7 +603,7 @@ void Drawable::setUseDisplayList(bool flag) void Drawable::setUseVertexBufferObjects(bool flag) { - osg::notify(osg::NOTICE)<<"Drawable::setUseVertexBufferObjects("<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("<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"<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 "<