Проблема с получением данных из вычислительного шейдера OpenGL (glMapBufferRange всегда возвращает NULL)



  • Привет.
    Пишу тестовую программу.[0_1521619665511_ComputeShOpenGL.rar](Uploading 100%)
    Никак не могу вытянуть данные из буфера, значения которого заполняются в шейдере.
    Функция glMapBufferRange всегда возвращает NULL.
    Может кто помочь с этой проблемой?
    Код программы и шейдера прилагаю.

    // h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QOpenGLWidget> // подключаем класс QGLWidget
    #include <QOpenGLFunctions>
    #include <QOpenGLShaderProgram>
    #include <QOpenGLBuffer>
    #include <QOpenGLVertexArrayObject>
    
    namespace Ui {
    class MainWindow;
    }
    
    class Scene3D : public QOpenGLWidget, protected QOpenGLFunctions // класс Scene3D наследует встроенный класс QGLWidget
    {
        Q_OBJECT
    public:
       Scene3D(QWidget* pwgt = 0); // конструктор класса (= 0 -- главное окно)
       ~Scene3D();
       void updateData();
    
    protected:
       void initializeGL();                     // метод для проведения инициализаций, связанных с OpenGL
       void resizeGL(int nWidth, int nHeight){}  // метод вызывается при изменении размеров окна виджета
       void paintGL();                          // метод, чтобы заново перерисовать содержимое виджета
    
    private:
          GLfloat *array;
          GLfloat *outArray;
          quint32 arrayCount;
    
          GLuint inBuf;
          GLuint outBuf;
          GLuint bufSize;
    
          bool fShaderAvailable;
          bool fVertexBufferAvailable;
          GLint  Unif_scale;
    
          QOpenGLShader *compSelectBufShader;
          QOpenGLShaderProgram *compSelectBufProgram;
          int fMaxComputeGroupSizeX;
          int fMaxComputeGroupSizeY;
          int fMaxComputeGroupSizeZ;
          int fMaxComputeItemsPerGroup;
    };
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    private slots:
        void on_pushButton_clicked();
    
    private:
        Ui::MainWindow *ui;
    
        Scene3D scene;
    };
    
    #endif // MAINWINDOW_H
    

    // cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QOpenGLExtraFunctions>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        ui->vl->addWidget(&scene);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    Scene3D::Scene3D(QWidget *pwgt)
    {
    
    }
    
    Scene3D::~Scene3D()
    {
    }
    
    void Scene3D::updateData()
    {
        makeCurrent();
    
        QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions();
    
        glBindBuffer( GL_SHADER_STORAGE_BUFFER, outBuf );
        GLfloat *ptr = (GLfloat *) f->glMapBufferRange( GL_SHADER_STORAGE_BUFFER, 0, bufSize, GL_READ_ONLY );
        if (ptr)
            memcpy(outArray, ptr, arrayCount*sizeof(GLfloat));
        else
            qDebug() << glGetError();
        f->glUnmapBuffer( GL_SHADER_STORAGE_BUFFER );
        glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
    
        QString outStr;
        for (int i = 0; i < arrayCount; i++)
            outStr += QString(" %1").arg(outArray[i]);
    
        qDebug() << "out:" << outStr;
    
        doneCurrent();
    }
    
    void Scene3D::initializeGL()
    {
        initializeOpenGLFunctions();
    
    
        fShaderAvailable = hasOpenGLFeature(QOpenGLFunctions::Shaders);
        if (!fShaderAvailable)
            qDebug() << "!!! Shader functions are NOT available!!!";
    
        fVertexBufferAvailable = hasOpenGLFeature(QOpenGLFunctions::Buffers);
        if (!fVertexBufferAvailable)
            qDebug() << "!!! Vertex and index buffer functions are NOT available!!!";
    
        if (!hasOpenGLFeature(QOpenGLFunctions::FixedFunctionPipeline)) {
            qDebug() << "!!! The fixed function pipeline is NOT available.";
        }
        qDebug() << format();
    
        if (fShaderAvailable && fVertexBufferAvailable) {
            QString vendor, renderer, version, glslVersion;
            const GLubyte *p;
            if ((p = glGetString(GL_VENDOR)))
                vendor = QString::fromLatin1(reinterpret_cast<const char *>(p));
            if ((p = glGetString(GL_RENDERER)))
                renderer = QString::fromLatin1(reinterpret_cast<const char *>(p));
            if ((p = glGetString(GL_VERSION)))
                version = QString::fromLatin1(reinterpret_cast<const char *>(p));
            if ((p = glGetString(GL_SHADING_LANGUAGE_VERSION)))
                glslVersion = QString::fromLatin1(reinterpret_cast<const char *>(p));
            qDebug() << "vendor:" << vendor;
            qDebug() << "renderer:" << renderer;
            qDebug() << "version:" << version;
            qDebug() << "glslVersion:" << glslVersion;
    
            {
                arrayCount = 10;
                array = new GLfloat[arrayCount];
                for (int i = 0; i < arrayCount; i++)
                    array[i] = i;
            }
            {
                outArray = new GLfloat[arrayCount];
                for (int i = 0; i < arrayCount; i++)
                    outArray[i] = 0;
            }
    
            QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions();
    
            f->glGetIntegeri_v ( GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &fMaxComputeGroupSizeX );
            f->glGetIntegeri_v ( GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, &fMaxComputeGroupSizeY );
            f->glGetIntegeri_v ( GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2, &fMaxComputeGroupSizeZ );
            glGetIntegerv   ( GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &fMaxComputeItemsPerGroup );
    
    
            bufSize = arrayCount * sizeof(GLfloat);
    
            glGenBuffers(1, &inBuf);
            f->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, inBuf);
            glBindBuffer(GL_SHADER_STORAGE_BUFFER, inBuf);
            glBufferData(GL_SHADER_STORAGE_BUFFER, bufSize, array, GL_STATIC_DRAW);
            glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
    
            glGenBuffers(1, &outBuf);
            f->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, outBuf);
            glBindBuffer(GL_SHADER_STORAGE_BUFFER, outBuf);
            glBufferData(GL_SHADER_STORAGE_BUFFER, bufSize, outArray, GL_DYNAMIC_COPY);
            glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
    
            compSelectBufShader = new QOpenGLShader(QOpenGLShader::Compute);
            compSelectBufShader->compileSourceFile(":/new/prefix1/vtz_geom_compute_sh.vert");
            qDebug() << "ComputeShader:" << compSelectBufShader->log();
            compSelectBufProgram = new QOpenGLShaderProgram(this);
            compSelectBufProgram->addShader(compSelectBufShader);
            compSelectBufProgram->link();
            qDebug() << "compSelectBufProgram:" << compSelectBufProgram->log();
        }
    }
    
    void Scene3D::paintGL()
    {
        static int scale = 0;
        QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions();
        compSelectBufProgram->bind();
    
        compSelectBufProgram->setUniformValue("scale", scale);
        f->glDispatchCompute(2, 1, 1);
        f->glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
    
        compSelectBufProgram->release();
    
        scale++;
    }
    
    void MainWindow::on_pushButton_clicked()
    {
        scene.updateData();
    }
    

    // Shader

    #version 430
    #extension GL_ARB_compute_shader : enable
    #extension GL_ARB_shader_storage_buffer_object : enable
    
    layout( local_size_x = 5 ) in;
    
    uniform float scale;
    
    layout(std430, binding = 0) buffer Buf
    {
        float buf [];
    };
    
    
    layout(std430, binding = 1) buffer OutBuf
    {
        float outBuf [];
    };
    
    void main()
    {
        uint idx = gl_GlobalInvocationID.x;
        float p = buf [idx];
        float x = p + scale;
        outBuf [idx] = x;
    }
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.