Began work on providing support for threading camera cull traversals in parallel with
the previous frames draw traversal. Changes range from osg::State, through osgUtil::RenderBin, through to osgViewer
This commit is contained in:
parent
6835996c21
commit
fd0ea388c2
@ -753,6 +753,47 @@ class OSG_EXPORT State : public Referenced
|
|||||||
* if true steps should be taken to complete rendering early.*/
|
* if true steps should be taken to complete rendering early.*/
|
||||||
bool getAbortRendering() const { return _abortRenderingPtr!=0?(*_abortRenderingPtr):false; }
|
bool getAbortRendering() const { return _abortRenderingPtr!=0?(*_abortRenderingPtr):false; }
|
||||||
|
|
||||||
|
|
||||||
|
struct DynamicObjectRenderingCompletedCallback : public osg::Referenced
|
||||||
|
{
|
||||||
|
virtual void completed(osg::State*) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Set the callback to be called when the dynamic object count hits 0.*/
|
||||||
|
void setDynamicObjectRenderingCompletedCallback(DynamicObjectRenderingCompletedCallback* cb){ _completeDynamicObjectRenderingCallback = cb; }
|
||||||
|
|
||||||
|
/** Get the callback to be called when the dynamic object count hits 0.*/
|
||||||
|
DynamicObjectRenderingCompletedCallback* getDynamicObjectRenderingCompletedCallback() { return _completeDynamicObjectRenderingCallback.get(); }
|
||||||
|
|
||||||
|
/** Set the number of dynamic objects that will be rendered in this graphics context this frame.*/
|
||||||
|
void setDynamicObjectCount(unsigned int count, bool callCallbackOnZero = false)
|
||||||
|
{
|
||||||
|
if (_dynamicObjectCount != count)
|
||||||
|
{
|
||||||
|
_dynamicObjectCount = count;
|
||||||
|
if (_dynamicObjectCount==0 && callCallbackOnZero && _completeDynamicObjectRenderingCallback.valid())
|
||||||
|
{
|
||||||
|
_completeDynamicObjectRenderingCallback->completed(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the number of dynamic objects that will be rendered in this graphics context this frame.*/
|
||||||
|
unsigned int getDynamicObjectCount() const { return _dynamicObjectCount; }
|
||||||
|
|
||||||
|
/** Decrement the number of dynamic objects left to render this frame, and once the count goes to zero call the
|
||||||
|
* DynamicObjectRenderingCompletedCallback to inform of completion.*/
|
||||||
|
inline void decrementDynamicObjectCount()
|
||||||
|
{
|
||||||
|
--_dynamicObjectCount;
|
||||||
|
if (_dynamicObjectCount==0 && _completeDynamicObjectRenderingCallback.valid())
|
||||||
|
{
|
||||||
|
_completeDynamicObjectRenderingCallback->completed(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
enum CheckForGLErrors
|
enum CheckForGLErrors
|
||||||
{
|
{
|
||||||
/** NEVER_CHECK_GL_ERRORS hints that OpenGL need not be checked for, this
|
/** NEVER_CHECK_GL_ERRORS hints that OpenGL need not be checked for, this
|
||||||
@ -1028,6 +1069,9 @@ class OSG_EXPORT State : public Referenced
|
|||||||
DisableVertexAttribProc _glDisableVertexAttribArray;
|
DisableVertexAttribProc _glDisableVertexAttribArray;
|
||||||
void initializeExtensionProcs();
|
void initializeExtensionProcs();
|
||||||
|
|
||||||
|
unsigned int _dynamicObjectCount;
|
||||||
|
osg::ref_ptr<DynamicObjectRenderingCompletedCallback> _completeDynamicObjectRenderingCallback;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void State::pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
|
inline void State::pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList)
|
||||||
|
@ -82,6 +82,7 @@ class OSGUTIL_EXPORT Optimizer
|
|||||||
MERGE_GEODES = 0x1000,
|
MERGE_GEODES = 0x1000,
|
||||||
FLATTEN_BILLBOARDS = 0x2000,
|
FLATTEN_BILLBOARDS = 0x2000,
|
||||||
TEXTURE_ATLAS_BUILDER = 0x4000,
|
TEXTURE_ATLAS_BUILDER = 0x4000,
|
||||||
|
STATIC_OBJECT_DETECTION = 0x8000,
|
||||||
DEFAULT_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS |
|
DEFAULT_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS |
|
||||||
REMOVE_REDUNDANT_NODES |
|
REMOVE_REDUNDANT_NODES |
|
||||||
REMOVE_LOADED_PROXY_NODES |
|
REMOVE_LOADED_PROXY_NODES |
|
||||||
@ -89,7 +90,8 @@ class OSGUTIL_EXPORT Optimizer
|
|||||||
SHARE_DUPLICATE_STATE |
|
SHARE_DUPLICATE_STATE |
|
||||||
MERGE_GEOMETRY |
|
MERGE_GEOMETRY |
|
||||||
CHECK_GEOMETRY |
|
CHECK_GEOMETRY |
|
||||||
OPTIMIZE_TEXTURE_SETTINGS,
|
OPTIMIZE_TEXTURE_SETTINGS |
|
||||||
|
STATIC_OBJECT_DETECTION,
|
||||||
ALL_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS |
|
ALL_OPTIMIZATIONS = FLATTEN_STATIC_TRANSFORMS |
|
||||||
REMOVE_REDUNDANT_NODES |
|
REMOVE_REDUNDANT_NODES |
|
||||||
REMOVE_LOADED_PROXY_NODES |
|
REMOVE_LOADED_PROXY_NODES |
|
||||||
@ -102,7 +104,8 @@ class OSGUTIL_EXPORT Optimizer
|
|||||||
COPY_SHARED_NODES |
|
COPY_SHARED_NODES |
|
||||||
TRISTRIP_GEOMETRY |
|
TRISTRIP_GEOMETRY |
|
||||||
OPTIMIZE_TEXTURE_SETTINGS |
|
OPTIMIZE_TEXTURE_SETTINGS |
|
||||||
TEXTURE_ATLAS_BUILDER
|
TEXTURE_ATLAS_BUILDER |
|
||||||
|
STATIC_OBJECT_DETECTION
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Reset internal data to initial state - the getPermissibleOptionsMap is cleared.*/
|
/** Reset internal data to initial state - the getPermissibleOptionsMap is cleared.*/
|
||||||
@ -740,6 +743,27 @@ class OSGUTIL_EXPORT Optimizer
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Optimize the setting of StateSet and Geometry objects in scene so that they have a STATIC DataVariance
|
||||||
|
* when they don't have any callbacks associated with them. */
|
||||||
|
class OSGUTIL_EXPORT StaticObjectDetectionVisitor : public BaseOptimizerVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// default to traversing all children.
|
||||||
|
StaticObjectDetectionVisitor(Optimizer* optimizer=0):
|
||||||
|
BaseOptimizerVisitor(optimizer, STATIC_OBJECT_DETECTION) {}
|
||||||
|
|
||||||
|
virtual void apply(osg::Node& node);
|
||||||
|
|
||||||
|
virtual void apply(osg::Geode& geode);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void applyStateSet(osg::StateSet& stateset);
|
||||||
|
|
||||||
|
void applyDrawable(osg::Drawable& drawable);
|
||||||
|
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool BaseOptimizerVisitor::isOperationPermissibleForObject(const osg::StateSet* object) const
|
inline bool BaseOptimizerVisitor::isOperationPermissibleForObject(const osg::StateSet* object) const
|
||||||
|
@ -140,6 +140,9 @@ class OSGUTIL_EXPORT RenderBin : public osg::Object
|
|||||||
|
|
||||||
/** Extract stats for current draw list. */
|
/** Extract stats for current draw list. */
|
||||||
bool getStats(Statistics& primStats) const;
|
bool getStats(Statistics& primStats) const;
|
||||||
|
|
||||||
|
/** Compute the number of dynamic RenderLeaves.*/
|
||||||
|
virtual unsigned int computeNumberOfDynamicRenderLeaves() const;
|
||||||
|
|
||||||
void copyLeavesFromStateGraphListToRenderLeafList();
|
void copyLeavesFromStateGraphListToRenderLeafList();
|
||||||
|
|
||||||
|
@ -39,16 +39,20 @@ class OSGUTIL_EXPORT RenderLeaf : public osg::Referenced
|
|||||||
_drawable(drawable),
|
_drawable(drawable),
|
||||||
_projection(projection),
|
_projection(projection),
|
||||||
_modelview(modelview),
|
_modelview(modelview),
|
||||||
_depth(depth) {}
|
_depth(depth)
|
||||||
|
{
|
||||||
|
_dynamic = (drawable->getDataVariance()==osg::Object::DYNAMIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void set(osg::Drawable* drawable,osg::RefMatrix* projection,osg::RefMatrix* modelview, float depth=0.0f)
|
inline void set(osg::Drawable* drawable,osg::RefMatrix* projection,osg::RefMatrix* modelview, float depth=0.0f)
|
||||||
{
|
{
|
||||||
_parent = 0;
|
_parent = 0;
|
||||||
_drawable = drawable;
|
_drawable = drawable;
|
||||||
_projection = projection,
|
_projection = projection,
|
||||||
_modelview = modelview,
|
_modelview = modelview,
|
||||||
_depth = depth;
|
_depth = depth;
|
||||||
|
_dynamic = (drawable->getDataVariance()==osg::Object::DYNAMIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void reset()
|
inline void reset()
|
||||||
@ -58,6 +62,7 @@ class OSGUTIL_EXPORT RenderLeaf : public osg::Referenced
|
|||||||
_projection = 0;
|
_projection = 0;
|
||||||
_modelview = 0;
|
_modelview = 0;
|
||||||
_depth = 0.0f;
|
_depth = 0.0f;
|
||||||
|
_dynamic = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void render(osg::RenderInfo& renderInfo,RenderLeaf* previous);
|
virtual void render(osg::RenderInfo& renderInfo,RenderLeaf* previous);
|
||||||
@ -72,6 +77,7 @@ class OSGUTIL_EXPORT RenderLeaf : public osg::Referenced
|
|||||||
osg::ref_ptr<osg::RefMatrix> _projection;
|
osg::ref_ptr<osg::RefMatrix> _projection;
|
||||||
osg::ref_ptr<osg::RefMatrix> _modelview;
|
osg::ref_ptr<osg::RefMatrix> _modelview;
|
||||||
float _depth;
|
float _depth;
|
||||||
|
bool _dynamic;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -201,9 +201,10 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin
|
|||||||
/** Extract stats for current draw list. */
|
/** Extract stats for current draw list. */
|
||||||
bool getStats(Statistics& stats) const;
|
bool getStats(Statistics& stats) const;
|
||||||
|
|
||||||
|
/** Compute the number of dynamic RenderLeaves.*/
|
||||||
|
virtual unsigned int computeNumberOfDynamicRenderLeaves() const;
|
||||||
|
|
||||||
|
struct Attachment
|
||||||
struct Attachment
|
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Image> _image;
|
osg::ref_ptr<osg::Image> _image;
|
||||||
GLenum _imageReadPixelFormat;
|
GLenum _imageReadPixelFormat;
|
||||||
|
@ -58,6 +58,7 @@ class OSGUTIL_EXPORT StateGraph : public osg::Referenced
|
|||||||
|
|
||||||
osg::ref_ptr<osg::Referenced> _userData;
|
osg::ref_ptr<osg::Referenced> _userData;
|
||||||
|
|
||||||
|
bool _dynamic;
|
||||||
|
|
||||||
StateGraph():
|
StateGraph():
|
||||||
osg::Referenced(false),
|
osg::Referenced(false),
|
||||||
@ -66,7 +67,8 @@ class OSGUTIL_EXPORT StateGraph : public osg::Referenced
|
|||||||
_depth(0),
|
_depth(0),
|
||||||
_averageDistance(0),
|
_averageDistance(0),
|
||||||
_minimumDistance(0),
|
_minimumDistance(0),
|
||||||
_userData(NULL)
|
_userData(NULL),
|
||||||
|
_dynamic(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,9 +79,13 @@ class OSGUTIL_EXPORT StateGraph : public osg::Referenced
|
|||||||
_depth(0),
|
_depth(0),
|
||||||
_averageDistance(0),
|
_averageDistance(0),
|
||||||
_minimumDistance(0),
|
_minimumDistance(0),
|
||||||
_userData(NULL)
|
_userData(NULL),
|
||||||
|
_dynamic(false)
|
||||||
{
|
{
|
||||||
if (_parent) _depth = _parent->_depth + 1;
|
if (_parent) _depth = _parent->_depth + 1;
|
||||||
|
|
||||||
|
if (_parent && _parent->_dynamic) _dynamic = true;
|
||||||
|
else _dynamic = stateset->getDataVariance()==osg::Object::DYNAMIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
~StateGraph() {}
|
~StateGraph() {}
|
||||||
@ -176,6 +182,7 @@ class OSGUTIL_EXPORT StateGraph : public osg::Referenced
|
|||||||
_minimumDistance = FLT_MAX; // signify dirty.
|
_minimumDistance = FLT_MAX; // signify dirty.
|
||||||
_leaves.push_back(leaf);
|
_leaves.push_back(leaf);
|
||||||
leaf->_parent = this;
|
leaf->_parent = this;
|
||||||
|
if (_dynamic) leaf->_dynamic = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,30 @@
|
|||||||
|
|
||||||
namespace osgViewer {
|
namespace osgViewer {
|
||||||
|
|
||||||
|
class OSGVIEWER_EXPORT EndOfDynamicDrawBlock : public osg::State::DynamicObjectRenderingCompletedCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
EndOfDynamicDrawBlock();
|
||||||
|
|
||||||
|
void completed(osg::State* state);
|
||||||
|
|
||||||
|
void block();
|
||||||
|
|
||||||
|
void release();
|
||||||
|
|
||||||
|
void set(unsigned int blockCount);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
~EndOfDynamicDrawBlock();
|
||||||
|
|
||||||
|
OpenThreads::Mutex _mut;
|
||||||
|
OpenThreads::Condition _cond;
|
||||||
|
unsigned int _blockCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/** View holds a single view on a scene, this view may be composed of one or more slave cameras.*/
|
/** View holds a single view on a scene, this view may be composed of one or more slave cameras.*/
|
||||||
class OSGVIEWER_EXPORT View : public osg::View, public osgGA::GUIActionAdapter
|
class OSGVIEWER_EXPORT View : public osg::View, public osgGA::GUIActionAdapter
|
||||||
{
|
{
|
||||||
|
@ -63,6 +63,13 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View
|
|||||||
/** Get the threading model the rendering traversals will use.*/
|
/** Get the threading model the rendering traversals will use.*/
|
||||||
ThreadingModel getThreadingModel() const { return _threadingModel; }
|
ThreadingModel getThreadingModel() const { return _threadingModel; }
|
||||||
|
|
||||||
|
/** Set whether the main thread, calling frame(), should be used for the rendering traversals.*/
|
||||||
|
void setUseMainThreadForRenderingTraversals(bool flag);
|
||||||
|
|
||||||
|
/** Get whether the main thread, calling frame(), should be used for the rendering traversals.*/
|
||||||
|
bool getUseMainThreadForRenderingTraversals() const { return _useMainThreadForRenderingTraversal; }
|
||||||
|
|
||||||
|
|
||||||
enum BarrierPosition
|
enum BarrierPosition
|
||||||
{
|
{
|
||||||
BeforeSwapBuffers,
|
BeforeSwapBuffers,
|
||||||
@ -148,11 +155,13 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View
|
|||||||
int _keyEventSetsDone;
|
int _keyEventSetsDone;
|
||||||
bool _quitEventSetsDone;
|
bool _quitEventSetsDone;
|
||||||
|
|
||||||
ThreadingModel _threadingModel;
|
ThreadingModel _threadingModel;
|
||||||
|
bool _useMainThreadForRenderingTraversal;
|
||||||
BarrierPosition _endBarrierPosition;
|
BarrierPosition _endBarrierPosition;
|
||||||
|
|
||||||
osg::ref_ptr<osg::BarrierOperation> _startRenderingBarrier;
|
osg::ref_ptr<osg::BarrierOperation> _startRenderingBarrier;
|
||||||
osg::ref_ptr<osg::BarrierOperation> _endRenderingDispatchBarrier;
|
osg::ref_ptr<osg::BarrierOperation> _endRenderingDispatchBarrier;
|
||||||
|
osg::ref_ptr<EndOfDynamicDrawBlock> _endDynamicDrawBlock;
|
||||||
|
|
||||||
unsigned int computeNumberOfThreadsIncludingMainRequired();
|
unsigned int computeNumberOfThreadsIncludingMainRequired();
|
||||||
|
|
||||||
|
@ -246,6 +246,8 @@ void Drawable::flushDeletedVertexBufferObjects(unsigned int contextID,double /*c
|
|||||||
|
|
||||||
Drawable::Drawable()
|
Drawable::Drawable()
|
||||||
{
|
{
|
||||||
|
setDataVariance(osg::Object::STATIC);
|
||||||
|
|
||||||
_boundingBoxComputed = false;
|
_boundingBoxComputed = false;
|
||||||
|
|
||||||
// Note, if your are defining a subclass from drawable which is
|
// Note, if your are defining a subclass from drawable which is
|
||||||
|
@ -53,6 +53,8 @@ State::State()
|
|||||||
_glVertexAttribPointer = 0;
|
_glVertexAttribPointer = 0;
|
||||||
_glEnableVertexAttribArray = 0;
|
_glEnableVertexAttribArray = 0;
|
||||||
_glDisableVertexAttribArray = 0;
|
_glDisableVertexAttribArray = 0;
|
||||||
|
|
||||||
|
_dynamicObjectCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
State::~State()
|
State::~State()
|
||||||
|
@ -80,7 +80,7 @@ bool osg::isTextureMode(StateAttribute::GLMode mode)
|
|||||||
|
|
||||||
StateSet::StateSet()
|
StateSet::StateSet()
|
||||||
{
|
{
|
||||||
setDataVariance(osg::StateAttribute::STATIC);
|
setDataVariance(osg::Object::STATIC);
|
||||||
|
|
||||||
_renderingHint = DEFAULT_BIN;
|
_renderingHint = DEFAULT_BIN;
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ void Optimizer::reset()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static osg::ApplicationUsageProxy Optimizer_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_OPTIMIZER \"<type> [<type>]\"","OFF | DEFAULT | FLATTEN_STATIC_TRANSFORMS | REMOVE_REDUNDANT_NODES | COMBINE_ADJACENT_LODS | SHARE_DUPLICATE_STATE | MERGE_GEOMETRY | MERGE_GEODES | SPATIALIZE_GROUPS | COPY_SHARED_NODES | TRISTRIP_GEOMETRY | OPTIMIZE_TEXTURE_SETTINGS | REMOVE_LOADED_PROXY_NODES | TESSELLATE_GEOMETRY | CHECK_GEOMETRY | FLATTEN_BILLBOARDS | TEXTURE_ATLAS_BUILDER");
|
static osg::ApplicationUsageProxy Optimizer_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_OPTIMIZER \"<type> [<type>]\"","OFF | DEFAULT | FLATTEN_STATIC_TRANSFORMS | REMOVE_REDUNDANT_NODES | COMBINE_ADJACENT_LODS | SHARE_DUPLICATE_STATE | MERGE_GEOMETRY | MERGE_GEODES | SPATIALIZE_GROUPS | COPY_SHARED_NODES | TRISTRIP_GEOMETRY | OPTIMIZE_TEXTURE_SETTINGS | REMOVE_LOADED_PROXY_NODES | TESSELLATE_GEOMETRY | CHECK_GEOMETRY | FLATTEN_BILLBOARDS | TEXTURE_ATLAS_BUILDER | STATIC_OBJECT_DETECTION");
|
||||||
|
|
||||||
void Optimizer::optimize(osg::Node* node)
|
void Optimizer::optimize(osg::Node* node)
|
||||||
{
|
{
|
||||||
@ -108,6 +108,9 @@ void Optimizer::optimize(osg::Node* node)
|
|||||||
|
|
||||||
if(str.find("~TEXTURE_ATLAS_BUILDER")!=std::string::npos) options ^= TEXTURE_ATLAS_BUILDER;
|
if(str.find("~TEXTURE_ATLAS_BUILDER")!=std::string::npos) options ^= TEXTURE_ATLAS_BUILDER;
|
||||||
else if(str.find("TEXTURE_ATLAS_BUILDER")!=std::string::npos) options |= TEXTURE_ATLAS_BUILDER;
|
else if(str.find("TEXTURE_ATLAS_BUILDER")!=std::string::npos) options |= TEXTURE_ATLAS_BUILDER;
|
||||||
|
|
||||||
|
if(str.find("~STATIC_OBJECT_DETECTION")!=std::string::npos) options ^= STATIC_OBJECT_DETECTION;
|
||||||
|
else if(str.find("STATIC_OBJECT_DETECTION")!=std::string::npos) options |= STATIC_OBJECT_DETECTION;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -299,7 +302,13 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
|
|||||||
node->accept(sv);
|
node->accept(sv);
|
||||||
sv.divide();
|
sv.divide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options & STATIC_OBJECT_DETECTION)
|
||||||
|
{
|
||||||
|
StaticObjectDetectionVisitor sodv;
|
||||||
|
node->accept(sodv);
|
||||||
|
}
|
||||||
|
|
||||||
if (osg::getNotifyLevel()>=osg::INFO)
|
if (osg::getNotifyLevel()>=osg::INFO)
|
||||||
{
|
{
|
||||||
stats.reset();
|
stats.reset();
|
||||||
@ -4104,3 +4113,45 @@ void Optimizer::TextureAtlasVisitor::optimize()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// StaticObjectDectionVisitor
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void Optimizer::StaticObjectDetectionVisitor::apply(osg::Node& node)
|
||||||
|
{
|
||||||
|
if (node.getStateSet()) applyStateSet(*node.getStateSet());
|
||||||
|
|
||||||
|
traverse(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Optimizer::StaticObjectDetectionVisitor::apply(osg::Geode& geode)
|
||||||
|
{
|
||||||
|
if (geode.getStateSet()) applyStateSet(*geode.getStateSet());
|
||||||
|
|
||||||
|
for(unsigned int i=0; i<geode.getNumDrawables(); ++i)
|
||||||
|
{
|
||||||
|
applyDrawable(*geode.getDrawable(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Optimizer::StaticObjectDetectionVisitor::applyStateSet(osg::StateSet& stateset)
|
||||||
|
{
|
||||||
|
stateset.setDataVariance(osg::Object::STATIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Optimizer::StaticObjectDetectionVisitor::applyDrawable(osg::Drawable& drawable)
|
||||||
|
{
|
||||||
|
if (drawable.getStateSet()) applyStateSet(*drawable.getStateSet());
|
||||||
|
|
||||||
|
osg::Object::DataVariance dataVariance = osg::Object::STATIC;
|
||||||
|
|
||||||
|
if (drawable.getDrawCallback()) dataVariance = osg::Object::DYNAMIC;
|
||||||
|
if (drawable.getCullCallback()) dataVariance = osg::Object::DYNAMIC;
|
||||||
|
if (drawable.getDrawCallback()) dataVariance = osg::Object::DYNAMIC;
|
||||||
|
|
||||||
|
drawable.setDataVariance(dataVariance);
|
||||||
|
}
|
||||||
|
@ -301,7 +301,7 @@ void RenderBin::sortBackToFront()
|
|||||||
|
|
||||||
void RenderBin::copyLeavesFromStateGraphListToRenderLeafList()
|
void RenderBin::copyLeavesFromStateGraphListToRenderLeafList()
|
||||||
{
|
{
|
||||||
// _renderLeafList.clear();
|
_renderLeafList.clear();
|
||||||
|
|
||||||
int totalsize=0;
|
int totalsize=0;
|
||||||
StateGraphList::iterator itr;
|
StateGraphList::iterator itr;
|
||||||
@ -509,3 +509,52 @@ bool RenderBin::getStats(Statistics& stats) const
|
|||||||
|
|
||||||
return statsCollected;
|
return statsCollected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int RenderBin::computeNumberOfDynamicRenderLeaves() const
|
||||||
|
{
|
||||||
|
unsigned int count = 0;
|
||||||
|
|
||||||
|
// draw first set of draw bins.
|
||||||
|
RenderBinList::const_iterator rbitr;
|
||||||
|
for(rbitr = _bins.begin();
|
||||||
|
rbitr!=_bins.end() && rbitr->first<0;
|
||||||
|
++rbitr)
|
||||||
|
{
|
||||||
|
count += rbitr->second->computeNumberOfDynamicRenderLeaves();
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw fine grained ordering.
|
||||||
|
for(RenderLeafList::const_iterator rlitr= _renderLeafList.begin();
|
||||||
|
rlitr!= _renderLeafList.end();
|
||||||
|
++rlitr)
|
||||||
|
{
|
||||||
|
RenderLeaf* rl = *rlitr;
|
||||||
|
if (rl->_dynamic) ++count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// draw coarse grained ordering.
|
||||||
|
for(StateGraphList::const_iterator oitr=_stateGraphList.begin();
|
||||||
|
oitr!=_stateGraphList.end();
|
||||||
|
++oitr)
|
||||||
|
{
|
||||||
|
|
||||||
|
for(StateGraph::LeafList::const_iterator dw_itr = (*oitr)->_leaves.begin();
|
||||||
|
dw_itr != (*oitr)->_leaves.end();
|
||||||
|
++dw_itr)
|
||||||
|
{
|
||||||
|
RenderLeaf* rl = dw_itr->get();
|
||||||
|
if (rl->_dynamic) ++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw post bins.
|
||||||
|
for(;
|
||||||
|
rbitr!=_bins.end();
|
||||||
|
++rbitr)
|
||||||
|
{
|
||||||
|
count += rbitr->second->computeNumberOfDynamicRenderLeaves();
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
@ -74,5 +74,10 @@ void RenderLeaf::render(osg::RenderInfo& renderInfo,RenderLeaf* previous)
|
|||||||
_drawable->draw(renderInfo);
|
_drawable->draw(renderInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_dynamic)
|
||||||
|
{
|
||||||
|
state.decrementDynamicObjectCount();
|
||||||
|
}
|
||||||
|
|
||||||
// osg::notify(osg::NOTICE)<<"RenderLeaf "<<_drawable->getName()<<" "<<_depth<<std::endl;
|
// osg::notify(osg::NOTICE)<<"RenderLeaf "<<_drawable->getName()<<" "<<_depth<<std::endl;
|
||||||
}
|
}
|
||||||
|
@ -1031,3 +1031,27 @@ void RenderStage::attach(osg::Camera::BufferComponent buffer, osg::Image* image)
|
|||||||
{
|
{
|
||||||
_bufferAttachmentMap[buffer]._image = image;
|
_bufferAttachmentMap[buffer]._image = image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int RenderStage::computeNumberOfDynamicRenderLeaves() const
|
||||||
|
{
|
||||||
|
unsigned int count = 0;
|
||||||
|
|
||||||
|
for(RenderStageList::const_iterator pre_itr = _preRenderList.begin();
|
||||||
|
pre_itr != _preRenderList.end();
|
||||||
|
++pre_itr)
|
||||||
|
{
|
||||||
|
count += pre_itr->second->computeNumberOfDynamicRenderLeaves();
|
||||||
|
}
|
||||||
|
|
||||||
|
count += RenderBin::computeNumberOfDynamicRenderLeaves();
|
||||||
|
|
||||||
|
for(RenderStageList::const_iterator post_itr = _postRenderList.begin();
|
||||||
|
post_itr != _postRenderList.end();
|
||||||
|
++post_itr)
|
||||||
|
{
|
||||||
|
count += post_itr->second->computeNumberOfDynamicRenderLeaves();
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -777,6 +777,11 @@ void SceneView::cullStage(const osg::Matrixd& projection,const osg::Matrixd& mod
|
|||||||
// a clean has been used instead to try to minimize the amount of
|
// a clean has been used instead to try to minimize the amount of
|
||||||
// allocation and deleteing of the StateGraph nodes.
|
// allocation and deleteing of the StateGraph nodes.
|
||||||
rendergraph->prune();
|
rendergraph->prune();
|
||||||
|
|
||||||
|
// set the number of dynamic objects in the scene.
|
||||||
|
getState()->setDynamicObjectCount( getState()->getDynamicObjectCount() + renderStage->computeNumberOfDynamicRenderLeaves());
|
||||||
|
|
||||||
|
// osg::notify(osg::NOTICE)<<"SceneView cull() DynamicObjectCount"<<getState()->getDynamicObjectCount()<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneView::releaseAllGLObjects()
|
void SceneView::releaseAllGLObjects()
|
||||||
@ -1319,6 +1324,9 @@ void SceneView::draw()
|
|||||||
state->setCheckForGLErrors(osg::State::ONCE_PER_ATTRIBUTE);
|
state->setCheckForGLErrors(osg::State::ONCE_PER_ATTRIBUTE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// osg::notify(osg::NOTICE)<<"SceneView draw() DynamicObjectCount"<<getState()->getDynamicObjectCount()<<std::endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Calculate, via glUnProject, the object coordinates of a window point.
|
/** Calculate, via glUnProject, the object coordinates of a window point.
|
||||||
|
@ -522,3 +522,60 @@ bool View::computeIntersections(float x,float y, osg::NodePath& nodePath, osgUti
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// EndOfDynamicDrawBlock
|
||||||
|
//
|
||||||
|
EndOfDynamicDrawBlock::EndOfDynamicDrawBlock():
|
||||||
|
_blockCount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void EndOfDynamicDrawBlock::completed(osg::State* state)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
|
||||||
|
if (_blockCount>0)
|
||||||
|
{
|
||||||
|
--_blockCount;
|
||||||
|
|
||||||
|
if (_blockCount==0)
|
||||||
|
{
|
||||||
|
// osg::notify(osg::NOTICE)<<"Released"<<std::endl;
|
||||||
|
_cond.broadcast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EndOfDynamicDrawBlock::block()
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
|
||||||
|
if (_blockCount)
|
||||||
|
_cond.wait(&_mut);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EndOfDynamicDrawBlock::release()
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
|
||||||
|
if (_blockCount)
|
||||||
|
{
|
||||||
|
_blockCount = 0;
|
||||||
|
_cond.broadcast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EndOfDynamicDrawBlock::set(unsigned int blockCount)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
|
||||||
|
if (blockCount!=_blockCount)
|
||||||
|
{
|
||||||
|
if (blockCount==0) _cond.broadcast();
|
||||||
|
_blockCount = blockCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EndOfDynamicDrawBlock::~EndOfDynamicDrawBlock()
|
||||||
|
{
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
@ -170,6 +170,16 @@ void Viewer::setThreadingModel(ThreadingModel threadingModel)
|
|||||||
if (_threadingModel!=SingleThreaded) startThreading();
|
if (_threadingModel!=SingleThreaded) startThreading();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Viewer::setUseMainThreadForRenderingTraversals(bool flag)
|
||||||
|
{
|
||||||
|
if (_useMainThreadForRenderingTraversal==flag) return;
|
||||||
|
|
||||||
|
if (_threadingModel!=SingleThreaded) stopThreading();
|
||||||
|
|
||||||
|
_useMainThreadForRenderingTraversal = flag;
|
||||||
|
|
||||||
|
if (_threadingModel!=SingleThreaded) startThreading();
|
||||||
|
}
|
||||||
|
|
||||||
void Viewer::setEndBarrierPosition(BarrierPosition bp)
|
void Viewer::setEndBarrierPosition(BarrierPosition bp)
|
||||||
{
|
{
|
||||||
@ -259,12 +269,9 @@ unsigned int Viewer::computeNumberOfThreadsIncludingMainRequired()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool firstContextAsMainThread = _threadingModel == ThreadPerContext;
|
return _useMainThreadForRenderingTraversal ? contexts.size() : contexts.size()+1;
|
||||||
|
|
||||||
return firstContextAsMainThread ? contexts.size() : contexts.size()+1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Viewer::startThreading()
|
void Viewer::startThreading()
|
||||||
{
|
{
|
||||||
unsigned int numThreadsIncludingMainThread = computeNumberOfThreadsIncludingMainRequired();
|
unsigned int numThreadsIncludingMainThread = computeNumberOfThreadsIncludingMainRequired();
|
||||||
@ -310,11 +317,21 @@ void Viewer::startThreading()
|
|||||||
|
|
||||||
_numThreadsOnBarrier = numThreadsIncludingMainThread;
|
_numThreadsOnBarrier = numThreadsIncludingMainThread;
|
||||||
_startRenderingBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION);
|
_startRenderingBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION);
|
||||||
#if 1
|
|
||||||
_endRenderingDispatchBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION);
|
|
||||||
#else
|
if (_threadingModel==ThreadPerContext)
|
||||||
_endRenderingDispatchBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::GL_FINISH);
|
{
|
||||||
#endif
|
#if 1
|
||||||
|
_endRenderingDispatchBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION);
|
||||||
|
#else
|
||||||
|
_endRenderingDispatchBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::GL_FINISH);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_endDynamicDrawBlock = new EndOfDynamicDrawBlock;
|
||||||
|
}
|
||||||
|
|
||||||
osg::ref_ptr<osg::SwapBuffersOperation> swapOp = new osg::SwapBuffersOperation();
|
osg::ref_ptr<osg::SwapBuffersOperation> swapOp = new osg::SwapBuffersOperation();
|
||||||
|
|
||||||
Contexts::iterator citr = contexts.begin();
|
Contexts::iterator citr = contexts.begin();
|
||||||
@ -326,12 +343,15 @@ void Viewer::startThreading()
|
|||||||
++citr;
|
++citr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for(;
|
for(;
|
||||||
citr != contexts.end();
|
citr != contexts.end();
|
||||||
++citr,
|
++citr,
|
||||||
++processNum)
|
++processNum)
|
||||||
{
|
{
|
||||||
osg::GraphicsContext* gc = (*citr);
|
osg::GraphicsContext* gc = (*citr);
|
||||||
|
|
||||||
|
gc->getState()->setDynamicObjectRenderingCompletedCallback(_endDynamicDrawBlock.get());
|
||||||
|
|
||||||
// create the a graphics thread for this context
|
// create the a graphics thread for this context
|
||||||
gc->createGraphicsThread();
|
gc->createGraphicsThread();
|
||||||
@ -346,7 +366,7 @@ void Viewer::startThreading()
|
|||||||
// add the rendering operation itself.
|
// add the rendering operation itself.
|
||||||
gc->getGraphicsThread()->add(new ViewerRunOperations());
|
gc->getGraphicsThread()->add(new ViewerRunOperations());
|
||||||
|
|
||||||
if (_endBarrierPosition==BeforeSwapBuffers)
|
if (_endBarrierPosition==BeforeSwapBuffers && _endRenderingDispatchBarrier.valid())
|
||||||
{
|
{
|
||||||
// add the endRenderingDispatchBarrier
|
// add the endRenderingDispatchBarrier
|
||||||
gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
|
gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
|
||||||
@ -355,7 +375,7 @@ void Viewer::startThreading()
|
|||||||
// add the swap buffers
|
// add the swap buffers
|
||||||
gc->getGraphicsThread()->add(swapOp.get());
|
gc->getGraphicsThread()->add(swapOp.get());
|
||||||
|
|
||||||
if (_endBarrierPosition==AfterSwapBuffers)
|
if (_endBarrierPosition==AfterSwapBuffers && _endRenderingDispatchBarrier.valid())
|
||||||
{
|
{
|
||||||
// add the endRenderingDispatchBarrier
|
// add the endRenderingDispatchBarrier
|
||||||
gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
|
gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
|
||||||
@ -561,6 +581,10 @@ struct ViewerRenderingOperation : public osg::GraphicsOperation
|
|||||||
_sceneView->cull();
|
_sceneView->cull();
|
||||||
osg::Timer_t afterCullTick = osg::Timer::instance()->tick();
|
osg::Timer_t afterCullTick = osg::Timer::instance()->tick();
|
||||||
|
|
||||||
|
if (state->getDynamicObjectCount()==0 && state->getDynamicObjectRenderingCompletedCallback())
|
||||||
|
{
|
||||||
|
state->getDynamicObjectRenderingCompletedCallback()->completed(state);
|
||||||
|
}
|
||||||
|
|
||||||
// do draw traveral
|
// do draw traveral
|
||||||
if (_aquireGPUStats)
|
if (_aquireGPUStats)
|
||||||
@ -1187,11 +1211,24 @@ void Viewer::renderingTraversals()
|
|||||||
|
|
||||||
Contexts contexts;
|
Contexts contexts;
|
||||||
getContexts(contexts);
|
getContexts(contexts);
|
||||||
|
|
||||||
|
Contexts::iterator itr;
|
||||||
|
if (_endDynamicDrawBlock.valid())
|
||||||
|
{
|
||||||
|
unsigned int numToBlock = 0;
|
||||||
|
for(itr = contexts.begin();
|
||||||
|
itr != contexts.end();
|
||||||
|
++itr)
|
||||||
|
{
|
||||||
|
if (((*itr)->getGraphicsThread())) ++numToBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
_endDynamicDrawBlock->set(numToBlock);
|
||||||
|
}
|
||||||
|
|
||||||
// dispatch the the rendering threads
|
// dispatch the the rendering threads
|
||||||
if (_startRenderingBarrier.valid()) _startRenderingBarrier->block();
|
if (_startRenderingBarrier.valid()) _startRenderingBarrier->block();
|
||||||
|
|
||||||
Contexts::iterator itr;
|
|
||||||
for(itr = contexts.begin();
|
for(itr = contexts.begin();
|
||||||
itr != contexts.end();
|
itr != contexts.end();
|
||||||
++itr)
|
++itr)
|
||||||
@ -1207,6 +1244,14 @@ void Viewer::renderingTraversals()
|
|||||||
|
|
||||||
// osg::notify(osg::NOTICE)<<"Joing _endRenderingDispatchBarrier block"<<std::endl;
|
// osg::notify(osg::NOTICE)<<"Joing _endRenderingDispatchBarrier block"<<std::endl;
|
||||||
|
|
||||||
|
// wait till the dynamic draw is complete.
|
||||||
|
if (_endDynamicDrawBlock.valid())
|
||||||
|
{
|
||||||
|
// osg::Timer_t startTick = osg::Timer::instance()->tick();
|
||||||
|
_endDynamicDrawBlock->block();
|
||||||
|
// osg::notify(osg::NOTICE)<<"Time waiting "<<osg::Timer::instance()->delta_m(startTick, osg::Timer::instance()->tick())<<std::endl;;
|
||||||
|
}
|
||||||
|
|
||||||
// wait till the rendering dispatch is done.
|
// wait till the rendering dispatch is done.
|
||||||
if (_endRenderingDispatchBarrier.valid()) _endRenderingDispatchBarrier->block();
|
if (_endRenderingDispatchBarrier.valid()) _endRenderingDispatchBarrier->block();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user