From 97daa561f47e178ce697120c9177e5c42989d36f Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 3 May 2005 21:46:47 +0000 Subject: [PATCH] Added support for lazy state updating of uniforms. --- include/osg/Program | 38 ++++++++++++++++++++++++++++++++++++-- include/osg/State | 27 +++++---------------------- include/osg/Uniform | 8 ++++++++ src/osg/State.cpp | 12 +++++++++++- src/osg/Uniform.cpp | 35 +++++++++++++++++++++++++---------- 5 files changed, 85 insertions(+), 35 deletions(-) diff --git a/include/osg/Program b/include/osg/Program index 63941bb0a..e33441f54 100644 --- a/include/osg/Program +++ b/include/osg/Program @@ -389,11 +389,41 @@ class OSG_EXPORT Program : public osg::StateAttribute bool getInfoLog( std::string& infoLog ) const; void useProgram() const; + + void resetAppliedUnifroms() const + { + for(LastAppliedUniformList::iterator itr=_lastAppliedUniformList.begin(); + itr!=_lastAppliedUniformList.end(); + ++itr) + { + (*itr).first = 0; + (*itr).second = 0; + } + } - void apply(const Uniform& uniform) const + + inline void apply(const Uniform& uniform) const { GLint location = getUniformLocation(uniform.getName()); - if (location>=0) uniform.apply(_extensions.get(),location); + if (location>=0) + { + if ((unsigned int)location>=_lastAppliedUniformList.size()) _lastAppliedUniformList.resize(location+1); + const Uniform* lastAppliedUniform = _lastAppliedUniformList[location].first; + if (lastAppliedUniform != &uniform) + { + // new attribute + uniform.apply(_extensions.get(),location); + _lastAppliedUniformList[location].first = &uniform; + _lastAppliedUniformList[location].second = uniform.getModifiedCount(); + } + else if (_lastAppliedUniformList[location].second != uniform.getModifiedCount()) + { + // existing attribute has been modified + uniform.apply(_extensions.get(),location); + _lastAppliedUniformList[location].first = &uniform; + _lastAppliedUniformList[location].second = uniform.getModifiedCount(); + } + } } inline GLint getUniformLocation( const std::string& name ) const { NameLocationMap::const_iterator itr = _uniformLocationMap.find(name); return (itr!=_uniformLocationMap.end()) ? itr->second : -1; } @@ -418,6 +448,10 @@ class OSG_EXPORT Program : public osg::StateAttribute typedef std::map NameLocationMap; NameLocationMap _uniformLocationMap; NameLocationMap _attribLocationMap; + + typedef std::pair UniformModifiedCountPair; + typedef std::vector LastAppliedUniformList; + mutable LastAppliedUniformList _lastAppliedUniformList; private: PerContextProgram(); // disallowed diff --git a/include/osg/State b/include/osg/State index 26c59cbd8..8a445c4ad 100644 --- a/include/osg/State +++ b/include/osg/State @@ -26,6 +26,7 @@ #include #include +#include #include #ifndef GL_TEXTURE0 @@ -662,7 +663,7 @@ class OSG_EXPORT State : public Referenced bool isVertexBufferObjectSupported() const { return _isVertexBufferObjectSupportResolved?_isVertexBufferObjectSupported:computeVertexBufferObjectSupported(); } - void setLastAppliedProgramObject(const Program::PerContextProgram* program) { _lastAppliedProgramObject = program; } + void setLastAppliedProgramObject(const Program::PerContextProgram* program) { if (_lastAppliedProgramObject!=program) { _lastAppliedProgramObject = program; if (program) _appliedProgramObjectSet.insert(program); } } const Program::PerContextProgram* getLastAppliedProgramObject() const { return _lastAppliedProgramObject; } inline GLint getUniformLocation( const std::string& name ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getUniformLocation(name) : -1; } @@ -797,36 +798,16 @@ class OSG_EXPORT State : public Referenced UniformStack() { changed = false; - last_applied_uniform = 0L; global_default_uniform = 0L; } /** apply an uniform if required */ bool changed; - const Uniform* last_applied_uniform; ref_ptr global_default_uniform; UniformVec uniformVec; }; - struct ProgramStack - { - typedef std::vector ProgramVec; - - ProgramStack() - { - changed = false; - last_applied_program = 0L; - global_default_program = 0L; - } - - /** apply an program if required */ - bool changed; - const Program* last_applied_program; - ref_ptr global_default_program; - ProgramVec programVec; - }; - /** Apply an OpenGL mode if required, passing in mode, enable flag and * appropriate mode stack. This is a wrapper around \c glEnable() and * \c glDisable(), that just actually calls these functions if the @@ -899,6 +880,8 @@ class OSG_EXPORT State : public Referenced typedef std::vector StateSetStack; typedef std::vector > MatrixStack; + + typedef std::set > AppliedProgramObjectSet; ModeMap _modeMap; AttributeMap _attributeMap; @@ -907,7 +890,7 @@ class OSG_EXPORT State : public Referenced TextureModeMapList _textureModeMapList; TextureAttributeMapList _textureAttributeMapList; - ProgramStack _programStack; + AppliedProgramObjectSet _appliedProgramObjectSet; const Program::PerContextProgram* _lastAppliedProgramObject; StateSetStack _stateStateStack; diff --git a/include/osg/Uniform b/include/osg/Uniform index d7fa4c543..c44d1cff7 100644 --- a/include/osg/Uniform +++ b/include/osg/Uniform @@ -300,6 +300,12 @@ class OSG_EXPORT Uniform : public Object /** Get the const EventCallback.*/ const Callback* getEventCallback() const { return _eventCallback.get(); } + /** Increment the modified count on the Uniform so ProgramObjects watching it know it update themselves. + * note, autoatmatically call bet Uniform::set(*). */ + inline void dirty() { ++_modifiedCount; } + + inline void setModifiedCount(unsigned int mc) { _modifiedCount = mc; } + inline unsigned int getModifiedCount() const { return _modifiedCount; } void apply(const GL2Extensions* ext, GLint location) const; @@ -335,6 +341,8 @@ class OSG_EXPORT Uniform : public Object ref_ptr _updateCallback; ref_ptr _eventCallback; + + unsigned int _modifiedCount; }; diff --git a/src/osg/State.cpp b/src/osg/State.cpp index 2c11640a0..5ad624e41 100644 --- a/src/osg/State.cpp +++ b/src/osg/State.cpp @@ -51,6 +51,7 @@ State::~State() void State::reset() { + /* for(ModeMap::iterator mitr=_modeMap.begin(); mitr!=_modeMap.end(); @@ -114,6 +115,16 @@ void State::reset() setActiveTextureUnit(0); _lastAppliedProgramObject = 0; + + for(AppliedProgramObjectSet::iterator apitr=_appliedProgramObjectSet.begin(); + apitr!=_appliedProgramObjectSet.end(); + ++apitr) + { + (*apitr)->resetAppliedUnifroms(); + } + + _appliedProgramObjectSet.clear(); + // what about uniforms??? need to clear them too... // go through all active Unfirom's, setting to change to force update, @@ -124,7 +135,6 @@ void State::reset() { UniformStack& us = uitr->second; us.uniformVec.clear(); - us.last_applied_uniform = NULL; us.changed = true; } diff --git a/src/osg/Uniform.cpp b/src/osg/Uniform.cpp index de8e3b565..70ff01e60 100644 --- a/src/osg/Uniform.cpp +++ b/src/osg/Uniform.cpp @@ -28,14 +28,14 @@ using namespace osg; /////////////////////////////////////////////////////////////////////////// Uniform::Uniform() : - _name(""), _type(UNDEFINED) + _name(""), _type(UNDEFINED),_modifiedCount(0) { setDataVariance(STATIC); } Uniform::Uniform( const char* name, Type type ) : - _name(name), _type(type) + _name(name), _type(type),_modifiedCount(0) { setDataVariance(STATIC); @@ -91,8 +91,8 @@ bool Uniform::setType( Type t ) { if( _type != UNDEFINED ) { - osg::notify(osg::WARN) << "cannot change Uniform type" << std::endl; - return false; + osg::notify(osg::WARN) << "cannot change Uniform type" << std::endl; + return false; } _type = t; return true; @@ -102,8 +102,8 @@ bool Uniform::setName( const std::string& name ) { if( _name != "" ) { - osg::notify(osg::WARN) << "cannot change Uniform name" << std::endl; - return false; + osg::notify(osg::WARN) << "cannot change Uniform name" << std::endl; + return false; } _name = name; return true; @@ -273,6 +273,8 @@ void Uniform::copyData(const Uniform& rhs) osg::notify(osg::WARN) << "cannot copy UNDEFINED Uniform type" << std::endl; break; } + + dirty(); } bool Uniform::isCompatibleType( Type t ) const @@ -465,6 +467,7 @@ bool Uniform::set( float f ) { if( ! isCompatibleType(FLOAT) ) return false; _data.f1 = f; + dirty(); return true; } @@ -473,6 +476,7 @@ bool Uniform::set( const osg::Vec2& v2 ) if( ! isCompatibleType(FLOAT_VEC2) ) return false; _data.f2[0] = v2.x(); _data.f2[1] = v2.y(); + dirty(); return true; } @@ -482,6 +486,7 @@ bool Uniform::set( const osg::Vec3& v3 ) _data.f3[0] = v3.x(); _data.f3[1] = v3.y(); _data.f3[2] = v3.z(); + dirty(); return true; } @@ -492,6 +497,7 @@ bool Uniform::set( const osg::Vec4& v4 ) _data.f4[1] = v4.y(); _data.f4[2] = v4.z(); _data.f4[3] = v4.w(); + dirty(); return true; } @@ -505,11 +511,12 @@ bool Uniform::set( const osg::Matrix& m4 ) int n = 0; for(int row=0; row<4; ++row) { - for(int col=0; col<4; ++col) - { - _data.f16[n++] = m4(row,col); - } + for(int col=0; col<4; ++col) + { + _data.f16[n++] = m4(row,col); + } } + dirty(); return true; } @@ -517,6 +524,7 @@ bool Uniform::set( int i ) { if( ! isCompatibleType(INT) ) return false; _data.i1 = i; + dirty(); return true; } @@ -525,6 +533,7 @@ bool Uniform::set( int i0, int i1 ) if( ! isCompatibleType(INT_VEC2) ) return false; _data.i2[0] = i0; _data.i2[1] = i1; + dirty(); return true; } @@ -534,6 +543,7 @@ bool Uniform::set( int i0, int i1, int i2 ) _data.i3[0] = i0; _data.i3[1] = i1; _data.i3[2] = i2; + dirty(); return true; } @@ -544,6 +554,7 @@ bool Uniform::set( int i0, int i1, int i2, int i3 ) _data.i4[1] = i1; _data.i4[2] = i2; _data.i4[3] = i3; + dirty(); return true; } @@ -551,6 +562,7 @@ bool Uniform::set( bool b ) { if( ! isCompatibleType(BOOL) ) return false; _data.i1 = b; + dirty(); return true; } @@ -559,6 +571,7 @@ bool Uniform::set( bool b0, bool b1 ) if( ! isCompatibleType(BOOL_VEC2) ) return false; _data.i2[0] = b0; _data.i2[1] = b1; + dirty(); return true; } @@ -568,6 +581,7 @@ bool Uniform::set( bool b0, bool b1, bool b2 ) _data.i3[0] = b0; _data.i3[1] = b1; _data.i3[2] = b2; + dirty(); return true; } @@ -578,6 +592,7 @@ bool Uniform::set( bool b0, bool b1, bool b2, bool b3 ) _data.i4[1] = b1; _data.i4[2] = b2; _data.i4[3] = b3; + dirty(); return true; }