1

I'm trying to read back data, a simple float array, from a shader storage buffer object after execution of a compute shader. I need this data into my application code running osg library. Following the osgssbo example I setup a shader storage buffer object callback but when I read data in it array elements appear at their initial value unchanged. Ssbo and shader seems linked well and correctly executed. Thanks

Here is my basic code:

#include <osgViewer/Viewer>
#include <osg/BufferIndexBinding>
#include <osgGA/TrackballManipulator>
#include <osg/GLExtensions>
using namespace osg;


class ShaderStorageBufferCBK : public osg::StateAttributeCallback
{
public:
    void operator() (osg::StateAttribute* attr, osg::NodeVisitor* nv)
    {
        //if you need to process the data in your app-code , better leaving it on GPU and processing there, uploading per frame will make it slow

        osg::ShaderStorageBufferBinding* ssbb = static_cast<osg::ShaderStorageBufferBinding*>(attr);
        osg::ShaderStorageBufferObject* ssbo
            = static_cast<osg::ShaderStorageBufferObject*>(ssbb->getBufferObject());

        osg::FloatArray* array = static_cast<osg::FloatArray*>(ssbo->getBufferData(0));

        for (int i = 0; i < array->size(); ++i){
            osg::notify(INFO) << array->at(i) << " ";
        }
        osg::notify(INFO) << std::endl;

    }
};


int mymain(){

    FloatArray * dati = new FloatArray;
    dati->push_back(1.2);
    dati->push_back(1.2);
    dati->push_back(1.2);
    dati->push_back(1.2);

    ShaderStorageBufferObject *ssbo = new osg::ShaderStorageBufferObject;
    dati->setBufferObject(ssbo);

    ShaderStorageBufferBinding * ssbb = new ShaderStorageBufferBinding(0, ssbo, 0, dati->size() * sizeof(GLfloat));
    ssbb->setUpdateCallback(new ShaderStorageBufferCBK);

    Shader * shader = new osg::Shader(osg::Shader::COMPUTE);
    shader->loadShaderSourceFromFile("shaders/lightpixels.cs");
    osg::ref_ptr<osg::Program> computeProg = new osg::Program;
    computeProg->setComputeGroups(1, 1, 1);
    shader->setType(Shader::COMPUTE);
    computeProg->addShader(shader);

    osg::Geometry * geom = createTexturedQuadGeometry(Vec3(-0.5, 0, -0.5), Vec3(1.0, 0, 0.0), Vec3(0, 0, 1.0));
    geom->getOrCreateStateSet()->setAttributeAndModes(computeProg);
    geom->getOrCreateStateSet()->setAttributeAndModes(ssbb, osg::StateAttribute::ON);

    osgViewer::Viewer viewer;
    viewer.setSceneData(geom);
    viewer.setUpViewInWindow(100, 100, 640, 480);
    viewer.realize();
    viewer.setCameraManipulator(new osgGA::TrackballManipulator());

    while (!viewer.done())
    {
        viewer.frame();
    }


    return 0;

}

And the trivial shader code is:

#version 430
layout (local_size_x = 1) in;

layout(std430, binding = 0) buffer destBuffer
{
      float data[];
};

void main() {
    data[0] = 348.0;
    data[2] = 23.0;
}

Output written by callback function is:

1.2 1.2 1.2 1.2 

when i expect to see:

348 1.2 23 1.2
Bikappa
  • 86
  • 6

1 Answers1

0

you can using the osg GLExtensions to read buffer data, you can read the AtomicCounterBufferBinding::readData function for reference.

FelixSFD
  • 6,052
  • 10
  • 43
  • 117