Search code examples
c++windowsperformanceopenscenegraph

OpenSceneGraph Texture2D image "dirty" vs "setImage" performance


I have a 2D texture placed over rectangular area - it's a dynamic texture image (640x480).

tex = new osg::Texture2D;
tex->setDataVariance( osg::Object::DYNAMIC );
tex->setResizeNonPowerOfTwoHint( false );
tex->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST );
tex->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST );
tex->setImage(myImage);

My image data is updated in other thread often (each N milliseconds):

myImage->setImage(
    width,
    height,
    1,
    3,
    GL_BGR,
    gl_data_size,
    (BYTE *)newImageData,
    osg::Image::AllocationMode::USE_MALLOC_FREE
);

And after that I want to update rendered image, if I use dirty( thought this was a best way for update ) on image set to texture, e.g.

// Update callback
...
myImage->dirty();
...

My performance is about 7-8 times slower than if I use just image replacement with same pointer.

// Update callback
...
tex->setImage(myImage);
...

Reading documentation and gidelines of OSG makes me think the correct way is - 'dirty()'. But it's extremly slow. Do I missunderstand something or there is a mistake in my code?


Solution

  • I'm assuming you are using not the latest (3.0.1) version of OSG, since it lacks the "dirty" method for Image class. In previous versions (2.x):

    inline void Image::dirty()
    {
        ++_modifiedCount;
        if (_bufferObject.valid())
            _bufferObject->dirty();
    }
    

    dirty() in turns resets all compiled lists for _bufferObject. On the other hand setImage begins like this:

    void Texture2D::setImage(Image* image)
    {
        if (_image == image) return;
        ...
    }
    

    so in your case it does nothing, if you are using the same pointer for the image. That's why it's faster, but I don't know how OSG updates the actual texture if nothing changed.