From 9f8670f50d623f3c4a1ca2a0bec4c4543807a639 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 2 Jul 2010 14:18:59 +0000 Subject: [PATCH] Implement basic cache in ShadeComposer --- include/osg/ShaderComposer | 14 ++++- src/osg/ShaderComposer.cpp | 106 +++++++++++++++++++++++++++++++++++++ src/osg/State.cpp | 7 +-- 3 files changed, 123 insertions(+), 4 deletions(-) diff --git a/include/osg/ShaderComposer b/include/osg/ShaderComposer index fbbd6d404..ff47209c6 100644 --- a/include/osg/ShaderComposer +++ b/include/osg/ShaderComposer @@ -23,6 +23,8 @@ namespace osg { // forward declare osg::State class State; +typedef std::vector ShaderComponents; + class OSG_EXPORT ShaderComposer : public osg::Object { public: @@ -31,12 +33,22 @@ class OSG_EXPORT ShaderComposer : public osg::Object ShaderComposer(const ShaderComposer& sa,const CopyOp& copyop=CopyOp::SHALLOW_COPY); META_Object(osg, ShaderComposer) - osg::Program* getOrCreateProgram() { return 0; } + virtual osg::Program* getOrCreateProgram(const ShaderComponents& shaderComponents); + + + typedef std::vector< const osg::Shader* > Shaders; + virtual osg::Shader* composeMain(const Shaders& shaders); protected: virtual ~ShaderComposer(); + typedef std::map< ShaderComponents, ref_ptr > ProgramMap; + ProgramMap _programMap; + + typedef std::map< Shaders, ref_ptr > ShaderMainMap; + ShaderMainMap _shaderMainMap; + }; } diff --git a/src/osg/ShaderComposer.cpp b/src/osg/ShaderComposer.cpp index 99038ba74..662d29bf2 100644 --- a/src/osg/ShaderComposer.cpp +++ b/src/osg/ShaderComposer.cpp @@ -32,3 +32,109 @@ ShaderComposer::~ShaderComposer() OSG_INFO<<"ShaderComposer::~ShaderComposer() "<second.get(); + } + + // strip out vertex shaders + Shaders vertexShaders; + Shaders geometryShaders; + Shaders fragmentShaders; + + for(ShaderComponents::const_iterator itr = shaderComponents.begin(); + itr != shaderComponents.end(); + ++itr) + { + const ShaderComponent* sc = *itr; + + for(unsigned int i=0; igetNumShaders(); ++i) + { + const Shader* shader = sc->getShader(i); + switch(shader->getType()) + { + case(Shader::VERTEX): + vertexShaders.push_back(shader); + break; + case(Shader::GEOMETRY): + geometryShaders.push_back(shader); + break; + case(Shader::FRAGMENT): + fragmentShaders.push_back(shader); + break; + case(Shader::UNDEFINED): + OSG_WARN<<"Warning: ShaderCompose::getOrCreateProgam(ShaderComponts) encounterd invalid Shader::Type."< program = new osg::Program; + + if (!vertexShaders.empty()) + { + ShaderMainMap::iterator itr = _shaderMainMap.find(vertexShaders); + if (itr == _shaderMainMap.end()) + { + // no vertex shader in map yet, need to compose a new main shader + osg::Shader* mainShader = composeMain(vertexShaders); + _shaderMainMap[vertexShaders] = mainShader; + program->addShader(mainShader); + } + else + { + program->addShader(itr->second.get()); + } + } + + if (!geometryShaders.empty()) + { + ShaderMainMap::iterator itr = _shaderMainMap.find(geometryShaders); + if (itr == _shaderMainMap.end()) + { + // no vertex shader in map yet, need to compose a new main shader + osg::Shader* mainShader = composeMain(geometryShaders); + _shaderMainMap[geometryShaders] = mainShader; + program->addShader(mainShader); + } + else + { + program->addShader(itr->second.get()); + } + } + + + if (!fragmentShaders.empty()) + { + ShaderMainMap::iterator itr = _shaderMainMap.find(fragmentShaders); + if (itr == _shaderMainMap.end()) + { + // no vertex shader in map yet, need to compose a new main shader + osg::Shader* mainShader = composeMain(fragmentShaders); + _shaderMainMap[fragmentShaders] = mainShader; + program->addShader(mainShader); + } + else + { + program->addShader(itr->second.get()); + } + } + + + // assign newly created program to map. + _programMap[shaderComponents] = program; + + OSG_NOTICE<<"ShaderComposer::getOrCreateProgram(..) created new Program"<getOrCreateProgram(); + // build lits of current ShaderComponents + ShaderComponents shaderComponents; + _currentShaderCompositionProgram = _shaderComposer->getOrCreateProgram(shaderComponents); } if (_currentShaderCompositionProgram)