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

Creating a webgl context in a webworker #10764

Closed
fibbo opened this issue Mar 25, 2020 · 6 comments
Closed

Creating a webgl context in a webworker #10764

fibbo opened this issue Mar 25, 2020 · 6 comments
Labels

Comments

@fibbo
Copy link

fibbo commented Mar 25, 2020

Using version 1.39.11 and Firefox developer edition 75.0b8 (64-bit)

I'm trying to use WebGL and Offscreen rendering in a web worker. Flags for linking are:

 -s USE_GLFW=3
 -s FULL_ES3=1
 -s OFFSCREEN_FRAMEBUFFER=1
 -s OFFSCREENCANVAS_SUPPORT=1
 -s USE_WEBGL2=1
 -s ENVIRONMENT=worker
EmscriptenWebGLContextAttributes attrs;
emscripten_webgl_init_context_attributes(&attrs);
attrs.majorVersion = 3;
attrs.minorVersion = 3;
attrs.renderViaOffscreenBackBuffer = true;
int ctx = emscripten_webgl_create_context(0, &attrs);

The program gets stuck inside create context and I'm wondering what's the problem. As I understand the first parameter of emscripten_webgl_create_context is the name of the canvas - but since I use offscreen rendering I guess that is not needed?

@kripken
Copy link
Member

kripken commented Mar 25, 2020

IIRC the model is to create the context on the main thread, so it is connected to the place where rendering appears. Then it is transferred to a worker (which emscripten should do automatically with those flags).

Can see browser.test_webgl_offscreen_canvas_only_in_pthread as a test that should show that working.

@stale
Copy link

stale bot commented Mar 26, 2021

This issue has been automatically marked as stale because there has been no activity in the past year. It will be closed automatically if no further activity occurs in the next 30 days. Feel free to re-open at any time if this issue is still relevant.

@stale stale bot added the wontfix label Mar 26, 2021
@stale stale bot closed this as completed Jun 4, 2021
@major-mayer
Copy link

major-mayer commented Jun 22, 2022

Hi everyone,
I know this is a pretty old issue, but I have exactly the same problem, so my program is also stuck at emscripten_webgl_create_context(...) .
I want to use native OffscreenCanvas and get rid of the proxying overhead.
For this i specified my context attributes like this:

	EmscriptenWebGLContextAttributes attr;
	emscripten_webgl_init_context_attributes(&attr);
	attr.explicitSwapControl = false;  // all frames are implicitly displayed to the user, if true the frame must be commited
	attr.proxyContextToMainThread = EMSCRIPTEN_WEBGL_CONTEXT_PROXY_DISALLOW;
	attr.renderViaOffscreenBackBuffer = false;
	auto ctx = emscripten_webgl_create_context("#canvas", &attr);

If I understand it correctly, i have to create a context on the main thread first, before i can transfer it using emscripten_pthread_attr_settransferredcanvases(&attr, "#canvas");.
Does this mean #canvas is now an offscreen canvas element bound to this new thread?
So even though i want to use an offscreen canvas, i first have to create a normal canvas element on my page, correct?

One thing that I also don't understand is if it's necessary to explicitly set Module["canvas].
Right now i am doing it like this in JS:

var Module = {
      onRuntimeInitialized: function() {
        try {
            Module["canvas"] = document.getElementById("canvas");
             //call c++ functions
        } catch (exception) {
           // handle errors
        }
      }

It would be very nice if you could clarify the things a bit for me @kripken 🙂

@major-mayer
Copy link

major-mayer commented Jun 27, 2022

Hmm so i tried as @kripken suggested and created a canvas on the main thread before and then handed the context over to the worker thread.
It's now looking like this:

// Create a context on the main thread first:
	EmscriptenWebGLContextAttributes webglAttr;
	emscripten_webgl_init_context_attributes(&webglAttr);
	emscripten_webgl_create_context("#canvas", &webglAttr);

	// Then create a pthread and transfer the canvas to the created thread
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	emscripten_pthread_attr_settransferredcanvases(&attr, "#canvas");
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  	pthread_create(&m_rcLoopThread, &attr, [](void* myThis)-> void*{
		  reinterpret_cast<MyClass*>(myThis)->MyRenderFunction(); pthread_exit(0);

		  }, this);

Unfortunately tho this gives me a new error right when I create the thread:
failed to transfer control of canvas "canvas" to OffscreenCanvas! Error: InvalidStateError: Failed to execute 'transferControlToOffscreen' on 'HTMLCanvasElement': Cannot transfer control from a canvas that has a rendering context

So transfering the control of a canvas element that has an existing context, doesn't seem to be the right way...

@major-mayer
Copy link

major-mayer commented Jun 28, 2022

I finally found the reason for this.
It is not necessary to create a context on the main thread first.
But it is crucial that you don't block on the main thread, while creating a context in a pthread.

That being said, I was always extremely confused how a test like this could pass then: https://github.com/emscripten-core/emscripten/blob/main/tests/gl_in_pthread.cpp
It's not using sOFFSCREEN_FRAMEBUFFER and only relies on sOFFSCREENCANVAS_SUPPORT, but also blocks on the main thread to wait for the context creation and drawing in the pthread.

Turns out that this thread is actually disabled on Chrome: https://github.com/emscripten-core/emscripten/blob/main/tests/test_browser.py#L4388
And I think that Chrome is the only browser where this test would be executed anyway, since Firefox is hiding it's offscreen canvas support behind a flag (yep that's correct).
So this is actually a test that's never executed.

I guess the reason to solve this problem is not blocking on the main thread and instead use a proxy to the main thread (PROXY_TO_PTHREAD).
I will test this now and report if it solves my problem.

@major-mayer
Copy link

Well, PROXY_TO_PTHREAD unfortunately isn't an option if you are using embind to create bindings for a CPP library, because there is no main function that you could proxy.
@kripken has described a workaround as pseudo-code here but I can't get it to working code...

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

No branches or pull requests

3 participants