[SOLVED] QOpenGLShaderProgram segfault



  • I wanna write some app that use QOpenGLWidget and QOpenGLFunctions. And I have problem when I try to use any of functions from QOpenGLShaderProgram in other function that initializeGL or paintGL. Exactly when I even try to use program->log() i have segmentation fault. In that function I have makeCurrent(). When I create new QOpenGLShaderProgram in that function there's no problem, but when not (and I'm sure that object of QOpenGLShaderProgram exists at the time) i have segfault. Have you had problem like this?


  • Qt Champions 2016

    Hi and welcome
    I have

    class GLRender : public QOpenGLWidget, protected QOpenGLFunctions
    {
        Q_OBJECT
        QOpenGLShaderProgram* m_program;
    ..
    

    and tried from

     void mousePressEvent(QMouseEvent *)
        {
            qDebug () << m_program->log();
            emit  RenderSelected(this);
        }
    

    And no crashes.


  • Lifetime Qt Champion

    Hi,

    To add to @mrjj, where are you initializing your QOpenGLShaderProgram ? And also when are you initializing it ?



  • Hey, thanks for your answers. It looks exactly like this:

    #include "openglcontroller.h"
    #include "global.h"
    
    #include <cmath>
    #include <QWidget>
    #include <QMouseEvent>
    #include <QWheelEvent>
    #include <QOpenGLShaderProgram>
    #include <QDebug>
    
    OpenGLController::OpenGLController(QWidget * parent) :
        QOpenGLWidget(parent),
        m_parent(parent),
        m_f(nullptr),
        m_wheelMesh(parent),
        m_camAngleX(0.0f),
        m_camAngleY(0.0f),
        m_camFar(3.0f),
        m_camYPos(0.5f)
    {
        m_objectMesh = nullptr;
    }
    
    OpenGLController::~OpenGLController()
    {
        clean();
    }
    
    void OpenGLController::initializeGL()
    {
        bool ok = true;
        makeCurrent();
        m_f = QOpenGLContext::currentContext()->functions();
        initializeOpenGLFunctions();
        connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &OpenGLController::clean);
    
        glClearColor(g_bgColor.x(), g_bgColor.y(), g_bgColor.z(), g_bgColor.w());
    
        m_colorShader = new QOpenGLShaderProgram/*(QOpenGLContext::currentContext())*/;
        ok &= m_colorShader->addShaderFromSourceFile(QOpenGLShader::Vertex, "shaders/colorS.vs");
        ok &= m_colorShader->addShaderFromSourceFile(QOpenGLShader::Fragment, "shaders/colorS.fs");
        if(ok)
        {
            m_colorShader->bindAttributeLocation("vVertex",0);
            m_colorShader->link();
            m_colorShader->bind();
    
            m_projMatInfo.id = m_colorShader->uniformLocation(m_projMatInfo.name = "Mproj");
            m_moveMatInfo.id = m_colorShader->uniformLocation(m_moveMatInfo.name = "Mmove");
            m_colorInfo.id = m_colorShader->uniformLocation(m_colorInfo.name = "materialColor");
    
            setWheelGrid();
    
            m_colorShader->release();
        }
        else
        {
            emit sendLog(Log(log_critical,tr("Nie znaleziono zawartości w katalogu shaders lub nie udało się uruchomić programów cieniujących"),
                             -1,"OpenGLController","initializeGL"));
        }
        doneCurrent();
    }
    
    void OpenGLController::resizeGL(int w, int h)
    {
        m_projMat.setToIdentity();
        m_projMat.perspective(80.0f,(float)(w)/(float)h,0.1f,20.0f);
    }
    
    void OpenGLController::paintGL()
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glEnable(GL_DEPTH_TEST);
    
        m_moveMat.setToIdentity();
        m_moveMat.translate(0.0f, 0.0f, -m_camFar);
        m_moveMat.rotate(m_camAngleX,1.0f,0.0f,0.0f);
        m_moveMat.rotate(m_camAngleY,0.0f,1.0f,0.0f);
        m_moveMat.translate(0.0f, -m_camYPos, 0.0f);
    
    
        m_colorShader->bind();
        m_colorShader->setUniformValue(m_projMatInfo.id, m_projMat);
        m_colorShader->setUniformValue(m_moveMatInfo.id, m_moveMat);
        m_colorShader->setUniformValue(m_colorInfo.id, m_wheelColor);
    
        m_wheelMesh.vao.bind();
        m_f->glEnable(GL_LINE_SMOOTH);
        m_f->glLineWidth(g_gridBold);
        m_f->glDrawArrays(GL_LINES, 0, m_wheelMesh.vCount);
        m_f->glDisable(GL_LINE_SMOOTH);
    
        if(m_objectMesh != nullptr)
        {
            m_objectMesh->vao.bind();
            m_colorShader->bind();
            m_colorShader->setUniformValue(m_projMatInfo.id, m_projMat);
            m_colorShader->setUniformValue(m_moveMatInfo.id, m_moveMat);
            m_colorShader->setUniformValue(m_colorInfo.id, m_wheelColor);
    
            m_f->glDrawArrays(GL_POINTS, 0, m_objectMesh->vCount);
        }
    
        m_colorShader->release();
    }
    
    // Funkcję można poprawić poprzez uwzględnienie rozmiaru renderowanego obszaru
    void OpenGLController::mouseMoveEvent(QMouseEvent * event)
    {
       // ... here is some code
    }
    
    void OpenGLController::wheelEvent(QWheelEvent * event)
    {
        //.... Here is some code
    }
    
    void OpenGLController::createObjectsMesh(unsigned horizontalPts, unsigned verticalPts)
    {
        delete m_objectMesh;
        m_objectMesh = new OGLCMesh(m_parent);
        m_objectMesh->vao.create();
        m_objectMesh->vao.bind();
        m_objectMesh->vbo.create();
        m_objectMesh->vbo.bind();
        m_objectMesh->vbo.allocate(horizontalPts * verticalPts * 4 * sizeof(GLfloat));
    
        //m_colorShader->log();  HERE IS SEGFAULT
    }
    
    void OpenGLController::addObjectsSubMesh(unsigned vertsCount, double * vertices)
    {
        makeCurrent();
        GLfloat * vConverted = new GLfloat[vertsCount * 4];
        for(unsigned i=0; i < vertsCount * 4; i++)
            vConverted[i] = vertices[i];
    
        m_objectMesh->vbo.write(m_objectMesh->vCount * 4, vConverted, vertsCount * 4);
        m_objectMesh->vCount += vertsCount;
        delete [] vConverted;
    
        update();
        doneCurrent();
    }
    
    void OpenGLController::setWheelGrid(float radius, unsigned rings, unsigned diameters)
    {
        float angleStep = 360.0f / diameters;
        float radStep = radius / rings;
        unsigned edgesCount = (rings + 1) * diameters;
        unsigned vertsCount = edgesCount * 2;
        if(m_wheelMesh.vTab != nullptr)
        {
            delete [] m_wheelMesh.vTab;
            m_wheelMesh.vTab = nullptr;
        }
        m_wheelMesh.vCount = vertsCount;
        m_wheelMesh.vTab = new GLfloat[vertsCount * 4];
    
        unsigned index = 0;
        //Najpierw promienie
        for(unsigned i = 0; i < diameters; i++)
        {
            double currentAngle = (double)angleStep * i * g_pi / 180.0;
            double nextAngle = (double)angleStep * (i+1) * g_pi / 180.0;
            m_wheelMesh.vTab[index++] = 0.0f;
            m_wheelMesh.vTab[index++] = 0.0f;
            m_wheelMesh.vTab[index++] = 0.0f;
            m_wheelMesh.vTab[index++] = 1.0f;       //Współrzędne środka
            m_wheelMesh.vTab[index++] = radius * cos(currentAngle);
            m_wheelMesh.vTab[index++] = 0.0f;
            m_wheelMesh.vTab[index++] = radius * sin(currentAngle);
            m_wheelMesh.vTab[index++] = 1.0f;
            //Następnie kolejne okręgi
            for(unsigned j = 0; j < rings; j++)
            {
                m_wheelMesh.vTab[index++] = radStep * (j+1) * cos(currentAngle);
                m_wheelMesh.vTab[index++] = 0.0f;
                m_wheelMesh.vTab[index++] = radStep * (j+1) * sin(currentAngle);
                m_wheelMesh.vTab[index++] = 1.0f;
                m_wheelMesh.vTab[index++] = radStep * (j+1) * cos(nextAngle);
                m_wheelMesh.vTab[index++] = 0.0f;
                m_wheelMesh.vTab[index++] = radStep * (j+1) * sin(nextAngle);
                m_wheelMesh.vTab[index++] = 1.0f;
            }
        }
    
        if(!m_wheelMesh.vao.isCreated())
            m_wheelMesh.vao.create();
        m_wheelMesh.vao.bind();
        if(!m_wheelMesh.vbo.isCreated())
            m_wheelMesh.vbo.create();
        m_wheelMesh.vbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
        m_wheelMesh.vbo.bind();
        m_wheelMesh.vbo.allocate(m_wheelMesh.vTab, m_wheelMesh.vCount*4*sizeof(GLfloat));
    
        m_colorShader->enableAttributeArray(0);
        m_colorShader->setAttributeArray(0,GL_FLOAT,0,4);
    }
    
    void OpenGLController::clean()
    {
        makeCurrent();
        m_wheelMesh.vao.destroy();
        m_wheelMesh.vbo.destroy();
        if(m_objectMesh != nullptr)
        {
            m_objectMesh->vao.destroy();
            m_objectMesh->vbo.destroy();
        }
        delete m_colorShader;
        m_colorShader = 0;
       // delete m_f;
        doneCurrent();
    }
    

    And the problem is in function createObjectsMesh. When I will create QOpenGLShaderProgram again in this function there will be no problem, but if I do like this I have segmentation fault.

    m_colorShader is QOpenGLShaderProgram with which i have problem.



  • Ok, I found solution. Well, i have made mistake in class MainWindow.
    Now this is part from MainWindow:

    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    private:
        Ui::MainWindow *ui;
        OpenGLController * m_glController;  // Here I had: OpenGLController m_glController
    };
    

    And in MainWindow.cpp constructor:

    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        m_glController = ui->openGLWidget;   // I did not wrote this line earlier 
    }
    

    And how I execute function createObjectsMesh(...) :

    m_glController->createObjectsMesh(ui->sb_pointsHorizontal->value(), 480);
    // Earlier it was just object, not pointer - like this:
    // m_glController.createObjectsMesh(ui->sb_pointsHorizontal->value(), 480);
    

    So in my app I had 2 objects of QOpenGLWidget - one that is made in GUI (Qt Form) and one which I had in my MainWindow class. And when I executed function createObjectsMesh(...) I did it for second of them, not first which were actually drawn in GUI.
    I should just not to create another QOpenGLWidget in MainWindow class, but only get pointer to this one from GUI, like this:

    m_glController = ui->openGLWidget;
    

    So now I have only one QOpenGLWidget - this one that is drawn in GUI.

    Anyway - thanks for your help :D


  • Qt Champions 2016

    ahh, tricky one :)


Log in to reply
 

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