Added support for GrapicsOpeations that are reused each frame, cleaned up

osgcamera example.
This commit is contained in:
Robert Osfield 2005-08-30 22:28:30 +00:00
parent 994192657a
commit c02e91c1b4
5 changed files with 133 additions and 57 deletions

View File

@ -10,6 +10,7 @@
#include <osgUtil/UpdateVisitor>
#include <osgUtil/CullVisitor>
#include <osgUtil/SceneView>
#include <osgUtil/GLObjectsVisitor>
#include <osgDB/ReadFile>
@ -29,6 +30,28 @@
///////////////////////////////////////////////////////////////////////////////
struct CompileOperation : public osg::GraphicsThread::Operation
{
CompileOperation(osg::Node* scene):
osg::GraphicsThread::Operation("Compile",false),
_scene(scene)
{
}
virtual void operator () (osg::GraphicsContext* context)
{
std::cout<<"Compile"<<std::endl;
osgUtil::GLObjectsVisitor compileVisitor;
compileVisitor.setState(context->getState());
// do the compile traversal
_scene->accept(compileVisitor);
}
osg::ref_ptr<osg::Node> _scene;
};
struct FrameOperation : public osg::GraphicsThread::Operation
{
FrameOperation(osg::CameraNode* camera, osg::FrameStamp* frameStamp):
@ -100,6 +123,9 @@ int main( int argc, char **argv )
CameraMap cameraMap;
GraphicsContextSet graphicsContextSet;
bool shareContexts = false;
osg::GraphicsContext* previousContext = 0;
for(unsigned int i=0; i< numberCameras; ++i)
{
osg::ref_ptr<osg::CameraNode> camera = new osg::CameraNode;
@ -113,7 +139,8 @@ int main( int argc, char **argv )
traits->_height = height;
traits->_windowDecoration = true;
traits->_doubleBuffer = true;
traits->_sharedContext = shareContexts ? previousContext : 0;
xpos += width;
osg::ref_ptr<osg::GraphicsContext> gfxc = osg::GraphicsContext::createGraphicsContext(traits.get());
@ -139,6 +166,8 @@ int main( int argc, char **argv )
gfxc->createGraphicsThread();
cameraMap[camera] = new FrameOperation(camera.get(), frameStamp.get());
previousContext = gfxc.get();
}
@ -150,9 +179,12 @@ int main( int argc, char **argv )
graphicsContextSet.insert(const_cast<osg::GraphicsContext*>(citr->first->getGraphicsContext()));
}
osg::ref_ptr<osg::SwapBuffersOperation> swapOp = new osg::SwapBuffersOperation();
osg::ref_ptr<CompileOperation> compileOp = new CompileOperation(loadedModel.get());
osg::ref_ptr<osg::BarrierOperation> frameBeginBarrierOp = new osg::BarrierOperation(graphicsContextSet.size()+1, osg::BarrierOperation::NO_OPERATION);
osg::ref_ptr<osg::BarrierOperation> frameEndBarrierOp = new osg::BarrierOperation(graphicsContextSet.size()+1, osg::BarrierOperation::NO_OPERATION);
osg::ref_ptr<osg::BarrierOperation> preSwapBarrierOp = new osg::BarrierOperation(graphicsContextSet.size(), osg::BarrierOperation::GL_FLUSH);
osg::ref_ptr<osg::SwapBuffersOperation> swapOp = new osg::SwapBuffersOperation();
std::cout<<"nubmer of gfx."<<graphicsContextSet.size()<<std::endl;
@ -162,7 +194,47 @@ int main( int argc, char **argv )
bool done = false;
// main loop (note, window toolkits which take control over the main loop will require a window redraw callback containing the code below.)
// first the compile of the GL Objects, do it syncronously.
GraphicsContextSet::iterator gitr;
for(gitr = graphicsContextSet.begin();
gitr != graphicsContextSet.end();
++gitr)
{
osg::GraphicsContext* context = *gitr;
context->getGraphicsThread()->add(compileOp.get(), true);
}
// second the begin frame barrier to all graphics threads
for(gitr = graphicsContextSet.begin();
gitr != graphicsContextSet.end();
++gitr)
{
osg::GraphicsContext* context = *gitr;
context->getGraphicsThread()->add(frameBeginBarrierOp.get(), false);
}
// third add the frame for each camera.
for(citr = cameraMap.begin();
citr != cameraMap.end();
++citr)
{
osg::CameraNode* camera = const_cast<osg::CameraNode*>(citr->first.get());
camera->getGraphicsContext()->getGraphicsThread()->add( citr->second.get(), false);
}
// fourth add the frame end barrier, the pre swap barrier and finally the swap buffers to each graphics thread
for(gitr = graphicsContextSet.begin();
gitr != graphicsContextSet.end();
++gitr)
{
osg::GraphicsContext* context = *gitr;
context->getGraphicsThread()->add(frameEndBarrierOp.get(), false);
context->getGraphicsThread()->add(preSwapBarrierOp.get(), false);
context->getGraphicsThread()->add(swapOp.get(), false);
}
// main loop - update scene graph, dispatch frame, wait for frame done.
while( !done )
{
@ -178,43 +250,11 @@ int main( int argc, char **argv )
// do the update traversal.
loadedModel->accept(updateVisitor);
// issue the frame for each camera.
for(citr = cameraMap.begin();
citr != cameraMap.end();
++citr)
{
osg::CameraNode* camera = const_cast<osg::CameraNode*>(citr->first.get());
camera->getGraphicsContext()->getGraphicsThread()->add( citr->second.get(), false);
}
GraphicsContextSet::iterator gitr;
for(gitr = graphicsContextSet.begin();
gitr != graphicsContextSet.end();
++gitr)
{
osg::GraphicsContext* context = *gitr;
context->getGraphicsThread()->add(frameEndBarrierOp.get(), false);
context->getGraphicsThread()->add(preSwapBarrierOp.get(), false);
}
osg::notify(osg::INFO)<<"Join frameEndBarrierOp block "<<std::endl;
osg::Timer_t before_tick = osg::Timer::instance()->tick();
// dispatch the frame.
frameBeginBarrierOp->block();
// wait till the frame is done.
frameEndBarrierOp->block();
osg::Timer_t after_tick = osg::Timer::instance()->tick();
osg::notify(osg::INFO)<<"Leave frameEndBarrierOp block "<<osg::Timer::instance()->delta_s(before_tick,after_tick)<<std::endl;
osg::notify(osg::INFO)<<"Join preSwapBarrierOp block "<<std::endl;
before_tick = osg::Timer::instance()->tick();
after_tick = osg::Timer::instance()->tick();
osg::notify(osg::INFO)<<"Leave preSwapBarrierOp block "<<osg::Timer::instance()->delta_s(before_tick,after_tick)<<std::endl;
for(gitr = graphicsContextSet.begin();
gitr != graphicsContextSet.end();
++gitr)
{
osg::GraphicsContext* context = *gitr;
context->getGraphicsThread()->add(swapOp.get(), true);
}
// check if any of the windows are closed
for(gitr = graphicsContextSet.begin();
@ -226,6 +266,5 @@ int main( int argc, char **argv )
}
}
return 0;
}

View File

@ -229,6 +229,8 @@ class DataConverter
void write(const osg::FrameStamp& fs)
{
osg::notify(osg::NOTICE)<<"writeFramestamp = "<<fs.getFrameNumber()<<" "<<fs.getReferenceTime()<<std::endl;
writeUInt(fs.getFrameNumber());
return writeDouble(fs.getReferenceTime());
@ -238,6 +240,8 @@ class DataConverter
{
fs.setFrameNumber(readUInt());
fs.setReferenceTime(readDouble());
osg::notify(osg::NOTICE)<<"readFramestamp = "<<fs.getFrameNumber()<<" "<<fs.getReferenceTime()<<std::endl;
}
void write(const osg::Matrix& matrix)
@ -261,6 +265,9 @@ class DataConverter
writeDouble(matrix(3,1));
writeDouble(matrix(3,2));
writeDouble(matrix(3,3));
osg::notify(osg::NOTICE)<<"writeMatrix = "<<matrix<<std::endl;
}
void read(osg::Matrix& matrix)
@ -284,6 +291,9 @@ class DataConverter
matrix(3,1) = readDouble();
matrix(3,2) = readDouble();
matrix(3,3) = readDouble();
osg::notify(osg::NOTICE)<<"readMatrix = "<<matrix<<std::endl;
}
void write(const osgProducer::EventAdapter& event)

View File

@ -26,7 +26,7 @@ namespace osg {
// forward declare GraphicsContext
class GraphicsContext;
class Block: public osg::Referenced {
class Block: virtual public osg::Referenced {
public:
Block():_released(false) {}
@ -82,17 +82,17 @@ class OSG_EXPORT GraphicsThread : public Referenced, public OpenThreads::Thread
GraphicsThread();
/** Base class for implementing GraphicsThread operations.*/
struct OSG_EXPORT Operation : public Referenced
struct OSG_EXPORT Operation : virtual public Referenced
{
Operation(const std::string& name, bool keep):
_name(name),
_keep(true) {}
_keep(keep) {}
/** Set the human readable name of the operation.*/
void setName(const std::string& name) { _name = name; }
/** Get the human readable name of the operation.*/
const std::string& gtName() const { return _name; }
const std::string& getName() const { return _name; }
/** Set whether the operation should be kept once its been applied.*/
void setKeep(bool keep) { _keep = keep; }

View File

@ -838,6 +838,9 @@ unsigned int Geometry::getGLObjectSizeHint() const
void Geometry::drawImplementation(State& state) const
{
// osg::notify(osg::NOTICE)<<"Geometry::drawImplementation"<<std::endl;
if (_internalOptimizedGeometry.valid())
{
_internalOptimizedGeometry->drawImplementation(state);

View File

@ -83,7 +83,7 @@ void GraphicsThread::add(Operation* operation, bool waitForCompletion)
{
osg::notify(osg::INFO)<<"Doing add"<<std::endl;
BlockOperation* block = 0;
ref_ptr<BlockOperation> block = 0;
{
// aquire the lock on the operations queue to prevent anyone else for modifying it at the same time
@ -95,13 +95,13 @@ void GraphicsThread::add(Operation* operation, bool waitForCompletion)
if (waitForCompletion)
{
block = new BlockOperation;
_operations.push_back(block);
_operations.push_back(block.get());
}
_operationsBlock->set(true);
}
if (block)
if (block.valid())
{
// now we wait till the barrier is joined by the graphics thread.
block->block();
@ -126,16 +126,24 @@ void GraphicsThread::run()
bool firstTime = true;
OperationQueue::iterator itr = _operations.begin();
do
{
// osg::notify(osg::NOTICE)<<"In main loop"<<std::endl;
osg::notify(osg::INFO)<<"In main loop"<<std::endl;
if (_operations.empty())
{
_operationsBlock->block();
itr = _operations.begin();
}
else
{
if (itr == _operations.end()) itr = _operations.begin();
}
// osg::notify(osg::NOTICE)<<"get op"<<std::endl;
osg::notify(osg::INFO)<<"get op"<<std::endl;
ref_ptr<Operation> operation;
@ -144,16 +152,32 @@ void GraphicsThread::run()
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
if (!_operations.empty())
{
// get the front the queue
operation = _operations.front();
// get the next item
operation = *itr;
// remove it from the opeations queue
_operations.erase(_operations.begin());
if (_operations.empty())
if (!operation->getKeep())
{
_operationsBlock->set(false);
osg::notify(osg::INFO)<<"removing "<<operation->getName()<<std::endl;
// remove it from the opeations queue
itr = _operations.erase(itr);
osg::notify(osg::INFO)<<"size "<<_operations.size()<<std::endl;
if (_operations.empty())
{
osg::notify(osg::INFO)<<"setting block "<<_operations.size()<<std::endl;
_operationsBlock->set(false);
}
}
else
{
osg::notify(osg::INFO)<<"increment "<<operation->getName()<<std::endl;
// move on to the next operation in the list.
++itr;
}
}
@ -161,7 +185,7 @@ void GraphicsThread::run()
if (operation.valid())
{
// osg::notify(osg::NOTICE)<<"Doing op"<<std::endl;
osg::notify(osg::INFO)<<"Doing op "<<operation->getName()<<std::endl;
// call the graphics operation.
(*operation)(_graphicsContext);