Implement basic cache in ShadeComposer

This commit is contained in:
Robert Osfield 2010-07-02 14:18:59 +00:00
parent a55c4b7d70
commit 9f8670f50d
3 changed files with 123 additions and 4 deletions

View File

@ -23,6 +23,8 @@ namespace osg {
// forward declare osg::State
class State;
typedef std::vector<osg::ShaderComponent*> 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<Program> > ProgramMap;
ProgramMap _programMap;
typedef std::map< Shaders, ref_ptr<Shader> > ShaderMainMap;
ShaderMainMap _shaderMainMap;
};
}

View File

@ -32,3 +32,109 @@ ShaderComposer::~ShaderComposer()
OSG_INFO<<"ShaderComposer::~ShaderComposer() "<<this<<std::endl;
}
osg::Program* ShaderComposer::getOrCreateProgram(const ShaderComponents& shaderComponents)
{
ProgramMap::iterator itr = _programMap.find(shaderComponents);
if (itr != _programMap.end())
{
OSG_NOTICE<<"ShaderComposer::getOrCreateProgram(..) using cached Program"<<std::endl;
return itr->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; i<sc->getNumShaders(); ++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."<<std::endl;
break;
}
}
}
osg::ref_ptr<osg::Program> 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"<<std::endl;
return program.get();
}
osg::Shader* ShaderComposer::composeMain(const Shaders& shaders)
{
OSG_NOTICE<<"ShaderComposer::composeMain(Shaders) shaders.size()=="<<shaders.size()<<std::endl;
return 0;
}

View File

@ -42,7 +42,7 @@ State::State():
_graphicsContext = 0;
_contextID = 0;
_shaderCompositionEnabled = true;
_shaderCompositionEnabled = false; // true;
_shaderCompositionDirty = true;
_shaderComposer = new ShaderComposer;
_currentShaderCompositionProgram = 0L;
@ -519,8 +519,9 @@ void State::apply(const StateSet* dstate)
{
if (_shaderCompositionDirty)
{
// built lits of current ShaderComponents
_currentShaderCompositionProgram = _shaderComposer->getOrCreateProgram();
// build lits of current ShaderComponents
ShaderComponents shaderComponents;
_currentShaderCompositionProgram = _shaderComposer->getOrCreateProgram(shaderComponents);
}
if (_currentShaderCompositionProgram)