From Tim More, "This submission tries to optimize redundant compilation of StateSets and Drawables
in the DatabasePager. The practical effects of these are to greatly reduce startup time and the time to load an individual scenery tile in FlightGear. - From my log message: Minimize the number of StateSets and drawables that are compiled by checking if they have already been compiled or will be elminated by the SharedStateManager. Move the sorting of the dataToCompile queue out of compileGLObjects into the man pager run function. Change the SharedStateManager to use maps instead of vectors."
This commit is contained in:
@@ -31,6 +31,8 @@
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
namespace osgDB {
|
||||
|
||||
@@ -275,7 +277,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
|
||||
|
||||
|
||||
friend struct DatabaseRequest;
|
||||
|
||||
|
||||
struct DatabaseRequest : public osg::Referenced
|
||||
{
|
||||
DatabaseRequest():
|
||||
@@ -294,8 +296,13 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
|
||||
osg::ref_ptr<osg::Node> _loadedModel;
|
||||
DataToCompileMap _dataToCompileMap;
|
||||
osg::ref_ptr<ReaderWriter::Options> _loadOptions;
|
||||
|
||||
bool isRequestCurrent (int frameNumber) const
|
||||
{
|
||||
return frameNumber - _frameNumberLastRequest <= 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector< osg::ref_ptr<DatabaseRequest> > DatabaseRequestList;
|
||||
typedef std::vector< osg::ref_ptr<osg::Object> > ObjectList;
|
||||
|
||||
@@ -321,8 +328,86 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl
|
||||
_databasePagerThreadBlock->set(
|
||||
(!_fileRequestList.empty() || !_childrenToDeleteList.empty()) && !_databasePagerThreadPaused);
|
||||
}
|
||||
|
||||
|
||||
// Helper functions for determining if objects need to be
|
||||
// compiled.
|
||||
inline static bool isCompiled(const osg::Texture* texture,
|
||||
unsigned int contextID)
|
||||
{
|
||||
return texture->getTextureObject(contextID);
|
||||
}
|
||||
// Is texture compiled for all active contexts?
|
||||
inline bool isCompiled(osg::Texture* texture) const
|
||||
{
|
||||
using namespace std;
|
||||
return (count_if(_activeGraphicsContexts.begin(),
|
||||
_activeGraphicsContexts.end(),
|
||||
bind1st(mem_fun(&osg::Texture::getTextureObject),
|
||||
texture))
|
||||
== _activeGraphicsContexts.size());
|
||||
}
|
||||
|
||||
inline static bool isCompiled(const osg::StateSet* stateSet,
|
||||
unsigned int contextID)
|
||||
{
|
||||
for (unsigned i = 0;
|
||||
i < stateSet->getTextureAttributeList().size();
|
||||
++i)
|
||||
{
|
||||
const osg::Texture* texture
|
||||
= dynamic_cast<const osg::Texture*>(stateSet->getTextureAttribute(i,osg::StateAttribute::TEXTURE));
|
||||
if (texture && !isCompiled(texture, contextID))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool isCompiled(osg::StateSet* stateSet)
|
||||
{
|
||||
using namespace std;
|
||||
for (unsigned i = 0;
|
||||
i < stateSet->getTextureAttributeList().size();
|
||||
++i)
|
||||
{
|
||||
osg::Texture* texture
|
||||
= dynamic_cast<osg::Texture*>(stateSet->getTextureAttribute(i,osg::StateAttribute::TEXTURE));
|
||||
if (texture
|
||||
&& (count_if(_activeGraphicsContexts.begin(),
|
||||
_activeGraphicsContexts.end(),
|
||||
bind1st(mem_fun(&osg::Texture::getTextureObject),
|
||||
texture))
|
||||
!= _activeGraphicsContexts.size()))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline static bool isCompiled(const osg::Drawable* drawable,
|
||||
unsigned int contextID)
|
||||
{
|
||||
// Worry about vbos later
|
||||
if (drawable->getUseDisplayList())
|
||||
{
|
||||
return drawable->getDisplayList(contextID) != 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool isCompiled(const osg::Drawable* drawable) const
|
||||
{
|
||||
using namespace std;
|
||||
if (drawable->getUseDisplayList())
|
||||
{
|
||||
return (count_if(_activeGraphicsContexts.begin(),
|
||||
_activeGraphicsContexts.end(),
|
||||
bind1st(mem_fun(&osg::Drawable::getDisplayList),
|
||||
drawable))
|
||||
== _activeGraphicsContexts.size());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/** Iterate through the active PagedLOD nodes children removing
|
||||
* children which havn't been visited since specified expiryTime.
|
||||
* note, should be only be called from the update thread. */
|
||||
|
||||
@@ -42,8 +42,8 @@ namespace osgDB {
|
||||
|
||||
SharedStateManager();
|
||||
|
||||
void setShareMode(unsigned int mode) { shareMode = mode; }
|
||||
unsigned int getShareMode() { return shareMode; }
|
||||
void setShareMode(unsigned int mode) { _shareMode = mode; }
|
||||
unsigned int getShareMode() { return _shareMode; }
|
||||
|
||||
// Call right after each unload and before Registry cache prune.
|
||||
void prune();
|
||||
@@ -53,7 +53,10 @@ namespace osgDB {
|
||||
|
||||
void apply(osg::Node& node);
|
||||
void apply(osg::Geode& geode);
|
||||
|
||||
// Answers the question "Will this state set be eliminated by
|
||||
// the SharedStateManager because an equivalent one has been
|
||||
// seen already?" Safe to call from the pager thread.
|
||||
bool isShared(osg::StateSet* stateSet);
|
||||
protected:
|
||||
|
||||
void process(osg::StateSet* ss, osg::Object* parent);
|
||||
@@ -62,24 +65,46 @@ namespace osgDB {
|
||||
void setStateSet(osg::StateSet* ss, osg::Object* object);
|
||||
void shareTextures(osg::StateSet* ss);
|
||||
|
||||
struct CompareStateAttributes
|
||||
{
|
||||
bool operator()(const osg::ref_ptr<osg::StateAttribute>& lhs,
|
||||
const osg::ref_ptr<osg::StateAttribute>& rhs)
|
||||
{
|
||||
return *lhs < *rhs;
|
||||
}
|
||||
};
|
||||
|
||||
struct CompareStateSets
|
||||
{
|
||||
bool operator()(const osg::ref_ptr<osg::StateSet>& lhs,
|
||||
const osg::ref_ptr<osg::StateSet>& rhs)
|
||||
{
|
||||
return lhs->compare(*rhs, true) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Lists of shared objects
|
||||
typedef std::set< osg::ref_ptr<osg::StateAttribute> > TextureSet;
|
||||
typedef std::set< osg::ref_ptr<osg::StateAttribute>, CompareStateAttributes > TextureSet;
|
||||
TextureSet _sharedTextureList;
|
||||
typedef std::set< osg::ref_ptr<osg::StateSet> > StateSetSet;
|
||||
|
||||
typedef std::set< osg::ref_ptr<osg::StateSet>, CompareStateSets > StateSetSet;
|
||||
StateSetSet _sharedStateSetList;
|
||||
|
||||
// Temporary lists just to avoid unnecessary 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;
|
||||
unsigned int _shareMode;
|
||||
|
||||
OpenThreads::Mutex *mutex;
|
||||
OpenThreads::Mutex *_mutex;
|
||||
// Mutex for doing isShared queries from other threads
|
||||
mutable OpenThreads::Mutex _listMutex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user