OpenSceneGraph Forum Forum Index OpenSceneGraph Forum
Official forum which mirrors the existent OSG mailing lists. Messages posted here are forwarded to the mailing list and vice versa.
 
   FAQFAQ    SearchSearch    MemberlistMemberlist    RulesRules    UsergroupsUsergroups    RegisterRegister 
 Mail2Forum SettingsMail2Forum Settings  ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
   AlbumAlbum  OpenSceneGraph IRC ChatOpenSceneGraph IRC Chat   SmartFeedSmartFeed 

Removing objects with shared GL state from scene graph


 
Post new topic   Reply to topic    OpenSceneGraph Forum Forum Index -> General
View previous topic :: View next topic  
Author Message
AnyOldName3 (Chris Djali)
User


Joined: 08 Sep 2017
Posts: 24

PostPosted: Wed Mar 20, 2019 5:05 pm    Post subject:
Removing objects with shared GL state from scene graph
Reply with quote

Hi,

I know that when an OpenGL context is destroyed, the associated viewer can only call releaseGLObjects(osg::State *) for nodes still attached to the scene graph, so if you're removing things before that, you're manually supposed to call releaseGLObjects on the subgraph.

However, as I see it, there's a potential problem here. If the subgraph contains nodes that share GL objects with things still attached to the main scenegraph, you'll end up releasing those, too. This can mostly be worked around by not sharing GL objects between nodes with different lifetimes, but sometimes that's not possible.

For example, osgText::Text seems to have a global osg::Program used for all instances (or, at least, all instances with the same settings). If I always call releaseGLObjects when removing subgraphs containing an osgText::Text, it's going to kill the per-context programs and they'll need rebuilding for any other text nodes, which isn't desirable. If I never call releaseGLObjects, then that's even worse (for obvious reasons). It seems like the only good ways of handling this would be to either keep track of when the last text node was removed so the objects could be released when their last user was removed, or move 'removed' objects to another part of the scene graph (e.g. as a disabled osg::Switch child) so they're actually kept around without being drawn, but still get their GL objects released when the context is destroyed. There's also the hacky option of attaching another text node somewhere else in the scenegraph so it always gets released, which works in the specific case of osgText::Text, but won't work in the general case, and doesn't seem desirable.

Is there a better way of handling this than I've suggested here? If there's something intended for this built into OSG that I just don't know about, that would be great, but I'm not going to shy away from writing something custom if that's what's necessary.

Cheers,
Chris
Back to top
View user's profile Send private message
mp3butcher (Julien Valentin)
Appreciator


Joined: 17 Feb 2010
Posts: 519
Location: France

PostPosted: Thu Mar 28, 2019 12:44 pm    Post subject:
Re: Removing objects with shared GL state from scene graph
Reply with quote

Hi Chris,
I haven't dive into the problem, but would making the osgText::Text::program static (and share it with all instances) could be a proper way to handle this issue?
Cheers

AnyOldName3 wrote:
Hi,

I know that when an OpenGL context is destroyed, the associated viewer can only call releaseGLObjects(osg::State *) for nodes still attached to the scene graph, so if you're removing things before that, you're manually supposed to call releaseGLObjects on the subgraph.

However, as I see it, there's a potential problem here. If the subgraph contains nodes that share GL objects with things still attached to the main scenegraph, you'll end up releasing those, too. This can mostly be worked around by not sharing GL objects between nodes with different lifetimes, but sometimes that's not possible.

For example, osgText::Text seems to have a global osg::Program used for all instances (or, at least, all instances with the same settings). If I always call releaseGLObjects when removing subgraphs containing an osgText::Text, it's going to kill the per-context programs and they'll need rebuilding for any other text nodes, which isn't desirable. If I never call releaseGLObjects, then that's even worse (for obvious reasons). It seems like the only good ways of handling this would be to either keep track of when the last text node was removed so the objects could be released when their last user was removed, or move 'removed' objects to another part of the scene graph (e.g. as a disabled osg::Switch child) so they're actually kept around without being drawn, but still get their GL objects released when the context is destroyed. There's also the hacky option of attaching another text node somewhere else in the scenegraph so it always gets released, which works in the specific case of osgText::Text, but won't work in the general case, and doesn't seem desirable.

Is there a better way of handling this than I've suggested here? If there's something intended for this built into OSG that I just don't know about, that would be great, but I'm not going to shy away from writing something custom if that's what's necessary.

Cheers,
Chris

_________________
Twirling twirling twirling toward freedom
Back to top
View user's profile Send private message Visit poster's website
AnyOldName3 (Chris Djali)
User


Joined: 08 Sep 2017
Posts: 24

PostPosted: Thu Mar 28, 2019 11:14 pm    Post subject:
Reply with quote

The problem is specifically because it's static. Unless I'm manually keeping track of when the last text object is removed from the scene, I can't release the program without it potentially still being in use. If I never release it, references to it can persist beyond the lifetime of the context it was created for.


Cheers,
Chris
Back to top
View user's profile Send private message
mp3butcher (Julien Valentin)
Appreciator


Joined: 17 Feb 2010
Posts: 519
Location: France

PostPosted: Fri Mar 29, 2019 2:36 am    Post subject:
Reply with quote

I don't understand:
I can't find any static osg::ref_ptr<osg::Program> in osgText/Text...
please give a simple code illustrating your problem

AnyOldName3 wrote:
The problem is specifically because it's static. Unless I'm manually keeping track of when the last text object is removed from the scene, I can't release the program without it potentially still being in use. If I never release it, references to it can persist beyond the lifetime of the context it was created for.


Cheers,
Chris

_________________
Twirling twirling twirling toward freedom
Back to top
View user's profile Send private message Visit poster's website
robertosfield
OSG Project Lead


Joined: 18 Mar 2009
Posts: 12264

PostPosted: Fri Mar 29, 2019 7:41 am    Post subject:
Removing objects with shared GL state from scene graph
Reply with quote

Hi Chris,

Which version of the OSG are you working with?

Robert.


------------------
Post generated by Mail2Forum
Back to top
View user's profile Send private message
AnyOldName3 (Chris Djali)
User


Joined: 08 Sep 2017
Posts: 24

PostPosted: Fri Mar 29, 2019 7:00 pm    Post subject:
Reply with quote

All out of the 3.6 branch, 3.4.1 and OpenMW's 3.4.1 fork (which doesn't make any changes to osgText, and we're trying to abandon, but it's much faster than the official 3.4.1 release). If everything's working as we think it does, OpenMW should work with any OSG release after 3.4.

The issue of the text program not being released when the context is torn down happens with all the versions listed above. Also, an answer to the question in the general case would probably be helpful for all of the versions.
Back to top
View user's profile Send private message
AnyOldName3 (Chris Djali)
User


Joined: 08 Sep 2017
Posts: 24

PostPosted: Fri Apr 12, 2019 3:53 pm    Post subject:
Reply with quote

Hi,

It's been a couple of weeks since the last reply to this. I'm guessing this has fallen off the radar, but I still need to fix the issue, so would appreciate if another look could be taken at this.

Thank you!

Cheers,
Chris
Back to top
View user's profile Send private message
robertosfield
OSG Project Lead


Joined: 18 Mar 2009
Posts: 12264

PostPosted: Sun Apr 14, 2019 6:42 am    Post subject:
Removing objects with shared GL state from scene graph
Reply with quote

Hi Chris,

On Fri, 12 Apr 2019 at 21:07, Chris Djali <> wrote:
Quote:
It's been a couple of weeks since the last reply to this. I'm guessing this has fallen off the radar, but I still need to fix the issue, so would appreciate if another look could be taken at this.

There is really enough to go on to be able to diagnose what is going
on, there is a limit to how much we can advise on usage combinations
that we haven't seen locally.

Could you create a small OSG example that illustrates the problem
across the different versions of the OSG.

Robert.


------------------
Post generated by Mail2Forum
Back to top
View user's profile Send private message
AnyOldName3 (Chris Djali)
User


Joined: 08 Sep 2017
Posts: 24

PostPosted: Tue Apr 16, 2019 3:58 pm    Post subject:
Reply with quote

Hi,

The following basically simulates the use case that's causing problems.

Code:
#include <random>

#include <osg/AutoTransform>
#include <osg/Group>
#include <osg/PositionAttitudeTransform>
#include <osg/ShapeDrawable>

#include <osgText/Text>

#include <osgViewer/Viewer>

/** A representation of something that gets edited.
 *  Pretend it's actually more complicated than this so that reference counting the number of attached text nodes is a nuisance. */
class World
{
public:
    World() : mScene(new osg::Group)
    {
        // add things so the viewer doesn't automatically zoom too far in to see the 'objects'
       
        auto worldCorners = { osg::Vec3(-11, -11, -11), osg::Vec3(-11, -11, 11),
                              osg::Vec3(-11, 11, -11), osg::Vec3(-11, 11, 11),
                              osg::Vec3(11, -11, -11), osg::Vec3(11, -11, 11),
                              osg::Vec3(11, 11, -11), osg::Vec3(11, 11, 11) };

        for (auto corner : worldCorners)
        {
            osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform();
            pat->setPosition(corner);
            pat->addChild(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0, 0, 0), 0.1)));
            mScene->addChild(pat);
        }
    }

    osg::ref_ptr<osg::Group> getScene() { return mScene; }

    /** Adds an object with a label to the scene based on something the user has done. */
    void addObject(std::string name)
    {
        osg::ref_ptr<osg::PositionAttitudeTransform> object = new osg::PositionAttitudeTransform();
        object->setName(name);

        static std::random_device r;
        static std::default_random_engine randEngine(r());
        static std::uniform_real_distribution<> dist(-10, 10);

        object->setPosition(osg::Vec3(dist(randEngine), dist(randEngine), dist(randEngine)));

        osg::ref_ptr<osgText::Text> objectLabel = new osgText::Text();
        osg::ref_ptr<osg::AutoTransform> autoTransform = new osg::AutoTransform();
        autoTransform->addChild(objectLabel);
        autoTransform->setAutoRotateMode(osg::AutoTransform::ROTATE_TO_SCREEN);
        object->addChild(autoTransform);
        autoTransform->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
        objectLabel->setText(name);
        objectLabel->setCharacterSize(1);

        osg::ref_ptr<osg::Shape> shape = new osg::Sphere(osg::Vec3(0, 0, 0), 1);
        object->addChild(new osg::ShapeDrawable(shape));

        mScene->addChild(object);
    }

    /** Removes an object from the scene based on something the user has done. */
    void removeObject(std::string name)
    {
        osg::ref_ptr<osg::Node> child;
        for (unsigned int i = 0; i < mScene->getNumChildren(); ++i)
        {
            if (mScene->getChild(i)->getName() == name)
            {
                child = mScene->getChild(i);
                mScene->removeChild(i);
                break;
            }
        }

        // If we call child->releaseGLObjects() here, the text program will be released, too, even though it could still be being used by other labels.
        // If we don't, we may be detaching the last text node from the scene graph, and so the text program may never get released.
    }

private:
    osg::ref_ptr<osg::Group> mScene;
};


World world;
bool useNewViewer = true;

class EventHandler : public osgGA::GUIEventHandler
{
public:
    bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
    {
        if (ea.getEventType() != osgGA::GUIEventAdapter::KEYDOWN)
            return false;

        // The user may wish to close the 3D view to work on something else and then reopen it later.
        // That would be a pain to implement directly, so instead, we simulate it by reopening the 3D view when it's closed if Return was pressed while it was open.
        if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Return)
        {
            useNewViewer = true;
            return true;
        }
        // Press a letter key without shift to add an object.
        else if (ea.getKey() >= 'a' && ea.getKey() <= 'z')
        {
            std::string name(1, ea.getKey());
            world.addObject(name);
            return true;
        }
        // Press a letter key with shift to remove an object.
        else if (ea.getKey() >= 'A' && ea.getKey() <= 'Z')
        {
            std::string name(1, ea.getKey() - ('Z' - 'z'));
            world.removeObject(name);
            return true;
        }

        return false;
    }
};

int main()
{
    osg::ref_ptr<osgViewer::Viewer> currentViewer;

    int returnCode = 0;

    while (useNewViewer)
    {
        currentViewer = new osgViewer::Viewer;
        currentViewer->setSceneData(world.getScene());
        currentViewer->addEventHandler(new EventHandler);

        useNewViewer = false;
       
        returnCode = currentViewer->run();
    }

    return returnCode;
}


Imagine this is part of a world editor for a game or CAD software or one of any number of types of software packages where you edit something and might want a 3D view of it, but wouldn't necessarily always want that 3D view taking up space in the window, so you'd possibly close it and then reopen it later. So I didn't have to make a load of extra stuff, this is simulated by opening a new viewer after the previous one closed if enter was pressed.

Pressing a letter key will add an object, and pressing the same letter with the shift key will remove it. Pretend that there are actually loads of different object types and not all of them have text labels so that keeping track of when the last text label is removed via reference counting or similar becomes a pain.

If you add at least one object, then remove all of them, then open a new view, you'll see OpenGL errors and text won't render correctly. This is because there were no osgText::Text nodes attached to the scene graph when the view was reset, so the program never got released, and the new text nodes try and reuse it with the new context, where it's not valid.

The obvious solution is to releaseGLObjects in the removeObject method, but if there are other objects still using text nodes, that's problematic as they'll still be using the program, and it would need recreating immediately.

Alternatively, removed objects could be kept around forever, attached to a hidden part of the scene graph so that anything that was ever used gets released when the context gets torn down. That means a bunch of junk needs keeping around forever, though.

Another option would just be to always have a hidden text node attached to the scene graph even when there are no objects. This solves the problem without much overhead but doesn't really seem like a tidy solution.

Thank you!

Cheers,
Chris
Back to top
View user's profile Send private message
AnyOldName3 (Chris Djali)
User


Joined: 08 Sep 2017
Posts: 24

PostPosted: Wed May 15, 2019 10:51 pm    Post subject:
Reply with quote

Hi,

It looks like this has fallen off the radar again as it's been a month. I'd still rather fix this in a robust way rather than making a guess as to the most sensible approach and creating maintenance problems down the line.

Thank you!

Cheers,
Chris
Back to top
View user's profile Send private message
robertosfield
OSG Project Lead


Joined: 18 Mar 2009
Posts: 12264

PostPosted: Thu May 16, 2019 8:01 am    Post subject:
Removing objects with shared GL state from scene graph
Reply with quote

On Thu, 16 May 2019 at 00:07, Chris Djali <> wrote:
Quote:
It looks like this has fallen off the radar again as it's been a month. I'd still rather fix this in a robust way rather than making a guess as to the most sensible approach and creating maintenance problems down the line.

Sorry, I've been submerged in VSG work.

Just now I had a quick scan of your test program but haven't compiled
and run it. My first though is the global World object holds a
ref_ptr<> to the scene graph and there is no mechanism for deleting
this global prior to the viewer cleans up so in essence it's prevent
that scene graph from being deleted and cleaned up. After the exit of
the main frame loop you could explicitly delete this object. Another
approach would be to make this World object a custom Group node in the
scene graph that adds the high level behaviors you want and with it
ensure that you can override any releaseGLObjects() etc on any locally
cached objects that would otherwise be hidden from the OSG's attempts
at cleaning things up.

Robert.


------------------
Post generated by Mail2Forum
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    OpenSceneGraph Forum Forum Index -> General All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum

Similar Topics
Topic Author Forum Replies Posted
No new posts Different views hide/show different n... icf80 General 13 Wed Apr 17, 2019 9:56 am View latest post
No new posts VertexAttribDivisor -- should it be p... gwaldron General 1 Tue Mar 19, 2019 4:51 pm View latest post
No new posts Deep cloning an active root scene node Robert Lockyer General 7 Thu Feb 28, 2019 5:52 pm View latest post
No new posts [propal] compare VertexArrayState wit... mp3butcher General 0 Mon Dec 31, 2018 3:32 pm View latest post
No new posts possible (probable) state leakage in ... Trajce Nikolov NICK General 1 Mon Nov 19, 2018 1:16 pm View latest post


Board Security Anti Bot Question MOD - phpBB MOD against Spam Bots
Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP