[moved to core for discussion]
Hello all,
Carsten Neumann wrote:
With only one ref count shared across all aspect copies I'm not sure if
this can be fixed in 1.x, I'm currently double checking that it works as
expected in 2.0.
attached is the 2.0 version of Marc's program; it crashes in
Image::changed in the render thread.
The problem comes from SimpleTexturedMaterial. It creates the
TextureObjChunk for the Image with createLocal, but since the image
comes from the app it is known across aspects, but it's parent (the
TexObjChunk) exists only in one aspect.
I think the right fix is to put the objects SimpleTexturedMaterial
creates into (internal) fields and have them synced normally.
In general this means if an object is created with createLocal(), it
must not point to something created with create().
Any ideas if it is possible to relax that or check/enforce it?
Cheers,
Carsten
#ifdef OSG_BUILD_ACTIVE
#include <OSGSimpleSceneManager.h>
#include <OSGSimpleTexturedMaterial.h>
#include <OSGNameAttachment.h>
#include <OSGSimpleGeometry.h>
#include <OSGGLUTWindow.h>
#include <OSGGLUT.h>
#include <OSGMaterialGroup.h>
#else // OSG_BUILD_ACTIVE
#include <OpenSG/OSGSimpleSceneManager.h>
#include <OpenSG/OSGSimpleTexturedMaterial.h>
#include <OpenSG/OSGNameAttachment.h>
#include <OpenSG/OSGSimpleGeometry.h>
#include <OpenSG/OSGGLUTWindow.h>
#include <OpenSG/OSGGLUT.h>
#include <OpenSG/OSGMaterialGroup.h>
#endif // OSG_BUILD_ACTIVE
OSG::SimpleSceneManager *mgr;
OSG::NodeUnrecPtr scene;
OSG::Thread* renderThread;
OSG::Thread* creationThread;
OSG::Barrier* syncBarrier;
volatile bool syncNeeded;
OSG::UInt32 fcStoreInitialSize = 0;
int setupGLUT( int *argc, char *argv[] );
void printOSGInstances(const std::string &prefix)
{
OSG::UInt32 liveFC = 0;
OSG::UInt32 liveFCInAspect = 0;
OSG::UInt32 fcStoreSize = OSG::FieldContainerFactory::the()->getNumContainers();
std::cout << prefix << "FieldContainerFactory::size(): "
<< (fcStoreSize - fcStoreInitialSize) << std::endl;
for(OSG::UInt32 i = fcStoreInitialSize; i < fcStoreSize; ++i)
{
OSG::FieldContainer *fc = OSG::FieldContainerFactory::the()->getContainer(i);
OSG::AspectStore *as = OSG::FieldContainerFactory::the()->getContainerHandler(i);
if(as != NULL)
{
++liveFC;
std::cout << prefix << "Detected live FC " << i;
OSG::UInt32 numAspects = as->getNumAspects();
for(OSG::UInt32 j = 0; j < numAspects; ++j)
{
std::cout << " (" << (j+1) << "/" << numAspects << ") rc ";
if(as->getPtr(j) != NULL)
std::cout << as->getPtr(j)->getRefCount();
else
std::cout << "N/A";
}
std::cout << "\n";
}
if(fc != NULL)
{
++liveFCInAspect;
std::cout << prefix
<< "Detected live FC " << fc->getTypeName()
<< " id: " << fc->getId()
<< " " << fc
<< " rc: " << fc->getRefCount() << std::endl;
}
}
std::cout << prefix
<< "liveFC " << liveFC
<< " liveFCInAspect " << liveFCInAspect
<< " store size " << (fcStoreSize - fcStoreInitialSize) << std::endl;
}
OSG::NodeTransitPtr createScenegraph(void)
{
OSG::NodeUnrecPtr n = OSG::Node::create();
n->setCore(OSG::Group::create());
return OSG::NodeTransitPtr(n);
}
// executed by each geometry creation thread
void create(void *args)
{
syncBarrier->enter(2);
renderThread->getChangeList()->applyNoClear();
syncBarrier->enter(2);
// (1)
{
OSG::NodeRecPtr node = OSG::Node::create();
syncNeeded = true;
std::cout << "(1a) pre-sync ==============================================\n";
printOSGInstances("createThread: ");
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
std::cout << "(1a) post-sync ==============================================\n";
printOSGInstances("createThread: ");
OSG::GeometryRecPtr geo = OSG::Geometry::create();
node->setCore(geo);
OSG::commitChanges();
syncNeeded = true;
std::cout << "(1b) pre-sync ==============================================\n";
printOSGInstances("createThread: ");
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
std::cout << "(1b) post-sync ===============================================\n";
printOSGInstances("createThread: ");
}
OSG::commitChanges();
syncNeeded = true;
std::cout << "(1c) pre-sync ==============================================\n";
printOSGInstances("createThread: ");
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
std::cout << "(1c) post-sync ==============================================\n";
printOSGInstances("createThread: ");
// (2)
{
OSG::NodeRecPtr node = OSG::Node::create();
syncNeeded = true;
std::cout << "(2a) pre-sync ==============================================\n";
printOSGInstances("createThread: ");
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
std::cout << "(2a) post-sync ==============================================\n";
printOSGInstances("createThread: ");
OSG::GeometryRecPtr geo = OSG::Geometry ::create();
OSG::GeoPnt3fPropertyRecPtr pos = OSG::GeoPnt3fProperty::create();
geo->setPositions(pos);
node->setCore(geo);
OSG::commitChanges();
syncNeeded = true;
std::cout << "(2b) pre-sync ==============================================\n";
printOSGInstances("createThread: ");
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
std::cout << "(2b) post-sync ==============================================\n";
printOSGInstances("createThread: ");
}
OSG::commitChanges();
syncNeeded = true;
std::cout << "(2c) pre-sync ==============================================\n";
printOSGInstances("createThread: ");
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
std::cout << "(2c) post-sync ==============================================\n";
printOSGInstances("createThread: "); // crash here!
std::cout << std::endl;
// (3)
for (unsigned int i=0; i<20; i++)
{
#if 1
OSG::NodeRecPtr node = OSG::Node::create();
syncNeeded = true;
if((i > 0) && (i % 10 == 0))
{
std::cout << "(3a) pre-sync (" << i << ") ==============================================\n";
printOSGInstances("createThread: ");
}
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
if((i > 0) && (i % 100 == 0))
{
std::cout << "(3a) post-sync (" << i << ") ==============================================\n";
printOSGInstances("createThread: ");
}
OSG::GeometryRecPtr boxGeo = OSG::makeBoxGeo(20, 20, 20, 20, 20, 20);
node->setCore(boxGeo);
OSG::commitChanges();
syncNeeded = true;
if((i > 0) && (i % 10 == 0))
{
std::cout << "(3b) pre-sync (" << i << ") ==============================================\n";
printOSGInstances("createThread: ");
}
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
if((i > 0) && (i % 10 == 0))
{
std::cout << "(3b) post-sync (" << i << ") ==============================================\n";
printOSGInstances("createThread: ");
}
#endif
OSG::commitChanges();
#if 0
{
OSG::NodeRecPtr node = OSG::Node::create();
std::cout << "(4a) pre-sync ==============================================\n";
printOSGInstances("createThread: ");
syncNeeded = true;
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
std::cout << "(4a) post-sync ==============================================\n";
printOSGInstances("createThread: ");
OSG::SimpleTexturedMaterialRecPtr mat = OSG::SimpleTexturedMaterial::create();
OSG::ImageRefPtr img = OSG::Image::create();
mat->setImage(img);
OSG::MaterialGroupRecPtr mat_grp = OSG::MaterialGroup::create();
mat_grp->setMaterial(mat);
node->setCore(mat_grp);
OSG::commitChanges();
std::cout << "(4b) pre-sync ==============================================\n";
printOSGInstances("createThread: ");
syncNeeded = true;
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
std::cout << "(4b) post-sync ==============================================\n";
printOSGInstances("createThread: ");
}
OSG::commitChanges();
syncNeeded = true;
std::cout << "(4c) pre-sync ==============================================\n";
printOSGInstances("createThread: ");
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
std::cout << "(4c) post-sync ==============================================\n";
printOSGInstances("createThread: ");
syncNeeded = true;
std::cout << "(4d) pre-sync ==============================================\n";
printOSGInstances("createThread: ");
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
std::cout << "(4d) post-sync ==============================================\n";
printOSGInstances("createThread: ");
#endif
}
OSG::commitChanges();
syncNeeded = true;
std::cout << "(3c) pre-sync ==============================================\n";
printOSGInstances("createThread: ");
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
std::cout << "(3c) post-sync ==============================================\n";
printOSGInstances("createThread: ");
#if 1
{
OSG::NodeRecPtr node = OSG::Node::create();
std::cout << "(4a) pre-sync ==============================================\n";
printOSGInstances("createThread: ");
syncNeeded = true;
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
std::cout << "(4a) post-sync ==============================================\n";
printOSGInstances("createThread: ");
OSG::SimpleTexturedMaterialRecPtr mat = OSG::SimpleTexturedMaterial::create();
OSG::ImageRecPtr img = OSG::Image::create();
mat->setImage(img);
std::cout << "(4 post STM create) ==============================================\n";
printOSGInstances("createThread: ");
OSG::MaterialGroupRecPtr mat_grp = OSG::MaterialGroup::create();
mat_grp->setMaterial(mat);
std::cout << "(4 post MG create) ==============================================\n";
printOSGInstances("createThread: ");
node->setCore(mat_grp);
OSG::commitChanges();
std::cout << "(4b) pre-sync ==============================================\n";
printOSGInstances("createThread: ");
syncNeeded = true;
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
std::cout << "(4b) post-sync ==============================================\n";
printOSGInstances("createThread: ");
}
OSG::commitChanges();
syncNeeded = true;
std::cout << "(4c) pre-sync ==============================================\n";
printOSGInstances("createThread: ");
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
std::cout << "(4c) post-sync ==============================================\n";
printOSGInstances("createThread: ");
syncNeeded = true;
std::cout << "(4d) pre-sync ==============================================\n";
printOSGInstances("createThread: ");
syncBarrier->enter(2);
syncNeeded = false;
syncBarrier->enter(2);
std::cout << "(4d) post-sync ==============================================\n";
printOSGInstances("createThread: ");
#endif
}
int main(int argc, char *argv[])
{
OSG::osgInit(argc, argv);
int winid = setupGLUT(&argc, argv);
OSG::GLUTWindowRecPtr gwin = OSG::GLUTWindow::create();
gwin->setGlutId(winid);
gwin->init();
scene = createScenegraph();
mgr = new OSG::SimpleSceneManager;
mgr->setWindow(gwin );
mgr->setRoot (scene);
mgr->setStatistics(true);
mgr->showAll();
syncBarrier = OSG::Barrier::get("syncBarrier1");
renderThread = dynamic_cast<OSG::Thread *>(OSG::ThreadManager::getAppThread());
syncNeeded = false;
// start the threads
creationThread = dynamic_cast<OSG::Thread *>(OSG::ThreadManager::the()->getThread("creationThread"));
creationThread->runFunction(create, 1, NULL);
OSG::commitChanges();
// wait for the creation threads to sync over changes
syncBarrier->enter(2);
syncBarrier->enter(2);
// clear changes - they are synced to aspect 1 now
OSG::Thread::getCurrentChangeList()->clear();
fcStoreInitialSize = OSG::FieldContainerFactory::the()->getNumContainers();
mgr->getCamera()->setNear( 0.5 );
mgr->getCamera()->setFar( 15000 );
OSG::commitChanges();
glutMainLoop();
return 0;
}
void display(void)
{
// check thread for available changes
if(syncNeeded == true)
{
syncBarrier->enter(2);
printOSGInstances("renderThread: pre sync: ");
creationThread->getChangeList()->applyAndClear();
printOSGInstances("renderThread: post sync: ");
syncBarrier->enter(2);
}
mgr->redraw();
OSG::commitChanges();
renderThread->getChangeList()->clear();
}
void reshape(int w, int h)
{
mgr->resize(w, h);
glutPostRedisplay();
}
void mouse(int button, int state, int x, int y)
{
if (state)
mgr->mouseButtonRelease(button, x, y);
else
mgr->mouseButtonPress(button, x, y);
glutPostRedisplay();
}
void motion(int x, int y)
{
mgr->mouseMove(x, y);
glutPostRedisplay();
}
int setupGLUT(int *argc, char *argv[])
{
glutInit(argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
int winid = glutCreateWindow("OpenSG Multithreading Test");
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutReshapeFunc(reshape);
glutIdleFunc(display);
return winid;
}
------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables unlimited
royalty-free distribution of the report engine for externally facing
server and web deployment.
http://p.sf.net/sfu/businessobjects
_______________________________________________
Opensg-core mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensg-core