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:
@@ -246,6 +246,8 @@ void Drawable::flushDeletedVertexBufferObjects(unsigned int contextID,double /*c
|
||||
|
||||
Drawable::Drawable()
|
||||
{
|
||||
setDataVariance(osg::Object::STATIC);
|
||||
|
||||
_boundingBoxComputed = false;
|
||||
|
||||
// Note, if your are defining a subclass from drawable which is
|
||||
|
||||
@@ -53,6 +53,8 @@ State::State()
|
||||
_glVertexAttribPointer = 0;
|
||||
_glEnableVertexAttribArray = 0;
|
||||
_glDisableVertexAttribArray = 0;
|
||||
|
||||
_dynamicObjectCount = 0;
|
||||
}
|
||||
|
||||
State::~State()
|
||||
|
||||
@@ -80,7 +80,7 @@ bool osg::isTextureMode(StateAttribute::GLMode mode)
|
||||
|
||||
StateSet::StateSet()
|
||||
{
|
||||
setDataVariance(osg::StateAttribute::STATIC);
|
||||
setDataVariance(osg::Object::STATIC);
|
||||
|
||||
_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)
|
||||
{
|
||||
@@ -108,6 +108,9 @@ void Optimizer::optimize(osg::Node* node)
|
||||
|
||||
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
|
||||
@@ -299,7 +302,13 @@ void Optimizer::optimize(osg::Node* node, unsigned int options)
|
||||
node->accept(sv);
|
||||
sv.divide();
|
||||
}
|
||||
|
||||
|
||||
if (options & STATIC_OBJECT_DETECTION)
|
||||
{
|
||||
StaticObjectDetectionVisitor sodv;
|
||||
node->accept(sodv);
|
||||
}
|
||||
|
||||
if (osg::getNotifyLevel()>=osg::INFO)
|
||||
{
|
||||
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()
|
||||
{
|
||||
// _renderLeafList.clear();
|
||||
_renderLeafList.clear();
|
||||
|
||||
int totalsize=0;
|
||||
StateGraphList::iterator itr;
|
||||
@@ -509,3 +509,52 @@ bool RenderBin::getStats(Statistics& stats) const
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (_dynamic)
|
||||
{
|
||||
state.decrementDynamicObjectCount();
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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
|
||||
// allocation and deleteing of the StateGraph nodes.
|
||||
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()
|
||||
@@ -1319,6 +1324,9 @@ void SceneView::draw()
|
||||
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.
|
||||
|
||||
@@ -522,3 +522,60 @@ bool View::computeIntersections(float x,float y, osg::NodePath& nodePath, osgUti
|
||||
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();
|
||||
}
|
||||
|
||||
void Viewer::setUseMainThreadForRenderingTraversals(bool flag)
|
||||
{
|
||||
if (_useMainThreadForRenderingTraversal==flag) return;
|
||||
|
||||
if (_threadingModel!=SingleThreaded) stopThreading();
|
||||
|
||||
_useMainThreadForRenderingTraversal = flag;
|
||||
|
||||
if (_threadingModel!=SingleThreaded) startThreading();
|
||||
}
|
||||
|
||||
void Viewer::setEndBarrierPosition(BarrierPosition bp)
|
||||
{
|
||||
@@ -259,12 +269,9 @@ unsigned int Viewer::computeNumberOfThreadsIncludingMainRequired()
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool firstContextAsMainThread = _threadingModel == ThreadPerContext;
|
||||
|
||||
return firstContextAsMainThread ? contexts.size() : contexts.size()+1;
|
||||
return _useMainThreadForRenderingTraversal ? contexts.size() : contexts.size()+1;
|
||||
}
|
||||
|
||||
|
||||
void Viewer::startThreading()
|
||||
{
|
||||
unsigned int numThreadsIncludingMainThread = computeNumberOfThreadsIncludingMainRequired();
|
||||
@@ -310,11 +317,21 @@ void Viewer::startThreading()
|
||||
|
||||
_numThreadsOnBarrier = numThreadsIncludingMainThread;
|
||||
_startRenderingBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION);
|
||||
#if 1
|
||||
_endRenderingDispatchBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION);
|
||||
#else
|
||||
_endRenderingDispatchBarrier = new osg::BarrierOperation(_numThreadsOnBarrier, osg::BarrierOperation::GL_FINISH);
|
||||
#endif
|
||||
|
||||
|
||||
if (_threadingModel==ThreadPerContext)
|
||||
{
|
||||
#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();
|
||||
|
||||
Contexts::iterator citr = contexts.begin();
|
||||
@@ -326,12 +343,15 @@ void Viewer::startThreading()
|
||||
++citr;
|
||||
}
|
||||
|
||||
|
||||
for(;
|
||||
citr != contexts.end();
|
||||
++citr,
|
||||
++processNum)
|
||||
{
|
||||
osg::GraphicsContext* gc = (*citr);
|
||||
|
||||
gc->getState()->setDynamicObjectRenderingCompletedCallback(_endDynamicDrawBlock.get());
|
||||
|
||||
// create the a graphics thread for this context
|
||||
gc->createGraphicsThread();
|
||||
@@ -346,7 +366,7 @@ void Viewer::startThreading()
|
||||
// add the rendering operation itself.
|
||||
gc->getGraphicsThread()->add(new ViewerRunOperations());
|
||||
|
||||
if (_endBarrierPosition==BeforeSwapBuffers)
|
||||
if (_endBarrierPosition==BeforeSwapBuffers && _endRenderingDispatchBarrier.valid())
|
||||
{
|
||||
// add the endRenderingDispatchBarrier
|
||||
gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
|
||||
@@ -355,7 +375,7 @@ void Viewer::startThreading()
|
||||
// add the swap buffers
|
||||
gc->getGraphicsThread()->add(swapOp.get());
|
||||
|
||||
if (_endBarrierPosition==AfterSwapBuffers)
|
||||
if (_endBarrierPosition==AfterSwapBuffers && _endRenderingDispatchBarrier.valid())
|
||||
{
|
||||
// add the endRenderingDispatchBarrier
|
||||
gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
|
||||
@@ -561,6 +581,10 @@ struct ViewerRenderingOperation : public osg::GraphicsOperation
|
||||
_sceneView->cull();
|
||||
osg::Timer_t afterCullTick = osg::Timer::instance()->tick();
|
||||
|
||||
if (state->getDynamicObjectCount()==0 && state->getDynamicObjectRenderingCompletedCallback())
|
||||
{
|
||||
state->getDynamicObjectRenderingCompletedCallback()->completed(state);
|
||||
}
|
||||
|
||||
// do draw traveral
|
||||
if (_aquireGPUStats)
|
||||
@@ -1187,11 +1211,24 @@ void Viewer::renderingTraversals()
|
||||
|
||||
Contexts 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
|
||||
if (_startRenderingBarrier.valid()) _startRenderingBarrier->block();
|
||||
|
||||
Contexts::iterator itr;
|
||||
for(itr = contexts.begin();
|
||||
itr != contexts.end();
|
||||
++itr)
|
||||
@@ -1207,6 +1244,14 @@ void Viewer::renderingTraversals()
|
||||
|
||||
// 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.
|
||||
if (_endRenderingDispatchBarrier.valid()) _endRenderingDispatchBarrier->block();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user