Hi,

I've added VAO support to osg Geometry.
It need to be discussed:
First I was thinking it was not a great deal:
-Add a flag in osg::Geometry
-Do the stuff done in drawimplementation in compileGLObjects. 
However , I ran into the problem that Primitiveset (DrawElements) embed their 
BO and so bind it even if it is already bound by VAO
So I had to add a virtual method in DrawElements (arbitrary named 
indexLessDraw).

It seams to work but don't know if I didn't break stuff

Need reviews and critisms 

Thank you!

Cheers,
Julien

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=63137#63137



Index: include/osg/Geometry
===================================================================
--- include/osg/Geometry        (revision 14800)
+++ include/osg/Geometry        (working copy)
@@ -140,6 +140,14 @@
             method to use OpenGL vertex buffer objects for rendering.*/
         virtual void setUseVertexBufferObjects(bool flag);
 
+
+               /**use VertexBufferArray For Drawing*/
+               bool getUseVertexArrayObjects()const{return 
_useVAO&&getUseVertexBufferObjects();}
+
+               void setUseVertexArrayObjects(bool flag){
+                       setUseVertexBufferObjects(flag);_useVAO=flag; 
+               }
+
         /** Force a recompile on next draw() of any OpenGL display list 
associated with this geoset.*/
         virtual void dirtyDisplayList();
 
@@ -217,6 +225,9 @@
         void addVertexBufferObjectIfRequired(osg::Array* array);
         void addElementBufferObjectIfRequired(osg::PrimitiveSet* primitiveSet);
 
+               bool _useVAO;
+               typedef std::pair<unsigned int, const PrimitiveSet*> VAOKey;
+               mutable std::map<VAOKey ,unsigned int> _contextID2VAO; ///per 
context per primset vertex array object 
 
         PrimitiveSetList                _primitives;
         osg::ref_ptr<Array>             _vertexArray;
Index: include/osg/PrimitiveSet
===================================================================
--- include/osg/PrimitiveSet    (revision 14800)
+++ include/osg/PrimitiveSet    (working copy)
@@ -395,7 +395,8 @@
         virtual void setElement(unsigned int, unsigned int) = 0;
         virtual unsigned int getElement(unsigned int) = 0;
         virtual void addElement(unsigned int) = 0;
-
+               ///use it in order not to bind index and give a start index 
+               virtual void indexLessDraw(State& state, GLsizeiptr indexstart) 
const =0;
     protected:
 
         virtual ~DrawElements() {}
@@ -439,6 +440,7 @@
         virtual bool            supportsBufferObject() const { return false; }
 
         virtual void draw(State& state, bool useVertexBufferObjects) const ;
+               virtual void indexLessDraw(State& state, GLsizeiptr indexstart) 
const ;
 
         virtual void accept(PrimitiveFunctor& functor) const;
         virtual void accept(PrimitiveIndexFunctor& functor) const;
@@ -503,6 +505,7 @@
         virtual bool            supportsBufferObject() const { return false; }
 
         virtual void draw(State& state, bool useVertexBufferObjects) const;
+               virtual void indexLessDraw(State& state, GLsizeiptr indexstart) 
const ;
 
         virtual void accept(PrimitiveFunctor& functor) const;
         virtual void accept(PrimitiveIndexFunctor& functor) const;
@@ -567,6 +570,7 @@
         virtual bool            supportsBufferObject() const { return false; }
 
         virtual void draw(State& state, bool useVertexBufferObjects) const;
+               virtual void indexLessDraw(State& state, GLsizeiptr indexstart) 
const ;
 
         virtual void accept(PrimitiveFunctor& functor) const;
         virtual void accept(PrimitiveIndexFunctor& functor) const;
Index: src/osg/Geometry.cpp
===================================================================
--- src/osg/Geometry.cpp        (revision 14800)
+++ src/osg/Geometry.cpp        (working copy)
@@ -23,8 +23,10 @@
     _containsDeprecatedData(false)
 {
     _supportsVertexBufferObjects = true;
+       setSupportsDisplayList(false);
     // temporary test
-    // setSupportsDisplayList(false);
+
+       ///default 4 DEBUGsetUseVertexArrayObjects(true); 
 }
 
 Geometry::Geometry(const Geometry& geometry,const CopyOp& copyop):
@@ -716,6 +718,50 @@
         extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB,0);
         extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0);
 
+               if (_useVAO){
+                               State& state = *renderInfo.getState();
+                               for (unsigned int primitiveSetNum = 0; 
primitiveSetNum != _primitives.size(); ++primitiveSetNum)
+                               {
+                               //      ArrayDispatchers& arrayDispatchers = 
state.getArrayDispatchers(); 
+                               
+                                       const PrimitiveSet* primitiveset = 
_primitives[primitiveSetNum].get();
+
+                                       ///create VAO for this context and 
primitiveset
+                                       std::map<VAOKey, unsigned 
int>::iterator itm = _contextID2VAO.find(VAOKey(contextID, primitiveset));
+                                       if (itm != _contextID2VAO.end()) 
//delete vao if already created
+                                               
extensions->glDeleteVertexArrays(1, &(*itm).second);
+
+                                       ///create new VAO
+                                       _contextID2VAO[VAOKey(contextID, 
primitiveset)] = 0;
+                                       itm = 
_contextID2VAO.find(VAOKey(contextID, primitiveset));
+                                       
+
+                                       extensions->glGenVertexArrays(1, 
&(*itm).second);
+
+                                       ///setup VAO
+                                       
extensions->glBindVertexArray((*itm).second);
+
+                                       //bind vertex buffers
+                                       
drawVertexArraysImplementation(renderInfo);
+                               
+
+                                       //bind element buffer
+                                       GLBufferObject* ebo = 
primitiveset->getOrCreateGLBufferObject(state.getContextID());
+                                       state.bindElementBufferObject(ebo);
+
+                                       ///end VAO setup
+                                       extensions->glBindVertexArray(NULL);
+                                       
+                                       state.lazyDisablingOfVertexAttributes();
+                                       
state.applyDisablingOfVertexAttributes();
+                
+
+                               }
+                               state.unbindVertexBufferObject();
+                               state.unbindElementBufferObject();
+
+               }
+
     }
     else
     {
@@ -733,23 +779,68 @@
 
     State& state = *renderInfo.getState();
 
+       
     bool checkForGLErrors = 
state.getCheckForGLErrors()==osg::State::ONCE_PER_ATTRIBUTE;
     if (checkForGLErrors) state.checkGLErrors("start of 
Geometry::drawImplementation()");
+       if (_useVAO){
 
-    drawVertexArraysImplementation(renderInfo);
+               //drawVertexArraysImplementation(renderInfo);
+               ArrayDispatchers& arrayDispatchers = 
state.getArrayDispatchers();
+               GLExtensions* extensions = state.get<GLExtensions>();
+               //HACK 
+               //reset candidates to osg::Array::BIND_OVERALL as glColor can't 
be embed in VAOs
+               arrayDispatchers.activateColorArray(_colorArray.get());
+               
arrayDispatchers.activateSecondaryColorArray(_secondaryColorArray.get());
 
-    if (checkForGLErrors) state.checkGLErrors("Geometry::drawImplementation() 
after vertex arrays setup.");
+               // dispatch any attributes that are bound overall
+               arrayDispatchers.dispatch(osg::Array::BIND_OVERALL, 0);
+        
+               
+               for (unsigned int primitiveSetNum = 0; primitiveSetNum != 
_primitives.size(); ++primitiveSetNum)
+               {
+                       // dispatch any attributes that are bound per primitive
+                       bool bindPerPrimitiveSetActive = 
arrayDispatchers.active(osg::Array::BIND_PER_PRIMITIVE_SET);
+                       if (bindPerPrimitiveSetActive) 
arrayDispatchers.dispatch(osg::Array::BIND_PER_PRIMITIVE_SET, primitiveSetNum);
+                       const PrimitiveSet* primitiveset = 
_primitives[primitiveSetNum].get();
+                       
+                       
extensions->glBindVertexArray(_contextID2VAO[VAOKey(state.getContextID(), 
primitiveset)]);
+                       
+                       //HACK 
+                       //problem with primitiveset embedding element buffer 
(we're here to avoid this using VAO)
+                       //:( binding->draw(state,true/* 
usingVertexBufferObjects*/);
+                       //so I add a new method in DrawElements
+                       GLBufferObject* ebo = 
primitiveset->getOrCreateGLBufferObject(state.getContextID());
+                       if (ebo)//assume DrawElements
+                       ((DrawElements*)primitiveset)->indexLessDraw(state, 
ebo->getOffset(primitiveset->getBufferIndex()));
+                       else primitiveset->draw(state, true);//drawArray
+                       
 
-    
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-    //
-    // draw the primitives themselves.
-    //
-    drawPrimitivesImplementation(renderInfo);
+                       extensions->glBindVertexArray(NULL);
+       
+               }
 
-    // unbind the VBO's if any are used.
-    state.unbindVertexBufferObject();
-    state.unbindElementBufferObject();
+               state.lazyDisablingOfVertexAttributes();
+               state.applyDisablingOfVertexAttributes();
 
+
+       }
+       else{
+               drawVertexArraysImplementation(renderInfo);
+
+               if (checkForGLErrors) 
state.checkGLErrors("Geometry::drawImplementation() after vertex arrays 
setup.");
+
+               
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+               //
+               // draw the primitives themselves.
+               //
+               drawPrimitivesImplementation(renderInfo);
+
+               // unbind the VBO's if any are used.
+               state.unbindVertexBufferObject();
+               state.unbindElementBufferObject();
+
+
+       }
     if (checkForGLErrors) state.checkGLErrors("end of 
Geometry::drawImplementation().");
 }
 
@@ -850,6 +941,49 @@
     }
 }
 
+class AttributeFunctorArrayVisitor : public ArrayVisitor
+{
+    public:
+
+        AttributeFunctorArrayVisitor(Drawable::AttributeFunctor& af):
+            _af(af),
+            _type(0) {}
+
+        virtual ~AttributeFunctorArrayVisitor() {}
+
+        virtual void apply(ByteArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(ShortArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(IntArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(UByteArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(UShortArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(UIntArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(Vec4ubArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(FloatArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(Vec2Array& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(Vec3Array& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(Vec4Array& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(DoubleArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(Vec2dArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(Vec3dArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(Vec4dArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+
+
+        inline void applyArray(Drawable::AttributeType type,Array* array)
+        {
+            if (array)
+            {
+                _type = type;
+                array->accept(*this);
+            }
+        }
+
+    protected:
+
+        AttributeFunctorArrayVisitor& operator = (const 
AttributeFunctorArrayVisitor&) { return *this; }
+        Drawable::AttributeFunctor&   _af;
+        Drawable::AttributeType       _type;
+};
+
 void Geometry::accept(AttributeFunctor& af)
 {
     AttributeFunctorArrayVisitor afav(af);
@@ -880,7 +1014,50 @@
     }
 }
 
+class ConstAttributeFunctorArrayVisitor : public ConstArrayVisitor
+{
+    public:
 
+        ConstAttributeFunctorArrayVisitor(Drawable::ConstAttributeFunctor& af):
+            _af(af),
+            _type(0) {}
+
+        virtual ~ConstAttributeFunctorArrayVisitor() {}
+
+        virtual void apply(const ByteArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(const ShortArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(const IntArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(const UByteArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(const UShortArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(const UIntArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(const Vec4ubArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(const FloatArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(const Vec2Array& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(const Vec3Array& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(const Vec4Array& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(const DoubleArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(const Vec2dArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(const Vec3dArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+        virtual void apply(const Vec4dArray& array) {  if (!array.empty()) 
_af.apply(_type,array.size(),&(array.front())); }
+
+
+        inline void applyArray(Drawable::AttributeType type,const Array* array)
+        {
+            if (array)
+            {
+                _type = type;
+                array->accept(*this);
+            }
+        }
+
+protected:
+
+        ConstAttributeFunctorArrayVisitor& operator = (const 
ConstAttributeFunctorArrayVisitor&) { return *this; }
+
+        Drawable::ConstAttributeFunctor&    _af;
+        Drawable::AttributeType             _type;
+};
+
 void Geometry::accept(ConstAttributeFunctor& af) const
 {
     ConstAttributeFunctorArrayVisitor afav(af);
Index: src/osg/PrimitiveSet.cpp
===================================================================
--- src/osg/PrimitiveSet.cpp    (revision 14800)
+++ src/osg/PrimitiveSet.cpp    (working copy)
@@ -164,6 +164,13 @@
     releaseGLObjects();
 }
 
+void DrawElementsUByte::indexLessDraw(State& state, GLsizeiptr indexstart) 
const{
+
+               if (_numInstances >= 1) state.glDrawElementsInstanced(_mode, 
size(), GL_UNSIGNED_BYTE, (const GLvoid 
*)indexstart/*ebo->getOffset(getBufferIndex()))*/, _numInstances);
+               else glDrawElements(_mode, size(), GL_UNSIGNED_BYTE, (const 
GLvoid *)indexstart/*ebo->getOffset(getBufferIndex()))*/);
+       
+
+}
 void DrawElementsUByte::draw(State& state, bool useVertexBufferObjects) const
 {
     GLenum mode = _mode;
@@ -219,7 +226,13 @@
 {
     releaseGLObjects();
 }
+void DrawElementsUShort::indexLessDraw(State& state, GLsizeiptr indexstart) 
const{
 
+               if (_numInstances >= 1) state.glDrawElementsInstanced(_mode, 
size(), GL_UNSIGNED_SHORT, (const GLvoid 
*)indexstart/*ebo->getOffset(getBufferIndex()))*/, _numInstances);
+               else glDrawElements(_mode, size(), GL_UNSIGNED_SHORT, (const 
GLvoid *)indexstart/*ebo->getOffset(getBufferIndex()))*/);
+       
+
+}
 void DrawElementsUShort::draw(State& state, bool useVertexBufferObjects) const
 {
     GLenum mode = _mode;
@@ -275,7 +288,13 @@
 {
     releaseGLObjects();
 }
+void DrawElementsUInt::indexLessDraw(State& state, GLsizeiptr indexstart) 
const{
 
+               if (_numInstances >= 1) state.glDrawElementsInstanced(_mode, 
size(), GL_UNSIGNED_INT, (const GLvoid 
*)indexstart/*ebo->getOffset(getBufferIndex()))*/, _numInstances);
+               else glDrawElements(_mode, size(), GL_UNSIGNED_INT, (const 
GLvoid *)indexstart/*ebo->getOffset(getBufferIndex()))*/);
+       
+
+}
 void DrawElementsUInt::draw(State& state, bool useVertexBufferObjects) const
 {
     GLenum mode = _mode;
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to