Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QGLWidget and Threads [SOLVED]



  • Hi there,

    I just googled my problem but I cannot find exactly what i want.

    Description:

    I have a class deriving from QGLWidget which handles user inputs and is responsible for drawing my scene.
    I overloaded the paintGL() method and let it send a signal:
    @void MyWidget::paintGL()
    {
    emit sigReadyPaint(); //that's all
    }@

    The signal will be received by a Worker object which has been moved to another thread.
    This worker just recieves the sigReadyPaint() signal from MyWidget and simply calls the startFrame() method of MyWidget like so:
    @void MyWorker::slotReadyPaint()
    {
    if(_widget != NULL) //_widget (MyWidget) is a private member of MyWorker
    {
    _widget->makeCurrent();
    _widget->startFrame();
    }
    }

    void MyWidget::init()
    {
    if(!_initialized) //_initialized (bool) is a private member of MyWidget and is false by default
    {
    QGLShaderProgram* shader= new QGLShaderProgram(); //shader (QGLShaderProgram) is a private member of MyWidget

    //the following lines are causing the "Shaders are not supported" error. But only if i call it from a thread!!
    if(!shader->addShaderFromSourceFile(QGLShader::Vertex, "myVertexShaderFile"))
    {
    cout<<"Failed to compile vertex shader!"<<endl;
    return;
    }

    if(!shader->addShaderFromSourceFile(QGLShader::Fragment, "myFragmentShaderFile"))
    {
    cout<<"Failed to compile fragment shader!"<<endl;
    return;
    }

    if(!shaderProgram->link())
    {
    cout<<"Failed to link shader!"<<endl;
    return;
    }

    vertex = shader->attributeLocation("vertex"); //vertex(int) is a private member of MyWidget

    _initialized = true;
    }
    }

    void MyWidget::startFrame()
    {
    init();

    shader->enableAttributeArray(vertex); //crash(segmentation fault) in this line

    //....
    }
    @

    Now when I reach the line shader->enableAttributeArray(vertex) I get a segmentation fault.
    If i do not move my worker to a thread it all works fine! And it works also fine if i set the SIGNAL/SLOT connection type to Qt::DirectConnection which is not what i need, because it is not asynchronous.

    I know that QGLContext is not thread safe (as OpenGL isn't) but I have only ONE THREAD executing openGL commands and shader commands!

    Thanks in advance

    [EDIT: I updated my last sentences because that statement was wrong. My Qt didn't really build my changes. Now it describes the real situation as it is.]



  • makeCurrent() is not the problem, because when i call it i get the following message from Qt:
    QGLContext::makeCurrent() : wglMakeCurrent failed: The requested resource is aleary in use (translated)
    Which means that my widget is already the current, i guess.



  • Hello Seraph !

    Why do You initialize shader to 0 ?



  • I'm sorry. I usually wanted to add a //.... comment between line 14 and 15.

    I edited the code



  • OK. I now have put all openGL code into my render step. So only the thread is calling them.
    I now get the following error:

    QGLShaderProgram: shader programs are not supported
    (Internal error: pc 0x0 in read in psymtab, but not in symtab.)
    (Internal error: pc 0x0 in read in psymtab, but not in symtab.)
    (Internal error: pc 0x0 in read in psymtab, but not in symtab.)
    (Internal error: pc 0x0 in read in psymtab, but not in symtab.)
    ...
    ...

    The "shader programs are not supported" error happens after calling
    QGLShaderProgram::addShaderFromSourceFile() which returns false

    Seems to me like i get a wrong context. But why is it working without the thread?

    I printed my format version, it is at 4!

    What could cause this error?



  • No idea anybody? Is there no default solution for that?

    I just had a look at this "article ":http://doc.qt.digia.com/qq/qq06-glimpsing.html#writingmultithreadedglapplications which is 10 years old! This cannot be state of the art!

    As far as I understand it is not necessary to create the gl context in a new thread, right?
    Is it necessary to have all open gl commands called by the thread? I don't think so, because only one context can be current at the same time right? And if i call makeCurrent() and execute some openGl commands they will be executed on the (new) current context. If i call it from the thread or not shouldn't be important, right?
    But how can it happen, that i get the error: "Shaders are not supportet" once i move my render worker to a thread?
    If not everything works fine!

    Please can anyone help me out with this?



  • OK i did it like the article said. It is not state of the art but it's working with QT4.8.4

    Thanks.


Log in to reply