Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Webgl calls from worker thread #8846

Closed
sergeyext opened this issue Jun 23, 2019 · 3 comments
Closed

Webgl calls from worker thread #8846

sergeyext opened this issue Jun 23, 2019 · 3 comments

Comments

@sergeyext
Copy link
Contributor

Consider the following example:

GLFWwindow* w;

void threadLoopIteration(void*)
{
        glClear(GL_COLOR_BUFFER_BIT);
        glfwSwapBuffers(w);
}

void tw()
{
        glfwMakeContextCurrent(w);
        emscripten_set_main_loop_arg(threadLoopIteration, nullptr, 0, 1);
}

void mainLoopIteration(void*) {}

int main()
{
        std::cout << "TSS: " << emscripten_has_threading_support() << std::endl;

        if (glewInit() != GLEW_OK) {
                std::cout << "No glew" << std::endl;
                return 1;
        }
        if (glfwInit() != GLFW_TRUE) {
                std::cout << "No glf" << std::endl;
                return 2;
        }
        w = glfwCreateWindow(100, 100, "Foo", 0, 0);

        glfwMakeContextCurrent(w);
        glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
        glfwMakeContextCurrent(nullptr);

        std::thread thread(tw);
        emscripten_set_main_loop_arg(mainLoopIteration, nullptr, 0, 1);

        return 0;
}

It worked correctly when compiled with sdk 1.38.31. After updating to sdk 1.38.36 it crashes with

Cannot read property 'clear' of undefined
    at _glClear (http://localhost:8006/ems_thread.js:6813:32)
    ...........

I'm compiling the code with

em++ --std=c++17 -s USE_PTHREADS=1 -s USE_GLFW=3 -s PTHREAD_POOL_SIZE=2 -o ems_thread.html ems_thread.cpp

Also tried:

  • Adding -s OFFSCREENCANVAS_SUPPORT=1 and/or -s USE_WEBGL2=1 with same result.
  • Removing emsdk, ~/.emscripten_cache/, ~/.emscripten and other sdk artifacts from home directory, reinstalling sdk from scratch. Same result.
  • Altering command line parameters order and using emcc instead of em++. Same result.

Offtopic:
I failed to roll back to 1.38.31, 38.33 and 38.34. Both adding older versions to existing latest installation and installing from scratch lead to error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory when running emcc. Only reinstalling latest from scratch can fix the problem. What is the proper way to use older versions?

What am I missing here?

@kripken
Copy link
Member

kripken commented Jun 24, 2019

I'm not sure how it worked earlier, but WebGL from a worker requires either offscreen canvas (browser support) or offscreen framebuffer (proxying support). Does it work with -s OFFSCREEN_FRAMEBUFFER?

If that's not it, then as a regression, bisecting might be the fastest way to see what broke this.

About libtinfo, there was an issue with that on our linux builds - turns out different linux distros have different versions and they can be incompatible (see for example emscripten-core/emsdk#252). That should be fixed on current builds, but older ones may not work without installing locally some other libtinfo versions for your distro.

@sergeyext
Copy link
Contributor Author

sergeyext commented Jul 19, 2019

Updated to 1.38.39 and compiled the same code with -s OFFSCREEN_FRAMEBUFFER:

em++ --std=c++17 -s USE_PTHREADS=1 -s USE_GLFW=3 -s PTHREAD_POOL_SIZE=2 -s OFFSCREENCANVAS_SUPPORT=1 -s OFFSCREEN_FRAMEBUFFER=1 -o ems_thread.html ems_thread.cpp

It does not crash, but also does not clear the viewport with red, as expected.

Also tried to move gl initialization to working thread, got crash on glfwInit (ReferenceError: window is not defined).

Next, I removed threading from code and compiled it with -s OFFSCREENCANVAS_SUPPORT=1 -s OFFSCREEN_FRAMEBUFFER=1:

GLFWwindow* w;

void mainLoopIteration(void*)
{
        glClear(GL_COLOR_BUFFER_BIT);
        glfwSwapBuffers(w);
}

int main()
{
        std::cout << "TSS: " << emscripten_has_threading_support() << std::endl;

        if (glfwInit() != GLFW_TRUE) {
                std::cout << "No glfw" << std::endl;
                return 2;
        }
        w = glfwCreateWindow(100, 100, "Foo", 0, 0);
        if (glewInit() != GLEW_OK) {
                std::cout << "No glew" << std::endl;
                return 1;
        }


        glfwMakeContextCurrent(w);
        glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
        emscripten_set_main_loop_arg(mainLoopIteration, nullptr, 0, 1);

        return 0;
}

Got black viewport. Removing OFFSCREEN_FRAMEBUFFER=1 fixed the problem. Looks like glfwSwapBuffers(); does not swap anything with OFFSCREEN_FRAMEBUFFER=1 flag. Or am I missing any other call for buffer swapping?

@sergeyext
Copy link
Contributor Author

Replaced glfwSwapBuffers() with emscripten_webgl_commit_frame() in multithreaded test, now it works.

Probably glfwSwapBuffers() should call emscripten_webgl_commit_frame() when compiled with OFFSCREEN_FRAMEBUFFER.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants