diff --git a/include/osg/Program b/include/osg/Program index 38dfaf751..71e180c76 100644 --- a/include/osg/Program +++ b/include/osg/Program @@ -142,8 +142,9 @@ class OSG_EXPORT Program : public osg::StateAttribute GLenum _type; GLint _size; }; + typedef std::map< unsigned int, ActiveVarInfo > ActiveUniformMap; typedef std::map< std::string, ActiveVarInfo > ActiveVarInfoMap; - const ActiveVarInfoMap& getActiveUniforms(unsigned int contextID) const; + const ActiveUniformMap& getActiveUniforms(unsigned int contextID) const; const ActiveVarInfoMap& getActiveAttribs(unsigned int contextID) const; public: @@ -184,7 +185,7 @@ class OSG_EXPORT Program : public osg::StateAttribute inline void apply(const Uniform& uniform) const { - GLint location = getUniformLocation(uniform.getName()); + GLint location = getUniformLocation(uniform.getNameID()); if (location>=0) { if ((unsigned int)location>=_lastAppliedUniformList.size()) _lastAppliedUniformList.resize(location+1); @@ -206,10 +207,21 @@ class OSG_EXPORT Program : public osg::StateAttribute } } - const ActiveVarInfoMap& getActiveUniforms() const {return _uniformInfoMap;} + const ActiveUniformMap& getActiveUniforms() const {return _uniformInfoMap;} const ActiveVarInfoMap& getActiveAttribs() const {return _attribInfoMap;} - inline GLint getUniformLocation( const std::string& name ) const { ActiveVarInfoMap::const_iterator itr = _uniformInfoMap.find(name); return (itr!=_uniformInfoMap.end()) ? itr->second._location : -1; } + inline GLint getUniformLocation( unsigned int uniformNameID ) const { ActiveUniformMap::const_iterator itr = _uniformInfoMap.find(uniformNameID); return (itr!=_uniformInfoMap.end()) ? itr->second._location : -1; } + + /** + * Alternative version of getUniformLocation( unsigned int uniformNameID ) + * retrofited into OSG for backward compatibility with osgCal, + * after uniform ids were refactored from std::strings to GLints in OSG version 2.9.10. + * + * Drawbacks: This method is not particularly fast. It has to access mutexed static + * map of uniform ids. So don't overuse it or your app performance will suffer. + */ + inline GLint getUniformLocation( const std::string & uniformName ) const { return getUniformLocation( Uniform::getNameID( uniformName ) ); } + inline GLint getAttribLocation( const std::string& name ) const { ActiveVarInfoMap::const_iterator itr = _attribInfoMap.find(name); return (itr!=_attribInfoMap.end()) ? itr->second._location : -1; } inline void addShaderToAttach(Shader *shader) @@ -238,7 +250,7 @@ class OSG_EXPORT Program : public osg::StateAttribute bool _isLinked; const unsigned int _contextID; - ActiveVarInfoMap _uniformInfoMap; + ActiveUniformMap _uniformInfoMap; ActiveVarInfoMap _attribInfoMap; typedef std::pair, unsigned int> UniformModifiedCountPair; diff --git a/include/osg/State b/include/osg/State index 1db439b17..194b338c8 100644 --- a/include/osg/State +++ b/include/osg/State @@ -975,7 +975,16 @@ class OSG_EXPORT State : public Referenced, public Observer } inline const Program::PerContextProgram* getLastAppliedProgramObject() const { return _lastAppliedProgramObject; } - inline GLint getUniformLocation( const std::string& name ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getUniformLocation(name) : -1; } + inline GLint getUniformLocation( unsigned int uniformNameID ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getUniformLocation(uniformNameID) : -1; } + /** + * Alternative version of getUniformLocation( unsigned int uniformNameID ) + * retrofited into OSG for backward compatibility with osgCal, + * after uniform ids were refactored from std::strings to GLints in OSG version 2.9.10. + * + * Drawbacks: This method is not particularly fast. It has to access mutexed static + * map of uniform ids. So don't overuse it or your app performance will suffer. + */ + inline GLint getUniformLocation( const std::string & uniformName ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getUniformLocation(uniformName) : -1; } inline GLint getAttribLocation( const std::string& name ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getAttribLocation(name) : -1; } diff --git a/include/osg/Uniform b/include/osg/Uniform index 09659ae50..bc51eddc9 100644 --- a/include/osg/Uniform +++ b/include/osg/Uniform @@ -259,6 +259,9 @@ class OSG_EXPORT Uniform : public Object /** Return the internal data array type corresponding to a GLSL type */ static GLenum getInternalArrayType( Type t ); + /** Return the number that the name maps to uniquely */ + static unsigned int getNameID(const std::string& name); + /** convenient scalar (non-array) constructors w/ assignment */ explicit Uniform( const char* name, float f ); explicit Uniform( const char* name, int i ); @@ -463,6 +466,8 @@ class OSG_EXPORT Uniform : public Object inline void setModifiedCount(unsigned int mc) { _modifiedCount = mc; } inline unsigned int getModifiedCount() const { return _modifiedCount; } + /** Get the number that the Uniform's name maps to uniquely */ + unsigned int getNameID() const; void apply(const GL2Extensions* ext, GLint location) const; @@ -484,6 +489,8 @@ class OSG_EXPORT Uniform : public Object Type _type; unsigned int _numElements; + unsigned int _nameID; + // The internal data for osg::Uniforms are stored as an array of // getInternalArrayType() of length getInternalArrayNumElements(). diff --git a/src/osg/Program.cpp b/src/osg/Program.cpp index fa95bf15b..77622ecf4 100644 --- a/src/osg/Program.cpp +++ b/src/osg/Program.cpp @@ -394,7 +394,7 @@ bool Program::getGlProgramInfoLog(unsigned int contextID, std::string& log) cons return getPCP( contextID )->getInfoLog( log ); } -const Program::ActiveVarInfoMap& Program::getActiveUniforms(unsigned int contextID) const +const Program::ActiveUniformMap& Program::getActiveUniforms(unsigned int contextID) const { return getPCP( contextID )->getActiveUniforms(); } @@ -532,10 +532,9 @@ void Program::PerContextProgram::linkProgram() if( loc != -1 ) { - _uniformInfoMap[name] = ActiveVarInfo(loc,type,size); + _uniformInfoMap[Uniform::getNameID(reinterpret_cast(name))] = ActiveVarInfo(loc,type,size); - osg::notify(osg::INFO) - << "\tUniform \"" << name << "\"" + OSG_INFO << "\tUniform \"" << name << "\"" << " loc="<< loc << " size="<< size << " type=" << Uniform::getTypename((Uniform::Type)type) diff --git a/src/osg/Uniform.cpp b/src/osg/Uniform.cpp index 417b29449..8f2536f5b 100644 --- a/src/osg/Uniform.cpp +++ b/src/osg/Uniform.cpp @@ -21,6 +21,7 @@ #include #include +#include #include using namespace osg; @@ -30,13 +31,13 @@ using namespace osg; /////////////////////////////////////////////////////////////////////////// Uniform::Uniform() : - _type(UNDEFINED), _numElements(0), _modifiedCount(0) + _type(UNDEFINED), _numElements(0), _nameID(UINT_MAX), _modifiedCount(0) { } Uniform::Uniform( Type type, const std::string& name, int numElements ) : - _type(type), _numElements(0), _modifiedCount(0) + _type(type), _numElements(0), _nameID(UINT_MAX), _modifiedCount(0) { setName(name); setNumElements(numElements); @@ -88,6 +89,7 @@ void Uniform::setName( const std::string& name ) return; } _name = name; + _nameID = getNameID(name); } void Uniform::setNumElements( unsigned int numElements ) @@ -255,6 +257,7 @@ void Uniform::copyData(const Uniform& rhs) { // caller must ensure that _type==rhs._type _numElements = rhs._numElements; + _nameID = rhs._nameID; if (rhs._floatArray.valid() || rhs._intArray.valid() || rhs._uintArray.valid()) allocateDataArray(); if( _floatArray.valid() && rhs._floatArray.valid() ) *_floatArray = *rhs._floatArray; if( _intArray.valid() && rhs._intArray.valid() ) *_intArray = *rhs._intArray; @@ -602,6 +605,24 @@ GLenum Uniform::getInternalArrayType( Type t ) } +unsigned int Uniform::getNameID(const std::string& name) +{ + typedef std::map UniformNameIDMap; + static OpenThreads::Mutex s_mutex_uniformNameIDMap; + static UniformNameIDMap s_uniformNameIDMap; + + OpenThreads::ScopedLock lock(s_mutex_uniformNameIDMap); + UniformNameIDMap::iterator it = s_uniformNameIDMap.find(name); + if (it != s_uniformNameIDMap.end()) + { + return it->second; + } + unsigned int id = s_uniformNameIDMap.size(); + s_uniformNameIDMap.insert(UniformNameIDMap::value_type(name, id)); + return id; +} + + /////////////////////////////////////////////////////////////////////////// // value constructors for single-element (ie: non-array) uniforms @@ -1389,6 +1410,11 @@ bool Uniform::getElement( unsigned int index, bool& b0, bool& b1, bool& b2, bool return true; } +unsigned int Uniform::getNameID() const +{ + return _nameID; +} + /////////////////////////////////////////////////////////////////////////// void Uniform::apply(const GL2Extensions* ext, GLint location) const