Hi, Igor,

I  got interested in this problem and checked your code by converting it to
pure osgViewer. Here are my observations:

I believe you do have circular reference. Your class Scene is a callback.
So RootNode points to callback but Scene callback points to RootNode. Hence
circular ref.
However, this does not explain increased ref count of your geometries. But
I believe this issue can be explained by by lazy clearing of render bins.
RenderBins are not
cleared after Draw but before next frame Draw. So after your Update, your
geometry is Culled/Drawn and lands in RenderLeaves of RenderBin. This
RenderBin is used to draw visible geometries but its not cleared after
Draw. Its cleared later, ie on next Cull/Draw traversal when RenderLeaves
container cleared before it gets filled again. So on next Update you will
notice increased ref count because its also added to RenderLeaves
container. But the next Cull/Draw will clear RenderLeaves and your geometry
will be finally released. Here is your modified test applet code ported to
vanilla osgViewer and modified to use observer_ptr instead of ref_ptr for
RootNode. I have put breakpoint in MyGeometry Destructor to see the call
stack and the call where the geometry is actually released and that way I
found the explanation.

Cheers, hth,
Wojtek Lewandowski

czw., 12 lip 2018 o 21:49 Igor Spiridonov <igw...@rambler.ru> napisaƂ(a):

> Here is simple project which reproduces this issue - RefCountTest (
> https://bitbucket.org/OmegaDoom/osgrefcounttest)
>
> It's a visual studio project with qt and osg. Not sure you are using
> windows but the main code in scene.cpp. ref count checks inside
> "Scene::operator()(osg::Node* node, osg::NodeVisitor* nv)"
>
> I expect both checks to return 1 but first one returns 2 as I explained
> earlier.
>
> I suppose it's the cause of memleak. I use osg 3.2.
>
> ------------------
> Read this topic online here:
> http://forum.openscenegraph.org/viewtopic.php?p=74334#74334
>
>
>
>
>
> _______________________________________________
> osg-users mailing list
> osg-users@lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>
#include <osg/Group>
#include <osg/Geode>
#include <osg/Texture2D>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osg/NodeCallback>
#include <osgGA/StateSetManipulator>

class Scene : public osg::NodeCallback
{
public:
  Scene();
  osg::Node* getRoot();

private:
  void operator()(osg::Node*, osg::NodeVisitor*) override;
  void UpdateScene() const;

  osg::observer_ptr<osg::Group> m_rootNode;
};

Scene::Scene()
  : m_rootNode(new osg::Group)
{
  m_rootNode->addChild(new osg::Geode);
  m_rootNode->addUpdateCallback(this);
}

osg::Node* Scene::getRoot()
{
  return m_rootNode.get();
}

void PrintDtor(int refcount)
{
  printf("Dtor Refcount: %d \n", refcount);
}

class MyGeometry : public osg::Geometry
{
public:
  ~MyGeometry()
  {
    int refcount = referenceCount();
    
    PrintDtor(refcount);
  }
};

void Scene::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
  //check refcount
  if (static_cast<osg::Geode*>(m_rootNode->getChild(0))->getNumDrawables())
  {
    auto drawable = 
static_cast<osg::Geode*>(m_rootNode->getChild(0))->getDrawable(0);
    int refcount = drawable->referenceCount();
    printf("Callback 1 Refcount: %d \n", refcount);
  }

  UpdateScene();

  //check refcount
  if (static_cast<osg::Geode*>(m_rootNode->getChild(0))->getNumDrawables())
  {
    auto drawable = 
static_cast<osg::Geode*>(m_rootNode->getChild(0))->getDrawable(0);
    int refcount = drawable->referenceCount();
    printf("Callback 2 Refcount: %d \n", refcount);
  }


  OpenThreads::Thread::microSleep(100000);
};

void Scene::UpdateScene() const
{
  auto childNode = static_cast<osg::Geode*>(m_rootNode->getChild(0));
  childNode->removeDrawables(0, childNode->getNumDrawables());

  osg::ref_ptr<osg::Geometry> geometry(new MyGeometry);
  childNode->addDrawable(geometry);

  int refcount = geometry->referenceCount();  
  printf("UpdateScene Refcount: %d \n", refcount);

}

int main(int argc, char** argv)
{
    osg::ArgumentParser arguments(&argc, argv);
    osgViewer::Viewer viewer( arguments );    

    // add the state manipulator
    viewer.addEventHandler(new 
osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));

    // add the thread model handler
    viewer.addEventHandler(new osgViewer::ThreadingHandler);

    // add the window size toggle handler
    viewer.addEventHandler(new osgViewer::WindowSizeHandler);

    // add the stats handler
    viewer.addEventHandler(new osgViewer::StatsHandler);

    // add the help handler
    viewer.addEventHandler(new 
osgViewer::HelpHandler(arguments.getApplicationUsage()));

    Scene view;
    viewer.setSceneData(view.getRoot());

    viewer.run();
}
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to