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.
This commit is contained in:
Robert Osfield 2009-10-21 11:18:13 +00:00
parent b7ffae25ce
commit 9499b19b43
6 changed files with 162 additions and 132 deletions

View File

@ -17,12 +17,12 @@
#include <osg/ref_ptr>
#include <osg/Array>
#include <osg/Matrixd>
#include <osg/GLBeginEndAdapter>
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<AttributeDispatch*> AttributeDispatchList;
struct BindingGroup
{
unsigned int _index;
AttributeDispatchList _attributeDispatchList;
};
typedef std::vector<BindingGroup> BindingGroupList;
BindingGroupList _bindingGroupList;
typedef std::vector<AttributeDispatchList> ActiveDispatchList;
ActiveDispatchList _activeDispatchList;
bool _useGLBeginEndAdapter;
};
}
#endif

View File

@ -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);

View File

@ -26,6 +26,7 @@
#include <osg/Polytope>
#include <osg/Viewport>
#include <osg/GLBeginEndAdapter>
#include <osg/ArrayDispatchers>
#include <vector>
#include <map>
@ -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<DynamicObjectRenderingCompletedCallback> _completeDynamicObjectRenderingCallback;
GLBeginEndAdapter _glBeginEndAdapter;
ArrayDispatchers _arrayDispatchers;
};

View File

@ -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<GLfloat>(Array::Vec3ArrayType, extensions->_glSecondaryColor3fv, 3);
_fogCoordDispatchers->assign<GLfloat>(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();
}
}

View File

@ -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<ArrayDispatchers> 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
vindex<indexEnd;
++vindex,++primCount)
{
if ((primCount%primLength)==0)
if (bindPerPrimtiveActive && (primCount%primLength)==0)
{
arrayDispatchers.dispatch(BIND_PER_PRIMITIVE);
arrayDispatchers.dispatch(BIND_PER_PRIMITIVE,++primitiveNum);
}
arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
@ -1438,9 +1448,9 @@ void Geometry::drawImplementation(RenderInfo& renderInfo) const
primCount<*primItr;
++vindex,++primCount)
{
if ((primCount%localPrimLength)==0)
if (bindPerPrimtiveActive && (primCount%localPrimLength)==0)
{
arrayDispatchers.dispatch(BIND_PER_PRIMITIVE);
arrayDispatchers.dispatch(BIND_PER_PRIMITIVE, ++primitiveNum);
}
arrayDispatchers.dispatch(BIND_PER_VERTEX, vindex);
}
@ -1463,9 +1473,9 @@ void Geometry::drawImplementation(RenderInfo& renderInfo) const
++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;
@ -1487,9 +1497,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;
@ -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)
{

View File

@ -120,6 +120,7 @@ State::State():
_maxBufferObjectPoolSize = 0;
_glBeginEndAdapter.setState(this);
_arrayDispatchers.setState(this);
}
State::~State()