Added support for lazy state updating of uniforms.

This commit is contained in:
Robert Osfield 2005-05-03 21:46:47 +00:00
parent e025ba39f0
commit 97daa561f4
5 changed files with 85 additions and 35 deletions

View File

@ -390,10 +390,40 @@ class OSG_EXPORT Program : public osg::StateAttribute
void useProgram() const; void useProgram() const;
void apply(const Uniform& uniform) const void resetAppliedUnifroms() const
{
for(LastAppliedUniformList::iterator itr=_lastAppliedUniformList.begin();
itr!=_lastAppliedUniformList.end();
++itr)
{
(*itr).first = 0;
(*itr).second = 0;
}
}
inline void apply(const Uniform& uniform) const
{ {
GLint location = getUniformLocation(uniform.getName()); 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; } inline GLint getUniformLocation( const std::string& name ) const { NameLocationMap::const_iterator itr = _uniformLocationMap.find(name); return (itr!=_uniformLocationMap.end()) ? itr->second : -1; }
@ -419,6 +449,10 @@ class OSG_EXPORT Program : public osg::StateAttribute
NameLocationMap _uniformLocationMap; NameLocationMap _uniformLocationMap;
NameLocationMap _attribLocationMap; NameLocationMap _attribLocationMap;
typedef std::pair<const osg::Uniform*, unsigned int> UniformModifiedCountPair;
typedef std::vector<UniformModifiedCountPair> LastAppliedUniformList;
mutable LastAppliedUniformList _lastAppliedUniformList;
private: private:
PerContextProgram(); // disallowed PerContextProgram(); // disallowed
PerContextProgram(const PerContextProgram&); // disallowed PerContextProgram(const PerContextProgram&); // disallowed

View File

@ -26,6 +26,7 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include <set>
#include <string> #include <string>
#ifndef GL_TEXTURE0 #ifndef GL_TEXTURE0
@ -662,7 +663,7 @@ class OSG_EXPORT State : public Referenced
bool isVertexBufferObjectSupported() const { return _isVertexBufferObjectSupportResolved?_isVertexBufferObjectSupported:computeVertexBufferObjectSupported(); } 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; } const Program::PerContextProgram* getLastAppliedProgramObject() const { return _lastAppliedProgramObject; }
inline GLint getUniformLocation( const std::string& name ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getUniformLocation(name) : -1; } 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() UniformStack()
{ {
changed = false; changed = false;
last_applied_uniform = 0L;
global_default_uniform = 0L; global_default_uniform = 0L;
} }
/** apply an uniform if required */ /** apply an uniform if required */
bool changed; bool changed;
const Uniform* last_applied_uniform;
ref_ptr<const Uniform> global_default_uniform; ref_ptr<const Uniform> global_default_uniform;
UniformVec uniformVec; UniformVec uniformVec;
}; };
struct ProgramStack
{
typedef std::vector<const Program*> 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<const Program> global_default_program;
ProgramVec programVec;
};
/** Apply an OpenGL mode if required, passing in mode, enable flag and /** Apply an OpenGL mode if required, passing in mode, enable flag and
* appropriate mode stack. This is a wrapper around \c glEnable() and * appropriate mode stack. This is a wrapper around \c glEnable() and
* \c glDisable(), that just actually calls these functions if the * \c glDisable(), that just actually calls these functions if the
@ -900,6 +881,8 @@ class OSG_EXPORT State : public Referenced
typedef std::vector<const StateSet*> StateSetStack; typedef std::vector<const StateSet*> StateSetStack;
typedef std::vector<ref_ptr<const Matrix> > MatrixStack; typedef std::vector<ref_ptr<const Matrix> > MatrixStack;
typedef std::set<osg::ref_ptr<const Program::PerContextProgram> > AppliedProgramObjectSet;
ModeMap _modeMap; ModeMap _modeMap;
AttributeMap _attributeMap; AttributeMap _attributeMap;
UniformMap _uniformMap; UniformMap _uniformMap;
@ -907,7 +890,7 @@ class OSG_EXPORT State : public Referenced
TextureModeMapList _textureModeMapList; TextureModeMapList _textureModeMapList;
TextureAttributeMapList _textureAttributeMapList; TextureAttributeMapList _textureAttributeMapList;
ProgramStack _programStack; AppliedProgramObjectSet _appliedProgramObjectSet;
const Program::PerContextProgram* _lastAppliedProgramObject; const Program::PerContextProgram* _lastAppliedProgramObject;
StateSetStack _stateStateStack; StateSetStack _stateStateStack;

View File

@ -300,6 +300,12 @@ class OSG_EXPORT Uniform : public Object
/** Get the const EventCallback.*/ /** Get the const EventCallback.*/
const Callback* getEventCallback() const { return _eventCallback.get(); } 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; void apply(const GL2Extensions* ext, GLint location) const;
@ -336,6 +342,8 @@ class OSG_EXPORT Uniform : public Object
ref_ptr<Callback> _updateCallback; ref_ptr<Callback> _updateCallback;
ref_ptr<Callback> _eventCallback; ref_ptr<Callback> _eventCallback;
unsigned int _modifiedCount;
}; };
} }

View File

@ -51,6 +51,7 @@ State::~State()
void State::reset() void State::reset()
{ {
/* /*
for(ModeMap::iterator mitr=_modeMap.begin(); for(ModeMap::iterator mitr=_modeMap.begin();
mitr!=_modeMap.end(); mitr!=_modeMap.end();
@ -115,6 +116,16 @@ void State::reset()
_lastAppliedProgramObject = 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... // what about uniforms??? need to clear them too...
// go through all active Unfirom's, setting to change to force update, // go through all active Unfirom's, setting to change to force update,
// the idea is to leave only the global defaults left. // the idea is to leave only the global defaults left.
@ -124,7 +135,6 @@ void State::reset()
{ {
UniformStack& us = uitr->second; UniformStack& us = uitr->second;
us.uniformVec.clear(); us.uniformVec.clear();
us.last_applied_uniform = NULL;
us.changed = true; us.changed = true;
} }

View File

@ -28,14 +28,14 @@ using namespace osg;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
Uniform::Uniform() : Uniform::Uniform() :
_name(""), _type(UNDEFINED) _name(""), _type(UNDEFINED),_modifiedCount(0)
{ {
setDataVariance(STATIC); setDataVariance(STATIC);
} }
Uniform::Uniform( const char* name, Type type ) : Uniform::Uniform( const char* name, Type type ) :
_name(name), _type(type) _name(name), _type(type),_modifiedCount(0)
{ {
setDataVariance(STATIC); setDataVariance(STATIC);
@ -273,6 +273,8 @@ void Uniform::copyData(const Uniform& rhs)
osg::notify(osg::WARN) << "cannot copy UNDEFINED Uniform type" << std::endl; osg::notify(osg::WARN) << "cannot copy UNDEFINED Uniform type" << std::endl;
break; break;
} }
dirty();
} }
bool Uniform::isCompatibleType( Type t ) const bool Uniform::isCompatibleType( Type t ) const
@ -465,6 +467,7 @@ bool Uniform::set( float f )
{ {
if( ! isCompatibleType(FLOAT) ) return false; if( ! isCompatibleType(FLOAT) ) return false;
_data.f1 = f; _data.f1 = f;
dirty();
return true; return true;
} }
@ -473,6 +476,7 @@ bool Uniform::set( const osg::Vec2& v2 )
if( ! isCompatibleType(FLOAT_VEC2) ) return false; if( ! isCompatibleType(FLOAT_VEC2) ) return false;
_data.f2[0] = v2.x(); _data.f2[0] = v2.x();
_data.f2[1] = v2.y(); _data.f2[1] = v2.y();
dirty();
return true; return true;
} }
@ -482,6 +486,7 @@ bool Uniform::set( const osg::Vec3& v3 )
_data.f3[0] = v3.x(); _data.f3[0] = v3.x();
_data.f3[1] = v3.y(); _data.f3[1] = v3.y();
_data.f3[2] = v3.z(); _data.f3[2] = v3.z();
dirty();
return true; return true;
} }
@ -492,6 +497,7 @@ bool Uniform::set( const osg::Vec4& v4 )
_data.f4[1] = v4.y(); _data.f4[1] = v4.y();
_data.f4[2] = v4.z(); _data.f4[2] = v4.z();
_data.f4[3] = v4.w(); _data.f4[3] = v4.w();
dirty();
return true; return true;
} }
@ -510,6 +516,7 @@ bool Uniform::set( const osg::Matrix& m4 )
_data.f16[n++] = m4(row,col); _data.f16[n++] = m4(row,col);
} }
} }
dirty();
return true; return true;
} }
@ -517,6 +524,7 @@ bool Uniform::set( int i )
{ {
if( ! isCompatibleType(INT) ) return false; if( ! isCompatibleType(INT) ) return false;
_data.i1 = i; _data.i1 = i;
dirty();
return true; return true;
} }
@ -525,6 +533,7 @@ bool Uniform::set( int i0, int i1 )
if( ! isCompatibleType(INT_VEC2) ) return false; if( ! isCompatibleType(INT_VEC2) ) return false;
_data.i2[0] = i0; _data.i2[0] = i0;
_data.i2[1] = i1; _data.i2[1] = i1;
dirty();
return true; return true;
} }
@ -534,6 +543,7 @@ bool Uniform::set( int i0, int i1, int i2 )
_data.i3[0] = i0; _data.i3[0] = i0;
_data.i3[1] = i1; _data.i3[1] = i1;
_data.i3[2] = i2; _data.i3[2] = i2;
dirty();
return true; return true;
} }
@ -544,6 +554,7 @@ bool Uniform::set( int i0, int i1, int i2, int i3 )
_data.i4[1] = i1; _data.i4[1] = i1;
_data.i4[2] = i2; _data.i4[2] = i2;
_data.i4[3] = i3; _data.i4[3] = i3;
dirty();
return true; return true;
} }
@ -551,6 +562,7 @@ bool Uniform::set( bool b )
{ {
if( ! isCompatibleType(BOOL) ) return false; if( ! isCompatibleType(BOOL) ) return false;
_data.i1 = b; _data.i1 = b;
dirty();
return true; return true;
} }
@ -559,6 +571,7 @@ bool Uniform::set( bool b0, bool b1 )
if( ! isCompatibleType(BOOL_VEC2) ) return false; if( ! isCompatibleType(BOOL_VEC2) ) return false;
_data.i2[0] = b0; _data.i2[0] = b0;
_data.i2[1] = b1; _data.i2[1] = b1;
dirty();
return true; return true;
} }
@ -568,6 +581,7 @@ bool Uniform::set( bool b0, bool b1, bool b2 )
_data.i3[0] = b0; _data.i3[0] = b0;
_data.i3[1] = b1; _data.i3[1] = b1;
_data.i3[2] = b2; _data.i3[2] = b2;
dirty();
return true; return true;
} }
@ -578,6 +592,7 @@ bool Uniform::set( bool b0, bool b1, bool b2, bool b3 )
_data.i4[1] = b1; _data.i4[1] = b1;
_data.i4[2] = b2; _data.i4[2] = b2;
_data.i4[3] = b3; _data.i4[3] = b3;
dirty();
return true; return true;
} }