Using eglMakeCurrent with PVRVFrame on multi threaded environment

This topic contains 2 replies, has 2 voices, and was last updated by  AugustoRighetto 3 years, 5 months ago.

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #31745

    Hi,

    I’m developing an app with three threads using PVRVFrame v9.8 libraries on MacOSX.
    In this app, the main thread is only responsible for spawning the rendering thread and a thread for uploading resources (textures, VBOs, shaders, …). Main thread doesn’t know about EGL or OpenGL ES 2.0.
    The rendering thread creates a EGLContext without sharing with any other EGLContext. After that, it creates a EGLWindowSurface and then calls eglMakeCurrent with these two new objects. When everything is set up, it calls glClear with red and then eglSwapBuffers.
    The resource uploader thread creates a shared EGLContext with the context created in the rendering thread. After that, it creates a PbufferSurface. When this thread calls eglMakeCurrent, the app crashes.

    No GL or EGL errors are generated during the calls.

    I’m using OSX 10.9.3 X86-64, PowerVR Tools & SDK v3.3.
    The dump points to the following address in eglMakeCurrent:
    Thread 9 Crashed:
    0 libEGL.dylib 0x000000010152ff5e eglMakeCurrent + 606

    This is the Rendering Thread source code:


    void RenderingThread::Impl::onStart()
    {
    LOGE("RenderingThread::Impl::onStart: %p", std::this_thread::get_id() );

    //


    EGL_CHECK(m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY));
    assert(m_eglDisplay != EGL_NO_DISPLAY);

    EGLBoolean displayInited;
    EGL_CHECK(displayInited = eglInitialize(m_eglDisplay, NULL, NULL));
    assert(displayInited);
    //


    EGLint numConfig = 0;
    EGLint confAttribs[] = {
    EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    EGL_NONE
    };
    EGL_CHECK(eglChooseConfig(m_eglDisplay, confAttribs, &m_eglConfig, 1, &numConfig));
    assert(numConfig == 1);
    //


    EGLBoolean apiBound;
    EGL_CHECK(apiBound = eglBindAPI(EGL_OPENGL_ES_API));
    assert(apiBound);
    //


    EGLint contextAttribs[] = {
    EGL_CONTEXT_CLIENT_VERSION, 2,
    EGL_NONE
    };
    EGL_CHECK(m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, contextAttribs));
    assert(m_eglContext != EGL_NO_CONTEXT);
    LOGE("RenderingThread::Impl::getEGLContext::eglCreateContext: %p", m_eglContext);
    //


    EGL_CHECK(m_eglSurface = eglCreateWindowSurface(m_eglDisplay, m_eglConfig, m_eglNativeWindow, nullptr));
    assert(m_eglSurface != EGL_NO_SURFACE);
    //


    EGLBoolean madeCurrent;
    EGL_CHECK(madeCurrent = eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext));
    assert(madeCurrent);
    //


    doTask();
    }

    void RenderingThread::Impl::doTask()
    {
    LOGE("RenderingThread::Impl::doTask: %p", std::this_thread::get_id());

    GL_CHECK(glClearColor(1.0, 0.0, 0.0, 1.0));
    GL_CHECK(glClear(GL_COLOR_BUFFER_BIT));
    //


    EGLBoolean bufferSwapped;
    EGL_CHECK(bufferSwapped = eglSwapBuffers(m_eglDisplay, m_eglSurface));
    assert(bufferSwapped);
    }

    This is the Resource Uploader source code:


    void ResourceUploadThread::Impl::onStart()
    {
    LOGE("ResourceUploadThread::Impl::onStart: %p", std::this_thread::get_id() );

    //


    EGL_CHECK(m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY));
    assert(m_eglDisplay != EGL_NO_DISPLAY);

    EGLBoolean displayInited;
    EGL_CHECK(displayInited = eglInitialize(m_eglDisplay, NULL, NULL));
    assert(displayInited);
    //


    EGLint numConfig = 0;
    EGLint confAttribs[] = {
    EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    EGL_NONE
    };
    EGL_CHECK(eglChooseConfig(m_eglDisplay, confAttribs, &m_eglConfig, 1, &numConfig));
    assert(numConfig == 1);
    //


    EGLBoolean apiBound;
    EGL_CHECK(apiBound = eglBindAPI(EGL_OPENGL_ES_API));
    assert(apiBound);
    //


    EGLint contextAttribs[] = {
    EGL_CONTEXT_CLIENT_VERSION, 2,
    EGL_NONE
    };
    LOGE("ResourceUploadThread::Impl::onStart::SharedContext: %p", m_eglSharedContext);
    EGL_CHECK(m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, m_eglSharedContext, contextAttribs));
    assert(m_eglContext != EGL_NO_CONTEXT);
    //


    EGLint surfaceAttribs[] = {
    EGL_WIDTH, 1,
    EGL_HEIGHT, 1,
    EGL_NONE
    };
    EGL_CHECK(m_eglSurface = eglCreatePbufferSurface(m_eglDisplay, m_eglConfig, surfaceAttribs));
    assert(m_eglSurface != EGL_NO_SURFACE);
    //


    EGLBoolean madeCurrent;
    EGL_CHECK(madeCurrent = eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext));
    assert(madeCurrent);
    //


    doTask();
    }

    void ResourceUploadThread::Impl::doTask()
    {
    LOGE("RenderingThread::Impl::doTask: %p", std::this_thread::get_id());

    GL_CHECK(glClearColor(0.0, 0.0, 1.0, 1.0));
    GL_CHECK(glClear(GL_COLOR_BUFFER_BIT));
    }

    The example code that comes with SDK 3.3 (Examples/Intermediate/MultiThreading) doesn’t have a pre built binary for OSX. Is this a sign that PVRVFrame is not thread safe? If this is the case, it this a fix that is scheduled for a near future?

    Regards,

    Augusto Righetto

    #38842

    chris
    Moderator

    Hi Augusto,

    Multithreading support on OSX is a little buggy at the moment, but it’s something I’ve been looking into recently as it’s gone overlooked for far too long. I believe the issue you’re seeing is due to an uninitialized variable bug within the emulation libraries.

    If you like, you can file a ticket at our support portal requesting a beta version of PVRVFrame for testing. Otherwise, this should be fixed in the next SDK release (along with the MultiThreading example for OSX)

    #38843

    Hi Chris,

    Thanks for you answer.
    I`ve created a ticket in your support portal. Thanks for the link.

    Regards,

    Augusto

Viewing 3 posts - 1 through 3 (of 3 total)
You must be logged in to reply to this topic.