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

emscripten_webgl_create_context ignores EmscriptenWebGLContextAttributes.majorVersion #23372

Open
ypujante opened this issue Jan 11, 2025 · 5 comments

Comments

@ypujante
Copy link
Contributor

I created the following test file:

#include <stdio.h>
#include <emscripten.h>
#include <emscripten/html5.h>
#include <GLES3/gl3.h>
int main() {
  constexpr int version = 0;
  EmscriptenWebGLContextAttributes attributes{};
  attributes.majorVersion = version;
  auto handle = emscripten_webgl_create_context("#canvas", &attributes);
  emscripten_webgl_make_context_current(handle);
  printf("%d | WebGL: %s | %s\n", version, glGetString(GL_VERSION), glGetString(GL_RENDERER));
  emscripten_webgl_destroy_context(handle);
  return 0;
}

Depending on which compilation flag it is called with, emscripten_webgl_create_context simply ignores the provided EmscriptenWebGLContextAttributes.majorVersion

Case 1: NO flag (ignored => 1.0 always)

// emcc issue.cpp -o build/index.html
// 0 | WebGL: OpenGL ES 2.0 (WebGL 1.0 (OpenGL ES 2.0 Chromium)) | WebKit WebGL
// 1 | WebGL: OpenGL ES 2.0 (WebGL 1.0 (OpenGL ES 2.0 Chromium)) | WebKit WebGL
// 2 | WebGL: OpenGL ES 2.0 (WebGL 1.0 (OpenGL ES 2.0 Chromium)) | WebKit WebGL

Case 2: -sMIN_WEBGL_VERSION=2 (ignored => 2.0 always)

// 0 | WebGL: OpenGL ES 3.0 (WebGL 2.0 (OpenGL ES 3.0 Chromium)) | WebKit WebGL
// 1 | WebGL: OpenGL ES 3.0 (WebGL 2.0 (OpenGL ES 3.0 Chromium)) | WebKit WebGL
// 2 | WebGL: OpenGL ES 3.0 (WebGL 2.0 (OpenGL ES 3.0 Chromium)) | WebKit WebGL

Case 3: -sMAX_WEBGL_VERSION=2 (uses value)

// 0 | WebGL: OpenGL ES 2.0 (WebGL 1.0 (OpenGL ES 2.0 Chromium)) | WebKit WebGL
// 1 | WebGL: OpenGL ES 2.0 (WebGL 1.0 (OpenGL ES 2.0 Chromium)) | WebKit WebGL
// 2 | WebGL: OpenGL ES 3.0 (WebGL 2.0 (OpenGL ES 3.0 Chromium)) | WebKit WebGL

What this test demonstrates is that emscripten_webgl_create_context ignores the majorVersion flag in 2 cases.

Internally, emscripten_webgl_create_context delegates the logic to GL.createContext

I know and understand that GL.createContext is being called by other parts of the code (like for example by library_glfw.js) but without attributes and so it makes sense that because there is no way to communicate a version, then you need to use a compilation flag to communicate the intent.

But when emscripten_webgl_create_context is being called with an attribute and a defined version, I think it doesn't make any sense to ignore it.

Proposed solution

What I am suggesting is to modify the code in GL.createContext to do something like this (pseudo code):

if webGLContextAttributes.majorVersion is undefined or 0
  // same logic as current implementation using compilation flag
else
  // use webGLContextAttributes.majorVersion to determine which context to create (ignore flags)

I can work on it if you think that is something you would be open to.

@sbc100
Copy link
Collaborator

sbc100 commented Jan 13, 2025

This seems like the expsect beahvour, bit maybe there is some misunderstanding about what MIN_WEBGL_VERSION and MAX_WEBGL_VERSION will do.

When no flag at all is used MIN_WEBGL_VERSION and MAX_WEBGL_VERSION both default to 1 which means the emscripten output is not built to support anything but 1, which means that 1.0 always is the expected result in this case.

With -sMIN_WEBGL_VERSION=2 only webgl 2 support is included so its not possible to use webgl 1 so 2.0 always is the expected result.

The only why the version can be controlled is if support for both webgl1 and webgl2 is included in the build, and the only way to go that is to have -sMIN_WEBGL_VERSION=1 (or just left as the default) and -sMAX_WEBGL_VERSION=2.

Perhaps one thing we should be doing here is to abort/assert if EmscriptenWebGLContextAttributes requests a GL version that is not support?

@ypujante
Copy link
Contributor Author

Thank you for explaining the internal of how things work.

But when you say "there is some misunderstanding", I think you have to take a step back and put yourself in the shoes of a user not knowing how the internals of Emscripten work.

As far as I can tell, emscripten_webgl_create_context is a public API. When you look at the "documentation" of the API without looking at the big picture, there is no indication whatsoever that essentially the major version provided via the attribute is simply ignored unless you provide the -sMAX_WEBGL_VERSION=2 linker flag.

To give you another point of view/example, just imagine for a second that the fopen C call behaved the same way (the public api is fopen(const char* filename, const char* mode)):

  • if you call fopen without providing any flag to the compiler, then mode is ignored and the file is always opened in read-only mode
  • if you call fopen and provide the compiler flag FOPEN_WRITE_ONLY, then mode is ignored and the file is always opened in write-only mode
  • if you call fopen and provide the compiler flag FOPEN_RW, then mode is no longer ignored and the value you provide is used

Wouldn't you think this is quite an awkward public API? At best it is confusing. At worst it is really counter-intuitive and prone to bugs.

That's how emscripten_webgl_create_context feels like from an outside user.

So yes I suggest, unless you want to change the way the API works, then at the bare minimum the documentation should be changed to clearly highlight the fact that the major version is ignored unless -sMAX_WEBGL_VERSION=2 linker flag is specified. And I supposed aborting when there is a mismatch between the flags and the value of majorVersion is a good idea but it is unclear about the consequences...

sbc100 pushed a commit that referenced this issue Jan 14, 2025
This is a follow up to the
[ticket](#23372)
discussion.

When users are using my port, the window hint
`GLFW_CONTEXT_VERSION_MAJOR` is ignored due to how Emscripten behaves
internally.

If the port sets the linker flag `MAX_WEBGL_VERSION=2`, then for a user
of the library, which interact throught the GLFW API, it transparently
works without asking the user to understand the internals of Emscripten
and modify their build script.
@sbc100
Copy link
Collaborator

sbc100 commented Jan 14, 2025

So yes I suggest, unless you want to change the way the API works, then at the bare minimum the documentation should be changed to clearly highlight the fact that the major version is ignored unless -sMAX_WEBGL_VERSION=2 linker flag is specified. And I supposed aborting when there is a mismatch between the flags and the value of majorVersion is a good idea but it is unclear about the consequences...

I agree, updating the doc and improving emscripten_webgl_create_context both sounds like good ideas. Passing majorVersion=2 in EmscriptenWebGLContextAttributes when -sMAX_WEBGL_VERSION=1 seems like it should be an error to me.

@ypujante
Copy link
Contributor Author

Do you want me to submit a PR for this work?

@sbc100
Copy link
Collaborator

sbc100 commented Jan 14, 2025

Thanks would be great, thank you!

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