diff --git a/include/osg/Program b/include/osg/Program index 4d5991ac6..d899e05e9 100644 --- a/include/osg/Program +++ b/include/osg/Program @@ -243,16 +243,17 @@ class OSG_EXPORT Program : public osg::StateAttribute class OSG_EXPORT PerContextProgram : public osg::Referenced { public: - PerContextProgram(const Program* program, unsigned int contextID); + /** Use "0" as programHandle to let the PeContextProgram execute "glCreateProgram"and "glDeleteProgram" */ + PerContextProgram(const Program* program, unsigned int contextID, GLuint programHandle=0); GLuint getHandle() const {return _glProgramHandle;} void requestLink(); - void linkProgram(osg::State& state); - bool validateProgram(); + virtual void linkProgram(osg::State& state); + virtual bool validateProgram(); bool needsLink() const {return _needsLink;} bool isLinked() const {return _isLinked;} - bool getInfoLog( std::string& infoLog ) const; + virtual bool getInfoLog( std::string& infoLog ) const; /** Was glProgramBinary called successfully? */ bool loadedBinary() const {return _loadedBinary;} @@ -263,9 +264,9 @@ class OSG_EXPORT Program : public osg::StateAttribute * compileProgramBinary should be called after the program has been * "exercised" by rendering with it. The ProgramBinary can then be saved * to disk for faster subsequent compiling. */ - ProgramBinary* compileProgramBinary(osg::State& state); + virtual ProgramBinary* compileProgramBinary(osg::State& state); - void useProgram() const; + virtual void useProgram() const; void resetAppliedUniforms() const { @@ -324,7 +325,7 @@ class OSG_EXPORT Program : public osg::StateAttribute } protected: /*methods*/ - ~PerContextProgram(); + virtual ~PerContextProgram(); protected: /*data*/ /** Pointer to our parent Program */ @@ -339,7 +340,11 @@ class OSG_EXPORT Program : public osg::StateAttribute bool _isLinked; /** Was glProgramBinary called successfully? */ bool _loadedBinary; + const unsigned int _contextID; + + /** Does the glProgram handle belongs to this class? */ + bool _ownsProgramHandle; ActiveUniformMap _uniformInfoMap; ActiveVarInfoMap _attribInfoMap; @@ -382,7 +387,7 @@ class OSG_EXPORT Program : public osg::StateAttribute GLint _geometryInputType; GLint _geometryOutputType; - + /** Parameter maintained with glDispatchCompute */ GLint _numGroupsX; GLint _numGroupsY; diff --git a/src/osg/Program.cpp b/src/osg/Program.cpp index 012ee1530..cb1b44e1f 100644 --- a/src/osg/Program.cpp +++ b/src/osg/Program.cpp @@ -205,10 +205,10 @@ int Program::compare(const osg::StateAttribute& sa) const if( _numGroupsX < rhs._numGroupsX ) return -1; if( rhs._numGroupsX < _numGroupsX ) return 1; - + if( _numGroupsY < rhs._numGroupsY ) return -1; if( rhs._numGroupsY < _numGroupsY ) return 1; - + if( _numGroupsZ < rhs._numGroupsZ ) return -1; if( rhs._numGroupsZ < _numGroupsZ ) return 1; @@ -513,20 +513,29 @@ const Program::UniformBlockMap& Program::getUniformBlocks(unsigned contextID) co // PCP is an OSG abstraction of the per-context glProgram /////////////////////////////////////////////////////////////////////////// -Program::PerContextProgram::PerContextProgram(const Program* program, unsigned int contextID ) : +Program::PerContextProgram::PerContextProgram(const Program* program, unsigned int contextID, GLuint programHandle ) : osg::Referenced(), _loadedBinary(false), - _contextID( contextID ) + _glProgramHandle(programHandle), + _contextID( contextID ), + _ownsProgramHandle(false) { _program = program; _extensions = GL2Extensions::Get( _contextID, true ); - _glProgramHandle = _extensions->glCreateProgram(); + if (_glProgramHandle == 0) + { + _glProgramHandle = _extensions->glCreateProgram(); + _ownsProgramHandle = true; + } requestLink(); } Program::PerContextProgram::~PerContextProgram() { - Program::deleteGlProgram( _contextID, _glProgramHandle ); + if (_ownsProgramHandle) + { + Program::deleteGlProgram( _contextID, _glProgramHandle ); + } } @@ -567,7 +576,7 @@ void Program::PerContextProgram::linkProgram(osg::State& state) _extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_INPUT_TYPE_EXT, _program->_geometryInputType ); _extensions->glProgramParameteri( _glProgramHandle, GL_GEOMETRY_OUTPUT_TYPE_EXT, _program->_geometryOutputType ); } - + // Detach removed shaders for( unsigned int i=0; i < _shadersToDetach.size(); ++i ) { @@ -759,7 +768,7 @@ void Program::PerContextProgram::linkProgram(osg::State& state) // print atomic counter - if (_extensions->isShaderAtomicCounterSupported() && !atomicCounterMap.empty()) + if (_extensions->isShaderAtomicCounterSupported() && !atomicCounterMap.empty()) { std::vector bufferIndex( atomicCounterMap.size(), 0 ); std::vector uniformIndex;