Introduced new shader composition approach that utilizes #pragma requires(), #pragma import_defines() and #ifdef in GLSL to enable multiple different versions of shaders based

on defines passed in from osg::StateSet::setDefine(..).



git-svn-id: http://svn.openscenegraph.org/osg/OpenSceneGraph/trunk@14681 16af8721-9629-0410-8352-f15c8da7e697
This commit is contained in:
Robert Osfield
2015-02-10 17:04:02 +00:00
parent bb637e73f3
commit b90503fdf5
14 changed files with 910 additions and 175 deletions

View File

@@ -1588,21 +1588,54 @@ class OSG_EXPORT State : public Referenced
UniformVec uniformVec;
};
struct DefineStack
{
typedef std::vector<StateSet::DefinePair> DefineVec;
DefineStack() {}
void print(std::ostream& fout) const;
bool changed;
DefineVec defineVec;
};
struct DefineMap
{
DefineMap():
changed(false) {}
typedef std::map<std::string, DefineStack> DefineStackMap;
DefineStackMap map;
bool changed;
StateSet::DefineList currentDefines;
bool updateCurrentDefines();
};
typedef std::map<StateAttribute::GLMode,ModeStack> ModeMap;
typedef std::vector<ModeMap> TextureModeMapList;
typedef std::map<StateAttribute::TypeMemberPair,AttributeStack> AttributeMap;
typedef std::vector<AttributeMap> TextureAttributeMapList;
typedef std::map<std::string,UniformStack> UniformMap;
typedef std::map<std::string, UniformStack> UniformMap;
typedef std::vector<ref_ptr<const Matrix> > MatrixStack;
inline const ModeMap& getModeMap() const {return _modeMap;};
inline const AttributeMap& getAttributeMap() const {return _attributeMap;};
inline const UniformMap& getUniformMap() const {return _uniformMap;};
inline const TextureModeMapList& getTextureModeMapList() const {return _textureModeMapList;};
inline const TextureAttributeMapList& getTextureAttributeMapList() const {return _textureAttributeMapList;};
typedef std::vector< ref_ptr<const Matrix> > MatrixStack;
inline const ModeMap& getModeMap() const {return _modeMap;}
inline const AttributeMap& getAttributeMap() const {return _attributeMap;}
inline const UniformMap& getUniformMap() const {return _uniformMap;}
inline DefineMap& getDefineMap() {return _defineMap;}
inline const DefineMap& getDefineMap() const {return _defineMap;}
inline const TextureModeMapList& getTextureModeMapList() const {return _textureModeMapList;}
inline const TextureAttributeMapList& getTextureAttributeMapList() const {return _textureAttributeMapList;}
std::string getDefineString(const osg::ShaderDefines& shaderDefines);
bool supportsShaderRequirements(const osg::ShaderDefines& shaderRequirements);
bool supportsShaderRequirement(const std::string& shaderRequirement);
protected:
@@ -1806,6 +1839,7 @@ class OSG_EXPORT State : public Referenced
ModeMap _modeMap;
AttributeMap _attributeMap;
UniformMap _uniformMap;
DefineMap _defineMap;
TextureModeMapList _textureModeMapList;
TextureAttributeMapList _textureAttributeMapList;
@@ -1865,18 +1899,22 @@ class OSG_EXPORT State : public Referenced
inline void pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
inline void pushAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
inline void pushUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
inline void pushDefineList(DefineMap& defineMap,const StateSet::DefineList& defineList);
inline void popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
inline void popAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
inline void popUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
inline void popDefineList(DefineMap& uniformMap,const StateSet::DefineList& defineList);
inline void applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList);
inline void applyAttributeList(AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
inline void applyUniformList(UniformMap& uniformMap,const StateSet::UniformList& uniformList);
inline void applyDefineList(DefineMap& uniformMap,const StateSet::DefineList& defineList);
inline void applyModeMap(ModeMap& modeMap);
inline void applyAttributeMap(AttributeMap& attributeMap);
inline void applyUniformMap(UniformMap& uniformMap);
inline void applyUniformMap(DefineMap& defineMap);
inline void applyModeListOnTexUnit(unsigned int unit,ModeMap& modeMap,const StateSet::ModeList& modeList);
inline void applyAttributeListOnTexUnit(unsigned int unit,AttributeMap& attributeMap,const StateSet::AttributeList& attributeList);
@@ -2042,6 +2080,44 @@ inline void State::pushUniformList(UniformMap& uniformMap,const StateSet::Unifor
}
}
inline void State::pushDefineList(DefineMap& defineMap,const StateSet::DefineList& defineList)
{
for(StateSet::DefineList::const_iterator aitr=defineList.begin();
aitr!=defineList.end();
++aitr)
{
// get the attribute stack for incoming type {aitr->first}.
DefineStack& ds = defineMap.map[aitr->first];
DefineStack::DefineVec& dv = ds.defineVec;
if (dv.empty())
{
// first pair so simply push incoming pair to back.
dv.push_back(StateSet::DefinePair(aitr->second.first,aitr->second.second));
ds.changed = true;
defineMap.changed = true;
}
else if ((ds.defineVec.back().second & StateAttribute::OVERRIDE) && !(aitr->second.second & StateAttribute::PROTECTED)) // check the existing override flag
{
// push existing back since override keeps the previous value.
ds.defineVec.push_back(ds.defineVec.back());
}
else
{
// no override on so simply push incoming pair to back.
dv.push_back(StateSet::DefinePair(aitr->second.first,aitr->second.second));
// if the back of the stack has changed since the last then mark it as changed.
bool changed = (dv[dv.size()-2].first==dv[dv.size()-1].first);
if (changed)
{
ds.changed = true;
defineMap.changed = true;
}
}
}
}
inline void State::popModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
{
for(StateSet::ModeList::const_iterator mitr=modeList.begin();
@@ -2089,6 +2165,28 @@ inline void State::popUniformList(UniformMap& uniformMap,const StateSet::Uniform
}
}
inline void State::popDefineList(DefineMap& defineMap,const StateSet::DefineList& defineList)
{
for(StateSet::DefineList::const_iterator aitr=defineList.begin();
aitr!=defineList.end();
++aitr)
{
// get the attribute stack for incoming type {aitr->first}.
DefineStack& ds = defineMap.map[aitr->first];
DefineStack::DefineVec& dv = ds.defineVec;
if (!dv.empty())
{
// if the stack has less than 2 entries or new back vs old back are different then mark the DefineStack as changed
if ((dv.size()<2) || (dv[dv.size()-2].first!=dv.back().first))
{
ds.changed = true;
defineMap.changed = true;
}
dv.pop_back();
}
}
}
inline void State::applyModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
{
StateSet::ModeList::const_iterator ds_mitr = modeList.begin();
@@ -2643,6 +2741,74 @@ inline void State::applyUniformList(UniformMap& uniformMap,const StateSet::Unifo
}
inline void State::applyDefineList(DefineMap& defineMap, const StateSet::DefineList& defineList)
{
StateSet::DefineList::const_iterator dl_itr = defineList.begin();
DefineMap::DefineStackMap::iterator dm_itr = defineMap.map.begin();
defineMap.changed = false;
defineMap.currentDefines.clear();
while (dm_itr!=defineMap.map.end() && dl_itr!=defineList.end())
{
if (dm_itr->first<dl_itr->first)
{
DefineStack& ds = dm_itr->second;
DefineStack::DefineVec& dv = ds.defineVec;
if (!dv.empty() && (dv.back().second & StateAttribute::ON)!=0) defineMap.currentDefines[dm_itr->first] = dv.back();
++dm_itr;
}
else if (dl_itr->first<dm_itr->first)
{
if ((dl_itr->second.second & StateAttribute::ON)!=0) defineMap.currentDefines[dl_itr->first] = dl_itr->second;
++dl_itr;
}
else
{
// this_mitr & ds_mitr refer to the same mode, check the override
// if any otherwise just apply the incoming mode.
DefineStack& ds = dm_itr->second;
DefineStack::DefineVec& dv = ds.defineVec;
if (!dv.empty() && (dv.back().second & StateAttribute::OVERRIDE)!=0 && !(dl_itr->second.second & StateAttribute::PROTECTED))
{
// override is on, just treat as a normal apply on modes.
if ((dv.back().second & StateAttribute::ON)!=0) defineMap.currentDefines[dm_itr->first] = dv.back();
}
else
{
// no override on or no previous entry, therefore consider incoming mode.
if ((dl_itr->second.second & StateAttribute::ON)!=0) defineMap.currentDefines[dl_itr->first] = dl_itr->second;
}
++dm_itr;
++dl_itr;
}
}
// iterator over the remaining state modes to apply any previous changes.
for(;
dm_itr!=defineMap.map.end();
++dm_itr)
{
// note GLMode = this_mitr->first
DefineStack& ds = dm_itr->second;
DefineStack::DefineVec& dv = ds.defineVec;
if (!dv.empty() && (dv.back().second & StateAttribute::ON)!=0) defineMap.currentDefines[dm_itr->first] = dv.back();
}
// iterator over the remaining incoming modes to apply any new mode.
for(;
dl_itr!=defineList.end();
++dl_itr)
{
if ((dl_itr->second.second & StateAttribute::ON)!=0) defineMap.currentDefines[dl_itr->first] = dl_itr->second;
}
}
inline void State::applyModeMap(ModeMap& modeMap)
{
for(ModeMap::iterator mitr=modeMap.begin();