I am trying to use PBOs to do texture upload/update of an osg::Image in a
thread different from the rendering thread, and render the same. I have created
a plugin that simply updates a simple buffer (filling every channel of every
pixel in the buffer with a value that varies over time from 0 to 1).
In the first iteration, I used an osg::Image. For increasing performance, I
switched to using an osg::ImageStream since it uses PBO.
The relevant parts of my update plugin's code are as below:
Code:
/// \brief A simple test OSG plugin that updates a buffer (by changing pixel
values)
class MYLIB_EXPORT TestBufferWriter : protected OpenThreads::Thread,
#ifdef USE_PBO
public osg::ImageStream
#else
public osg::Image
#endif
{
public:
/// \brief constructor
TestBufferWriter();
...
protected:
/// \brief Buffers into which we write our updates
unsigned char* _updateBuffers[2];
}
void
TestBufferWriter::_initialize()
{
// Allocate two new buffers
unsigned char* newBuffers[2];
newBuffers[0] = new unsigned char[_width*_height*3];
newBuffers[1] = new unsigned char[_width*_height*3];
// Call set image using the second of the 2 new buffers created
if(_firstTimeInit)
{
setImage(_width,
_height,
1,
GL_RGB,
GL_RGB,
GL_UNSIGNED_BYTE,
newBuffers[1],
osg::Image::NO_DELETE);
_firstTimeInit = false;
}
else
{
_data = newBuffers[1];
dirty();
}
// Release any previously allocated buffers
_releaseBuffers();
// Set our member buffer pointers to the newly allocated buffers
_updateBuffers[0] = newBuffers[0];
_updateBuffers[1] = newBuffers[1];
_data = _updateBuffers[1];
dirty();
_currentBufferIndex = 1;
}
void TestBufferWriter::_update()
{
double currentTime = osg::Timer::instance()->time_s();
float oscillator = (sinf(currentTime)*0.5)+0.5;
oscillator += _randomOffset;
int pixVal = oscillator*255.f;
// First set the image buffer to the previously updated buffer
setImage(_width, _height, 1, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE,
_updateBuffers[_currentBufferIndex], osg::Image::NO_DELETE);
// Now swap buffer index so that we can update the other buffer
_currentBufferIndex = _currentBufferIndex==0?1:0;
// Update the other buffer by modifying pixel values
unsigned char* imgData = _updateBuffers[_currentBufferIndex];
memset(imgData, pixVal, _width*_height*3);
}
I find that using PBOs, I did get a marginal speedup of frame rate(~20 FPS
more) and a significant drop in processor usage (~20% less). However, I believe
that the performance improvements possible must be more drastic.
Investigating further, I wrote a simple sample of my own in OpenGL where I
update a texture exactly like I do in the osg plugin described above. While not
using PBOs, I find the performance/framerates nearly equal to what I got with
OpenScenegraph plugin. However, on using PBOs, I get dramatic improvements in
performance, in the order of 10x(!) improvements in render rates. This means
that there is a lot of scope for improving performance in my osg plugin as
well. From the above code, can someone point out any flaws in the way I am
using ImageStream in OpenScenegraph that is preventing me from getting the full
benefits of using PBO?
Currently, during every update, I use osg::ImageStream setImage to map to the
buffer on the host that I create. I am guessing there must be a memcpy being
doing to copy from my image buffer to the PBO that image stream maintains
internally. This seems inefficient to me. In this regard, I would like to know,
if there is a way I can create two PBOs, and write my updates to one directly
while using the other to render the osg::Texture with.
Thank you!
Cheers,
Abhishek
------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=57635#57635
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org