From 9499b19b435ca220ffacc7719c010b0aa7074c4e Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 21 Oct 2009 11:18:13 +0000 Subject: [PATCH] Moved the ArrayDispatchers management so that osg::State now has a ArrayDispatchers object that any osg::Geometry can reuse, and optimized the implementation to reduce the CPU overhead. --- include/osg/ArrayDispatchers | 70 ++++++++++++------- include/osg/Drawable | 5 +- include/osg/State | 4 ++ src/osg/ArrayDispatchers.cpp | 132 ++++++++++++++++------------------- src/osg/Geometry.cpp | 82 ++++++++++++---------- src/osg/State.cpp | 1 + 6 files changed, 162 insertions(+), 132 deletions(-) diff --git a/include/osg/ArrayDispatchers b/include/osg/ArrayDispatchers index 1fec13726..64a5ead2b 100644 --- a/include/osg/ArrayDispatchers +++ b/include/osg/ArrayDispatchers @@ -17,12 +17,12 @@ #include #include #include +#include namespace osg { // forward declare class State; -class GLBeginEndAdapter; class AttributeDispatchMap; struct AttributeDispatch : public osg::Referenced @@ -36,11 +36,10 @@ class OSG_EXPORT ArrayDispatchers : public osg::Referenced { public: - ArrayDispatchers(osg::State& state); + ArrayDispatchers(); ~ArrayDispatchers(); - void assignTexCoordDispatchers(unsigned int unit); - void assignVertexAttribDispatchers(unsigned int unit); + void setState(osg::State* state); AttributeDispatch* vertexDispatcher(Array* array, IndexArray* indices); AttributeDispatch* normalDispatcher(Array* array, IndexArray* indices); @@ -55,24 +54,52 @@ class OSG_EXPORT ArrayDispatchers : public osg::Referenced void setUseGLBeginEndAdapter(bool flag) { _useGLBeginEndAdapter = flag; } bool getUseGLBeginEndAdapter() const { return _useGLBeginEndAdapter; } - void activate(unsigned int binding, AttributeDispatch* at); + void activate(unsigned int binding, AttributeDispatch* at) + { + if (at) _activeDispatchList[binding].push_back(at); + } - void activateVertexArray(unsigned int binding, osg::Array* array, osg::IndexArray* indices) { activate(binding, vertexDispatcher(array, indices)); } - void activateColorArray(unsigned int binding, osg::Array* array, osg::IndexArray* indices) { activate(binding, colorDispatcher(array, indices)); } - void activateNormalArray(unsigned int binding, osg::Array* array, osg::IndexArray* indices) { activate(binding, normalDispatcher(array, indices)); } - void activateSecondaryColorArray(unsigned int binding, osg::Array* array, osg::IndexArray* indices) { activate(binding, secondaryColorDispatcher(array, indices)); } - void activateFogCoordArray(unsigned int binding, osg::Array* array, osg::IndexArray* indices) { activate(binding, fogCoordDispatcher(array, indices)); } - void activateTexCoordArray(unsigned int binding, unsigned int unit, osg::Array* array, osg::IndexArray* indices) { activate(binding, texCoordDispatcher(unit, array, indices)); } - void activateVertexAttribArray(unsigned int binding, unsigned int unit, osg::Array* array, osg::IndexArray* indices) { activate(binding, vertexAttribDispatcher(unit, array, indices)); } + void activateVertexArray(unsigned int binding, osg::Array* array, osg::IndexArray* indices) { if (binding && array) activate(binding, vertexDispatcher(array, indices)); } + void activateColorArray(unsigned int binding, osg::Array* array, osg::IndexArray* indices) { if (binding && array) activate(binding, colorDispatcher(array, indices)); } + void activateNormalArray(unsigned int binding, osg::Array* array, osg::IndexArray* indices) { if (binding && array) activate(binding, normalDispatcher(array, indices)); } + void activateSecondaryColorArray(unsigned int binding, osg::Array* array, osg::IndexArray* indices) { if (binding && array) activate(binding, secondaryColorDispatcher(array, indices)); } + void activateFogCoordArray(unsigned int binding, osg::Array* array, osg::IndexArray* indices) { if (binding && array) activate(binding, fogCoordDispatcher(array, indices)); } + void activateTexCoordArray(unsigned int binding, unsigned int unit, osg::Array* array, osg::IndexArray* indices) { if (binding && array) activate(binding, texCoordDispatcher(unit, array, indices)); } + void activateVertexAttribArray(unsigned int binding, unsigned int unit, osg::Array* array, osg::IndexArray* indices) { if (binding && array) activate(binding, vertexAttribDispatcher(unit, array, indices)); } - void dispatch(unsigned int binding); - void dispatch(unsigned int binding, unsigned int index); + void dispatch(unsigned int binding, unsigned int index) + { + AttributeDispatchList& ad = _activeDispatchList[binding]; + for(AttributeDispatchList::iterator itr = ad.begin(); + itr != ad.end(); + ++itr) + { + (*(*itr))(index); + } + } - void Begin(GLenum mode); - void End(); + bool active(unsigned int binding) const { return !_activeDispatchList[binding].empty(); } + + void Begin(GLenum mode) + { + if (_useGLBeginEndAdapter) _glBeginEndAdapter->Begin(mode); + else ::glBegin(mode); + } + + void End() + { + if (_useGLBeginEndAdapter) _glBeginEndAdapter->End(); + else ::glEnd(); + } protected: + void init(); + + void assignTexCoordDispatchers(unsigned int unit); + void assignVertexAttribDispatchers(unsigned int unit); + + bool _initialized; State* _state; GLBeginEndAdapter* _glBeginEndAdapter; @@ -88,19 +115,12 @@ class OSG_EXPORT ArrayDispatchers : public osg::Referenced typedef std::vector AttributeDispatchList; - struct BindingGroup - { - unsigned int _index; - AttributeDispatchList _attributeDispatchList; - }; - - typedef std::vector BindingGroupList; - BindingGroupList _bindingGroupList; + typedef std::vector ActiveDispatchList; + ActiveDispatchList _activeDispatchList; bool _useGLBeginEndAdapter; }; - } #endif diff --git a/include/osg/Drawable b/include/osg/Drawable index 0060bb3a6..1de5e1595 100644 --- a/include/osg/Drawable +++ b/include/osg/Drawable @@ -73,6 +73,7 @@ class Vec4f; class Vec4ub; class Geometry; class NodeVisitor; +class ArrayDispatchers; // this is defined to alter the way display lists are compiled inside the // the draw method, it has been found that the NVidia drivers fail completely @@ -666,7 +667,9 @@ class OSG_EXPORT Drawable : public Object void glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) const; void glGetQueryObjectui64v(GLuint id, GLenum pname, GLuint64EXT *params) const; - public: + protected: + + friend class ArrayDispatchers; typedef void (APIENTRY * FogCoordProc) (const GLfloat* coord); diff --git a/include/osg/State b/include/osg/State index dd144f578..ca3bc12d5 100644 --- a/include/osg/State +++ b/include/osg/State @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -1246,6 +1247,8 @@ class OSG_EXPORT State : public Referenced, public Observer /** get the GL adapter object used to map OpenGL 1.0 glBegin/glEnd usage to vertex arrays.*/ inline GLBeginEndAdapter& getGLBeginEndAdapter() { return _glBeginEndAdapter; } + /** get the helper class for dispatching osg::Arrays as OpenGL attribute data.*/ + inline ArrayDispatchers& getArrayDispatchers() { return _arrayDispatchers; } protected: @@ -1558,6 +1561,7 @@ class OSG_EXPORT State : public Referenced, public Observer osg::ref_ptr _completeDynamicObjectRenderingCallback; GLBeginEndAdapter _glBeginEndAdapter; + ArrayDispatchers _arrayDispatchers; }; diff --git a/src/osg/ArrayDispatchers.cpp b/src/osg/ArrayDispatchers.cpp index d19162b6d..c7bec6a88 100644 --- a/src/osg/ArrayDispatchers.cpp +++ b/src/osg/ArrayDispatchers.cpp @@ -345,15 +345,62 @@ public: AttributeDispatchList _glBeginEndAttributeDispatchWithIndicesList; }; -ArrayDispatchers::ArrayDispatchers(osg::State& state): - _state(&state), - _vertexDispatchers(new AttributeDispatchMap(&(_state->getGLBeginEndAdapter()))), - _normalDispatchers(new AttributeDispatchMap(&(_state->getGLBeginEndAdapter()))), - _colorDispatchers(new AttributeDispatchMap(&(_state->getGLBeginEndAdapter()))), - _secondaryColorDispatchers(new AttributeDispatchMap(&(_state->getGLBeginEndAdapter()))), - _fogCoordDispatchers(new AttributeDispatchMap(&(_state->getGLBeginEndAdapter()))) +ArrayDispatchers::ArrayDispatchers(): + _initialized(false), + _state(0), + _glBeginEndAdapter(0), + _vertexDispatchers(0), + _normalDispatchers(0), + _colorDispatchers(0), + _secondaryColorDispatchers(0), + _fogCoordDispatchers(0), + _useGLBeginEndAdapter(false) { - Drawable::Extensions* extensions = Drawable::getExtensions(state.getContextID(),true); + +} + +ArrayDispatchers::~ArrayDispatchers() +{ + delete _vertexDispatchers; + delete _normalDispatchers; + delete _colorDispatchers; + delete _secondaryColorDispatchers; + delete _fogCoordDispatchers; + + for(AttributeDispatchMapList::iterator itr = _texCoordDispatchers.begin(); + itr != _texCoordDispatchers.end(); + ++itr) + { + delete *itr; + } + + for(AttributeDispatchMapList::iterator itr = _vertexAttribDispatchers.begin(); + itr != _vertexAttribDispatchers.end(); + ++itr) + { + delete *itr; + } +} + +void ArrayDispatchers::setState(osg::State* state) +{ + _state = state; + _glBeginEndAdapter = &(state->getGLBeginEndAdapter()); +} + +void ArrayDispatchers::init() +{ + if (_initialized) return; + + _initialized = true; + + _vertexDispatchers = new AttributeDispatchMap(&(_state->getGLBeginEndAdapter())); + _normalDispatchers = new AttributeDispatchMap(&(_state->getGLBeginEndAdapter())); + _colorDispatchers = new AttributeDispatchMap(&(_state->getGLBeginEndAdapter())); + _secondaryColorDispatchers = new AttributeDispatchMap(&(_state->getGLBeginEndAdapter())); + _fogCoordDispatchers = new AttributeDispatchMap(&(_state->getGLBeginEndAdapter())); + + Drawable::Extensions* extensions = Drawable::getExtensions(_state->getContextID(),true); _glBeginEndAdapter = &(_state->getGLBeginEndAdapter()); _useGLBeginEndAdapter = false; @@ -378,10 +425,9 @@ ArrayDispatchers::ArrayDispatchers(osg::State& state): _secondaryColorDispatchers->assign(Array::Vec3ArrayType, extensions->_glSecondaryColor3fv, 3); _fogCoordDispatchers->assign(Array::FloatArrayType, extensions->_glFogCoordfv, 1); -} -ArrayDispatchers::~ArrayDispatchers() -{ + // pre allocate. + _activeDispatchList.resize(5); } AttributeDispatch* ArrayDispatchers::vertexDispatcher(Array* array, IndexArray* indices) { return _vertexDispatchers->dispatcher(_useGLBeginEndAdapter, array, indices); } @@ -452,70 +498,16 @@ void ArrayDispatchers::assignVertexAttribDispatchers(unsigned int unit) void ArrayDispatchers::reset() { + if (!_initialized) init(); + _useGLBeginEndAdapter = false; - for(BindingGroupList::iterator itr = _bindingGroupList.begin(); - itr != _bindingGroupList.end(); + for(ActiveDispatchList::iterator itr = _activeDispatchList.begin(); + itr != _activeDispatchList.end(); ++itr) { - itr->_index = 0; - itr->_attributeDispatchList.clear(); + (*itr).clear(); } } -void ArrayDispatchers::activate(unsigned int binding, AttributeDispatch* at) -{ - if (!at) return; - - if (binding>=_bindingGroupList.size()) _bindingGroupList.resize(binding+1); - - BindingGroup& bindingGroup = _bindingGroupList[binding]; - bindingGroup._attributeDispatchList.push_back(at); } - -void ArrayDispatchers::dispatch(unsigned int binding, unsigned int index) -{ - if (binding>=_bindingGroupList.size()) return; - - BindingGroup& bg = _bindingGroupList[binding]; - for(AttributeDispatchList::iterator itr = bg._attributeDispatchList.begin(); - itr != bg._attributeDispatchList.end(); - ++itr) - { - AttributeDispatch* at = *itr; - (*at)(index); - } -} - -void ArrayDispatchers::dispatch(unsigned int binding) -{ - if (binding>=_bindingGroupList.size()) return; - - BindingGroup& bg = _bindingGroupList[binding]; - unsigned int index = bg._index; - for(AttributeDispatchList::iterator itr = bg._attributeDispatchList.begin(); - itr != bg._attributeDispatchList.end(); - ++itr) - { - AttributeDispatch* at = *itr; - (*at)(index); - } - - // advance the index so that it's ready for the next dispatch - ++(bg._index); -} - -void ArrayDispatchers::Begin(GLenum mode) -{ - if (_useGLBeginEndAdapter) _glBeginEndAdapter->Begin(mode); - else ::glBegin(mode); -} - -void ArrayDispatchers::End() -{ - if (_useGLBeginEndAdapter) _glBeginEndAdapter->End(); - else ::glEnd(); -} - -} - diff --git a/src/osg/Geometry.cpp b/src/osg/Geometry.cpp index 4a85a50ca..bd577a09d 100644 --- a/src/osg/Geometry.cpp +++ b/src/osg/Geometry.cpp @@ -20,6 +20,9 @@ using namespace osg; const Geometry::ArrayData Geometry::s_InvalidArrayData; +// #define USE_OLD_DRAW_IMPLEMENTATOIN + +#ifdef USE_OLD_DRAW_IMPLEMENTATOIN class DrawVertex { public: @@ -394,6 +397,8 @@ class DrawFogCoord : public osg::ConstValueVisitor const Drawable::Extensions * _extensions; }; +#endif + Geometry::ArrayData::ArrayData(const ArrayData& data,const CopyOp& copyop): array(copyop(data.array.get())), @@ -414,7 +419,7 @@ Geometry::Vec3ArrayData::Vec3ArrayData(const Vec3ArrayData& data,const CopyOp& c Geometry::Geometry() { // temporary test - // setSupportsDisplayList(false); + setSupportsDisplayList(false); _fastPath = false; _fastPathHint = true; @@ -431,7 +436,7 @@ Geometry::Geometry(const Geometry& geometry,const CopyOp& copyop): _fastPathHint(geometry._fastPathHint) { // temporary test - // setSupportsDisplayList(false); + setSupportsDisplayList(false); for(PrimitiveSetList::const_iterator pitr=geometry._primitives.begin(); pitr!=geometry._primitives.end(); @@ -1279,7 +1284,7 @@ void Geometry::releaseGLObjects(State* state) const } -#if 1 +#ifndef USE_OLD_DRAW_IMPLEMENTATOIN void Geometry::drawImplementation(RenderInfo& renderInfo) const { State& state = *renderInfo.getState(); @@ -1290,34 +1295,26 @@ void Geometry::drawImplementation(RenderInfo& renderInfo) const bool usingVertexBufferObjects = _useVertexBufferObjects && state.isVertexBufferObjectSupported(); bool handleVertexAttributes = !_vertexAttribList.empty() && extensions->isVertexProgramSupported(); - osg::ref_ptr s_ArrayDispatchers = 0; - if (!s_ArrayDispatchers) s_ArrayDispatchers = new ArrayDispatchers(state); - - ArrayDispatchers& arrayDispatchers = *s_ArrayDispatchers; + ArrayDispatchers& arrayDispatchers = state.getArrayDispatchers(); arrayDispatchers.reset(); - arrayDispatchers.setUseGLBeginEndAdapter(!useFastPath); + // arrayDispatchers.setUseGLBeginEndAdapter(!useFastPath); arrayDispatchers.activateNormalArray(_normalData.binding, _normalData.array.get(), _normalData.indices.get()); arrayDispatchers.activateColorArray(_colorData.binding, _colorData.array.get(), _colorData.indices.get()); arrayDispatchers.activateSecondaryColorArray(_secondaryColorData.binding, _secondaryColorData.array.get(), _secondaryColorData.indices.get()); arrayDispatchers.activateFogCoordArray(_fogCoordData.binding, _fogCoordData.array.get(), _fogCoordData.indices.get()); - for(unsigned int unit=0;unit<_texCoordList.size();++unit) + if (handleVertexAttributes) { - arrayDispatchers.activateTexCoordArray(BIND_PER_VERTEX, unit, _texCoordList[unit].array.get(), _texCoordList[unit].indices.get()); + for(unsigned int unit=0;unit<_vertexAttribList.size();++unit) + { + arrayDispatchers.activateVertexAttribArray(_vertexAttribList[unit].binding, unit, _vertexAttribList[unit].array.get(), _vertexAttribList[unit].indices.get()); + } } - for(unsigned int unit=0;unit<_vertexAttribList.size();++unit) - { - arrayDispatchers.activateVertexAttribArray(_vertexAttribList[unit].binding, unit, _vertexAttribList[unit].array.get(), _vertexAttribList[unit].indices.get()); - } - - arrayDispatchers.activateVertexArray(BIND_PER_VERTEX, _vertexData.array.get(), _vertexData.indices.get()); - - // dispatch any attributes that are bound overall - arrayDispatchers.dispatch(BIND_OVERALL); + arrayDispatchers.dispatch(BIND_OVERALL,0); state.lazyDisablingOfVertexAttributes(); @@ -1358,21 +1355,34 @@ void Geometry::drawImplementation(RenderInfo& renderInfo) const } } } + else + { + for(unsigned int unit=0;unit<_texCoordList.size();++unit) + { + arrayDispatchers.activateTexCoordArray(BIND_PER_VERTEX, unit, _texCoordList[unit].array.get(), _texCoordList[unit].indices.get()); + } + + arrayDispatchers.activateVertexArray(BIND_PER_VERTEX, _vertexData.array.get(), _vertexData.indices.get()); + } state.applyDisablingOfVertexAttributes(); + bool bindPerPrimtiveSetActive = arrayDispatchers.active(BIND_PER_PRIMITIVE_SET); + bool bindPerPrimtiveActive = arrayDispatchers.active(BIND_PER_PRIMITIVE); + + unsigned int primitiveNum = 0; + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // draw the primitives themselves. // - for(PrimitiveSetList::const_iterator itr=_primitives.begin(); - itr!=_primitives.end(); - ++itr) + for(unsigned int primitiveSetNum=0; primitiveSetNum!=_primitives.size(); ++primitiveSetNum) { - // dispatch any attributes that are bound per primitive - arrayDispatchers.dispatch(BIND_PER_PRIMITIVE_SET); - const PrimitiveSet* primitiveset = itr->get(); + // dispatch any attributes that are bound per primitive + if (bindPerPrimtiveSetActive) arrayDispatchers.dispatch(BIND_PER_PRIMITIVE_SET, primitiveSetNum); + + const PrimitiveSet* primitiveset = _primitives[primitiveSetNum].get(); if (useFastPath) { @@ -1409,9 +1419,9 @@ void Geometry::drawImplementation(RenderInfo& renderInfo) const vindexend(); ++primCount,++primItr) { - if ((primCount%primLength)==0) + if (bindPerPrimtiveActive && (primCount%primLength)==0) { - arrayDispatchers.dispatch(BIND_PER_PRIMITIVE); + arrayDispatchers.dispatch(BIND_PER_PRIMITIVE, ++primitiveNum); } unsigned int vindex=*primItr; @@ -1511,9 +1521,9 @@ void Geometry::drawImplementation(RenderInfo& renderInfo) const primItr!=drawElements->end(); ++primCount,++primItr) { - if ((primCount%primLength)==0) + if (bindPerPrimtiveActive && (primCount%primLength)==0) { - arrayDispatchers.dispatch(BIND_PER_PRIMITIVE); + arrayDispatchers.dispatch(BIND_PER_PRIMITIVE, ++primitiveNum); } unsigned int vindex=*primItr; @@ -1643,7 +1653,7 @@ void Geometry::drawImplementation(RenderInfo& renderInfo) const } // force the use of the slow path code to test the glBegin/glEnd replacement codes. - bool forceSlowPath = false; + bool forceSlowPath = true; if (areFastPathsUsed() && !forceSlowPath) { diff --git a/src/osg/State.cpp b/src/osg/State.cpp index 1490b3a89..07a53d09f 100644 --- a/src/osg/State.cpp +++ b/src/osg/State.cpp @@ -120,6 +120,7 @@ State::State(): _maxBufferObjectPoolSize = 0; _glBeginEndAdapter.setState(this); + _arrayDispatchers.setState(this); } State::~State()