From Alberto Farre, added osgDB::SharedStateManager. Also a couple of

ammendments by Robert Osfield, adding get/setSharedStateManager()
methods into osgDB::Registry, and clean up fixes in SharedStateManager
for the StateSet arrays.
This commit is contained in:
Robert Osfield
2004-01-10 17:13:20 +00:00
parent 30c2cca1a3
commit 23443aa5db
10 changed files with 408 additions and 6 deletions

View File

@@ -97,6 +97,10 @@ SOURCE=..\..\src\osgDB\DatabasePager.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osgDB\SharedStateManager.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Src\osgDB\DotOsgWrapper.cpp
# End Source File
# Begin Source File
@@ -161,6 +165,10 @@ SOURCE=..\..\Include\osgDB\DatabasePager
# End Source File
# Begin Source File
SOURCE=..\..\Include\osgDB\SharedStateManager
# End Source File
# Begin Source File
SOURCE=..\..\Include\osgDB\DotOsgWrapper
# End Source File
# Begin Source File

View File

@@ -23,6 +23,7 @@
#include <OpenThreads/Mutex>
#include <OpenThreads/Condition>
#include <osgDB/SharedStateManager>
#include <osgDB/Export>
#include <map>
@@ -45,8 +46,11 @@ class Block: public osg::Referenced {
void release()
{
_mut.lock();
_released = true;
_cond.broadcast();
if (!_released)
{
_released = true;
_cond.broadcast();
}
_mut.unlock();
}
@@ -230,7 +234,6 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
double _expiryDelay;
ActiveGraphicsContexts _activeGraphicsContexts;
};
}

View File

@@ -221,6 +221,16 @@ class OSGDB_EXPORT Registry : public osg::Referenced
/** Get the DatabasePager. Return 0 if no DatabasePager has been assigned.*/
DatabasePager* getDatabasePager() { return _databasePager.get(); }
/** Set the SharedStateManager.*/
void setSharedStateManager(SharedStateManager* SharedStateManager) { _sharedStateManager = SharedStateManager; }
/** Get the SharedStateManager, creating one if one is not already created.*/
SharedStateManager* getOrCreateSharedStateManager();
/** Get the SharedStateManager. Return 0 if no SharedStateManager has been assigned.*/
SharedStateManager* getSharedStateManager() { return _sharedStateManager.get(); }
protected:
virtual ~Registry();
@@ -276,7 +286,8 @@ class OSGDB_EXPORT Registry : public osg::Referenced
bool _useObjectCacheHint;
ObjectCache _objectCache;
osg::ref_ptr<DatabasePager> _databasePager;
osg::ref_ptr<DatabasePager> _databasePager;
osg::ref_ptr<SharedStateManager> _sharedStateManager;
};

View File

@@ -0,0 +1,86 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#ifndef OSGDB_SHAREDSTATEMANAGER
#define OSGDB_SHAREDSTATEMANAGER 1
#include <osg/NodeVisitor>
#include <osg/Geode>
#include <osgDB/Export>
#include <OpenThreads/Mutex>
#include <set>
namespace osgDB {
class OSGDB_EXPORT SharedStateManager : public osg::NodeVisitor
{
public:
enum ShareMode
{
SHARE_NONE = 0x00,
SHARE_TEXTURES = 0x01,
SHARE_STATESETS = 0x02,
SHARE_ALL = SHARE_TEXTURES |
SHARE_STATESETS
};
SharedStateManager();
void setShareMode(unsigned int mode) { shareMode = mode; }
unsigned int getShareMode() { return shareMode; }
// Call right after each unload and before Registry cache prune.
void prune();
// Call right after each load
void share(osg::Node *node, OpenThreads::Mutex *mt=0);
protected:
void apply(osg::Node& node);
void apply(osg::Geode& geode);
void process(osg::StateSet* ss, osg::Object* parent);
inline osg::StateAttribute *find(osg::StateAttribute *sa);
inline osg::StateSet *find(osg::StateSet *ss);
inline void setStateSet(osg::StateSet* ss, osg::Object* object);
inline void shareTextures(osg::StateSet* ss);
// Lists of shared objects
typedef std::set< osg::ref_ptr<osg::StateAttribute> > TextureSet;
TextureSet _sharedTextureList;
typedef std::set< osg::ref_ptr<osg::StateSet> > StateSetSet;
StateSetSet _sharedStateSetList;
// Temporary lists just to avoid unnecesary find calls
typedef std::pair<osg::StateAttribute*, bool> TextureSharePair;
typedef std::map<osg::StateAttribute*, TextureSharePair> TextureTextureSharePairMap;
TextureTextureSharePairMap tmpSharedTextureList;
typedef std::pair<osg::StateSet*, bool> StateSetSharePair;
typedef std::map<osg::StateSet*, StateSetSharePair> StateSetStateSetSharePairMap;
StateSetStateSetSharePairMap tmpSharedStateSetList;
// Share connection mutex
unsigned int shareMode;
OpenThreads::Mutex *mutex;
};
}
#endif

View File

@@ -216,7 +216,9 @@ int Texture::compareTexture(const Texture& rhs) const
COMPARE_StateAttribute_Parameter(_maxAnisotropy)
COMPARE_StateAttribute_Parameter(_useHardwareMipMapGeneration)
COMPARE_StateAttribute_Parameter(_internalFormatMode)
#if 1
COMPARE_StateAttribute_Parameter(_internalFormat)
#endif
COMPARE_StateAttribute_Parameter(_use_shadow_comparison)
COMPARE_StateAttribute_Parameter(_shadow_compare_func)
COMPARE_StateAttribute_Parameter(_shadow_texture_mode)

View File

@@ -81,8 +81,10 @@ int Texture2D::compare(const StateAttribute& sa) const
if (result!=0) return result;
// compare each paramter in turn against the rhs.
#if 1
COMPARE_StateAttribute_Parameter(_textureWidth)
COMPARE_StateAttribute_Parameter(_textureHeight)
#endif
COMPARE_StateAttribute_Parameter(_subloadCallback)
return 0; // passed all the above comparison macro's, must be equal.

View File

@@ -27,17 +27,30 @@ DatabasePager::DatabasePager()
_deleteRemovedSubgraphsInDatabaseThread = true;
_expiryDelay = 1.0;
// make sure a SharedStateManager exists.
//osgDB::Registry::instance()->getOrCreateSharedStateManager();
//if (osgDB::Registry::instance()->getSharedStateManager())
//osgDB::Registry::instance()->setUseObjectCacheHint(true);
}
DatabasePager::~DatabasePager()
{
//std::cout<<"DatabasePager::~DatabasePager()"<<std::endl;
if( isRunning() )
{
// cancel the thread..
cancel();
//join();
// release the frameBlock incase its holding up thread cancelation.
_frameBlock->release();
// then wait for the the thread to stop running.
while(isRunning())
{
@@ -308,14 +321,14 @@ void DatabasePager::run()
// check if databaseRequest is still relevant
if (_frameNumber-databaseRequest->_frameNumberLastRequest<=1)
{
// load the data, note safe to write to the databaseRequest since once
// it is created this thread is the only one to write to the _loadedModel pointer.
osg::notify(osg::INFO)<<"In DatabasePager thread readNodeFile("<<databaseRequest->_fileName<<")"<<std::endl;
osg::Timer_t before = osg::Timer::instance()->tick();
databaseRequest->_loadedModel = osgDB::readNodeFile(databaseRequest->_fileName);
osg::notify(osg::INFO)<<" node read in "<<osg::Timer::instance()->delta_m(before,osg::Timer::instance()->tick())<<" ms"<<std::endl;
bool loadedObjectsNeedToBeCompiled = false;
if (databaseRequest->_loadedModel.valid() && !_activeGraphicsContexts.empty())
@@ -422,6 +435,12 @@ void DatabasePager::addLoadedDataToSceneGraph(double timeStamp)
++itr)
{
DatabaseRequest* databaseRequest = itr->get();
if (osgDB::Registry::instance()->getSharedStateManager())
osgDB::Registry::instance()->getSharedStateManager()->share(databaseRequest->_loadedModel.get());
registerPagedLODs(databaseRequest->_loadedModel.get());
osg::Group* group = databaseRequest->_groupForAddingLoadedSubgraph.get();
@@ -535,6 +554,10 @@ void DatabasePager::removeExpiredSubgraphs(double currentFrameTime)
}
if (osgDB::Registry::instance()->getSharedStateManager())
osgDB::Registry::instance()->getSharedStateManager()->prune();
if (_deleteRemovedSubgraphsInDatabaseThread)
{
// transfer the removed children over to the to delete list so the database thread can delete them.

View File

@@ -17,6 +17,7 @@ CXXFILES =\
FieldReader.cpp\
FieldReaderIterator.cpp\
DotOsgWrapper.cpp\
SharedStateManager.cpp\
LIBS += -losg $(OTHER_LIBS) $(DYNAMICLIBRARYLIB)

View File

@@ -201,6 +201,18 @@ Registry::~Registry()
// rest of the Registry.
_databasePager = 0;
// clean up the SharedStateManager
_sharedStateManager = 0;
// object cache clear needed here to prevent crash in unref() of
// the objects it contains when running the TXP plugin.
// Not sure why, but perhaps there is is something in a TXP plugin
// which is deleted the data before its ref count hits zero, perhaps
// even some issue with objects be allocated by a plugin that is
// mainted after that plugin is deleted... Robert Osfield, Jan 2004.
_objectCache.clear();
// unload all the plugin before we finally destruct.
closeAllLibraries();
}
@@ -1831,6 +1843,7 @@ void Registry::removeExpiredObjectsInCache(double expiryTime)
ritr!=objectsToRemove.end();
++ritr)
{
// std::cout<<"Removing from Registry object cache '"<<*ritr<<"'"<<std::endl;
_objectCache.erase(*ritr);
}
@@ -1847,3 +1860,10 @@ DatabasePager* Registry::getOrCreateDatabasePager()
return _databasePager.get();
}
SharedStateManager* Registry::getOrCreateSharedStateManager()
{
if (!_sharedStateManager) _sharedStateManager = new SharedStateManager;
return _sharedStateManager.get();
}

View File

@@ -0,0 +1,246 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osg/Timer>
#include <osgDB/SharedStateManager>
using namespace osgDB;
SharedStateManager::SharedStateManager():
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
{
shareMode = SHARE_TEXTURES;
//shareMode = SHARE_STATESETS;
mutex=0;
}
//----------------------------------------------------------------
// SharedStateManager::prune
//----------------------------------------------------------------
void SharedStateManager::prune()
{
StateSetSet::iterator sitr, sitr1;
for(sitr=_sharedStateSetList.begin(); sitr!=_sharedStateSetList.end(); sitr=sitr1)
{
sitr1=sitr; ++sitr1;
if((*sitr)->referenceCount()<=1) _sharedStateSetList.erase(sitr);
}
TextureSet::iterator titr, titr1;
for(titr=_sharedTextureList.begin(); titr!=_sharedTextureList.end(); titr=titr1)
{
titr1=titr; ++titr1;
if((*titr)->referenceCount()<=1) _sharedTextureList.erase(titr);
}
}
//----------------------------------------------------------------
// SharedStateManager::share
//----------------------------------------------------------------
void SharedStateManager::share(osg::Node *node, OpenThreads::Mutex *mt)
{
const osg::Timer& timer = *osg::Timer::instance();
osg::Timer_t start_tick = timer.tick();
mutex = mt;
apply(*node);
tmpSharedTextureList.clear();
tmpSharedStateSetList.clear();
mutex = 0;
osg::Timer_t end_tick = timer.tick();
// std::cout << "SHARING TIME = "<<timer.delta_m(start_tick,end_tick)<<"ms"<<std::endl;
// std::cout << " _sharedStateSetList.size() = "<<_sharedStateSetList.size()<<std::endl;
// std::cout << " _sharedTextureList.size() = "<<_sharedTextureList.size()<<std::endl;
}
//----------------------------------------------------------------
// SharedStateManager::apply
//----------------------------------------------------------------
void SharedStateManager::apply(osg::Node& node)
{
osg::StateSet* ss = node.getStateSet();
if(ss) process(ss, &node);
traverse(node);
}
void SharedStateManager::apply(osg::Geode& geode)
{
osg::StateSet* ss = geode.getStateSet();
if(ss) process(ss, &geode);
for(unsigned int i=0;i<geode.getNumDrawables();++i)
{
osg::Drawable* drawable = geode.getDrawable(i);
if(drawable)
{
ss = drawable->getStateSet();
if(ss) process(ss, drawable);
}
}
}
//----------------------------------------------------------------
// SharedStateManager::find
//----------------------------------------------------------------
osg::StateSet *SharedStateManager::find(osg::StateSet *ss)
{
for(StateSetSet::iterator itr=_sharedStateSetList.begin();
itr!=_sharedStateSetList.end();
++itr)
{
if(ss->compare(*(itr->get()),true)==0)
return (osg::StateSet *)itr->get();
}
return NULL;
}
osg::StateAttribute *SharedStateManager::find(osg::StateAttribute *sa)
{
for(TextureSet::iterator itr=_sharedTextureList.begin();
itr!=_sharedTextureList.end();
++itr)
{
if(sa->compare(*(itr->get()))==0)
return (osg::StateAttribute *)itr->get();
}
return NULL;
}
//----------------------------------------------------------------
// SharedStateManager::setStateSet
//----------------------------------------------------------------
void SharedStateManager::setStateSet(osg::StateSet* ss, osg::Object* object)
{
osg::Drawable* drawable = dynamic_cast<osg::Drawable*>(object);
if (drawable)
{
drawable->setStateSet(ss);
}
else
{
osg::Node* node = dynamic_cast<osg::Node*>(object);
if (node)
{
node->setStateSet(ss);
}
}
}
//----------------------------------------------------------------
// SharedStateManager::shareTextures
//----------------------------------------------------------------
void SharedStateManager::shareTextures(osg::StateSet* ss)
{
osg::StateSet::TextureAttributeList& texAttributes = ss->getTextureAttributeList();
for(unsigned int unit=0;unit<texAttributes.size();++unit)
{
osg::StateAttribute *texture = ss->getTextureAttribute(unit, osg::StateAttribute::TEXTURE);
// Valid Texture to be shared
if(texture && texture->getDataVariance()==osg::Object::STATIC)
{
TextureTextureSharePairMap::iterator titr = tmpSharedTextureList.find(texture);
if(titr==tmpSharedTextureList.end())
{
// Texture is not in tmp list:
// First time it appears in this file, search Texture in sharedAttributeList
osg::StateAttribute *textureFromSharedList = find(texture);
if(textureFromSharedList)
{
// Texture is in sharedAttributeList:
// Share now. Required to be shared all next times
if(mutex) mutex->lock();
ss->setTextureAttributeAndModes(unit, textureFromSharedList, osg::StateAttribute::ON);
if(mutex) mutex->unlock();
tmpSharedTextureList[texture] = TextureSharePair(textureFromSharedList, true);
}
else
{
// Texture is not in _sharedAttributeList:
// Add to _sharedAttributeList. Not needed to be shared all next times.
_sharedTextureList.insert(texture);
tmpSharedTextureList[texture] = TextureSharePair(texture, false);
}
}
else if(titr->second.second)
{
// Texture is in tmpSharedAttributeList and share flag is on:
// It should be shared
if(mutex) mutex->lock();
ss->setTextureAttributeAndModes(unit, titr->second.first, osg::StateAttribute::ON);
if(mutex) mutex->unlock();
}
}
}
}
//----------------------------------------------------------------
// SharedStateManager::process
//----------------------------------------------------------------
void SharedStateManager::process(osg::StateSet* ss, osg::Object* parent)
{
if(shareMode & SHARE_STATESETS)
{
// Valid StateSet to be shared
if(ss->getDataVariance()==osg::Object::STATIC)
{
StateSetStateSetSharePairMap::iterator sitr = tmpSharedStateSetList.find(ss);
if(sitr==tmpSharedStateSetList.end())
{
// StateSet is not in tmp list:
// First time it appears in this file, search StateSet in sharedObjectList
osg::StateSet *ssFromSharedList = find(ss);
if(ssFromSharedList)
{
// StateSet is in sharedStateSetList:
// Share now. Required to be shared all next times
if(mutex) mutex->lock();
setStateSet(ssFromSharedList, parent);
if(mutex) mutex->unlock();
tmpSharedStateSetList[ss] = StateSetSharePair(ssFromSharedList, true);
}
else
{
// StateSet is not in sharedStateSetList:
// Add to sharedStateSetList. Not needed to be shared all next times.
_sharedStateSetList.insert(ss);
tmpSharedStateSetList[ss] = StateSetSharePair(ss, false);
// Only in this case sharing textures is also required
if(shareMode & SHARE_TEXTURES)
{
shareTextures(ss);
}
}
}
else if(sitr->second.second)
{
// StateSet is in tmpSharedStateSetList and share flag is on:
// It should be shared
if(mutex) mutex->lock();
setStateSet(sitr->second.first, parent);
if(mutex) mutex->unlock();
}
}
}
else if(shareMode & SHARE_TEXTURES)
{
shareTextures(ss);
}
}