[osg-users] Crash when frequently recreating VBOs

Jannik Heller scrawl at baseoftrash.de
Wed May 6 09:07:16 PDT 2015


Hi,

I get random crashes when recreating VBOs in my app. I managed to isolate the crash into a small reproduction case.

Basically I have a cull thread filling in draw commands with VBOs, and the draw thread executes them. Recreating the VBOs is what makes the crash appear.


Code:

#include <osg/Geode>

#include <osg/Drawable>
#include <osg/Array>

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>

class VertexBuffer
{
    public:
    VertexBuffer()
    {
        create();
    }

    osg::ref_ptr<osg::VertexBufferObject> mVBO;
    osg::ref_ptr<osg::UByteArray> mArray;

    void destroy()
    {
        mVBO = NULL;
        mArray = NULL;
    }

    void create()
    {
        mVBO = new osg::VertexBufferObject;
        mVBO->setDataVariance(osg::Object::DYNAMIC);
        mVBO->setUsage(GL_DYNAMIC_DRAW);
        mArray = new osg::UByteArray(6 + std::rand()/float(RAND_MAX) * 1000);
        mVBO->setArray(0, mArray);
    }
};

class MyDrawable : public osg::Drawable
{
public:
    MyDrawable()
        : mWriteTo(0)
        , mReadFrom(0)
    {
        osg::ref_ptr<FillBatchCallback> callback = new FillBatchCallback;
        callback->setDrawable(this);
        setCullCallback(callback);

        setDataVariance(osg::Object::STATIC);

        setSupportsDisplayList(false);

        for (int i=0; i<1000; ++i)
        {
            mVertexBuffers.push_back(VertexBuffer());
        }
    }

    MyDrawable(const MyDrawable& copy, const osg::CopyOp& copyop)
        : mWriteTo(copy.mWriteTo)
        , mReadFrom(copy.mReadFrom)
    {

    }

    META_Object(example, MyDrawable)

    class FillBatchCallback : public osg::Drawable::CullCallback
    {
    public:

        /** do customized cull code, return true if drawable should be culled.*/
        virtual bool cull(osg::NodeVisitor* nv, osg::Drawable* drawable, osg::RenderInfo* renderInfo) const
        {
            mDrawable->collectBatches();

            return false;
        }

        void setDrawable(MyDrawable* drawable)
        {
            mDrawable = drawable;
        }

    private:

        MyDrawable* mDrawable;
    };

    void collectBatches()
    {
        clear();

        for (std::vector<VertexBuffer>::iterator it = mVertexBuffers.begin(); it != mVertexBuffers.end(); ++it)
        {
            VertexBuffer& vertexbuffer = *it;

            if (std::rand()/float(RAND_MAX) > 0.9)
            {
                vertexbuffer.destroy();
                vertexbuffer.create();
            }

            addBatch(vertexbuffer);
        }
    }

    virtual void drawImplementation(osg::RenderInfo& renderInfo) const
    {
        mReadFrom = (mReadFrom+1)%2;

        osg::State* state = renderInfo.getState();

        const std::vector<VertexBuffer>& vec = mBatchVector[mReadFrom];

        for (std::vector<VertexBuffer>::const_iterator it = vec.begin(); it != vec.end(); ++it)
        {
            const VertexBuffer& b = *it;
            osg::GLBufferObject* obj = state->isVertexBufferObjectSupported() ? b.mVBO->getOrCreateGLBufferObject(state->getContextID()) : 0;
            if (obj)
            {
                state->bindVertexBufferObject(obj);
            }
        }

        state->unbindVertexBufferObject();
    }

private:
    std::vector<VertexBuffer> mVertexBuffers;


    std::vector<VertexBuffer> mBatchVector[2];
    int mWriteTo;
    mutable int mReadFrom;

public:

    void addBatch(const VertexBuffer& batch)
    {
        mBatchVector[mWriteTo].push_back(batch);
    }

    void clear()
    {
        mWriteTo = (mWriteTo+1)%2;
        mBatchVector[mWriteTo].clear();
    }
};

int main( int argc, char **argv )
{
    osg::ref_ptr<osg::Geode> rootnode = new osg::Geode;
    rootnode->addDrawable(new MyDrawable);

    osgViewer::Viewer viewer;

    viewer.addEventHandler(new osgViewer::StatsHandler);
     
    // set the scene to render
    viewer.setSceneData(rootnode);

    return viewer.run();
}




Leaving that example running for one or two minutes, I get the message

Warning: deleting still referenced object 0x7f846c3d7ac0 of type 'PN3osg10ReferencedE'
         the final reference count was 1, memory corruption possible.

and then shortly after it crashes, presumably accessing a deleted GLBufferObject:


Code:


Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff1650700 (LWP 4610)]
0x00007ffff79953a0 in osg::GLBufferObject::compileBuffer() () from /home/scrawl/Downloads/OpenSceneGraph-3.2.0/build/lib/libosg.so.100
(gdb) bt
#0  0x00007ffff79953a0 in osg::GLBufferObject::compileBuffer() () from /home/scrawl/Downloads/OpenSceneGraph-3.2.0/build/lib/libosg.so.100
#1  0x0000000000406649 in MyDrawable::drawImplementation(osg::RenderInfo&) const ()
#2  0x00007ffff561cb27 in osgUtil::RenderLeaf::render(osg::RenderInfo&, osgUtil::RenderLeaf*) () from /home/scrawl/Downloads/OpenSceneGraph-3.2.0/build/lib/libosgUtil.so.100
#3  0x00007ffff56173c0 in osgUtil::RenderBin::drawImplementation(osg::RenderInfo&, osgUtil::RenderLeaf*&) () from /home/scrawl/Downloads/OpenSceneGraph-3.2.0/build/lib/libosgUtil.so.100





This bug seems timing sensitive as I have only reproduced it in a Release build.

I get the crash with both OSG-3.2 and svn/trunk r14862, on Linux 64-bit.

Any ideas?

Thank you!
Jannik[/code]

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=63649#63649








More information about the osg-users mailing list