Added support for lazy state updating of uniforms.
This commit is contained in:
parent
e025ba39f0
commit
97daa561f4
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user