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

EGL multi-context support, and other ideas #391

Open
tycho opened this issue Nov 2, 2022 · 4 comments
Open

EGL multi-context support, and other ideas #391

tycho opened this issue Nov 2, 2022 · 4 comments

Comments

@tycho
Copy link

tycho commented Nov 2, 2022

It seems like the EGL loader could really benefit from multi-context support. With EGL 1.5, or with EGL_EXT_client_extensions, different extensions are made available without and with an EGLDisplay, i.e. client vs display extensions respectively. I found that in my code I was forced to re-load the context any time I needed to switch back and forth between the two, which is a bit cumbersome.

I've been maintaining my own fork of glad2 to better handle this. My changes are almost certainly not ready to merge as-is, because I only really use glad2 with these arguments:

glad --out-path="$PWD" --api gl:core,gles2,vulkan,egl,glx,wgl --merge c --alias --loader --mx --mx-global

So there's a high chance that my changes break other argument combinations, or tests, in some way. (Also I had to restore the --mx-global feature, I'm not sure why that's gone in the glad2 branch right now?)

Regardless of the quality of my changes (man, that templating stuff is a headache), I'd like to share these changes with you in case you can get them into better shape!

tycho@f0a1597 Allow loading with EGL_NO_DISPLAY (to get client extensions), and do not implicitly get the current EGLDisplay when EGL_NO_DISPLAY is passed
tycho@10c9b1d EGL multi-context support

And this change is less relevant to this specific problem, but maybe worth review anyway:

tycho@ba3c786 Implement plain C API function declarations as MSVC IntelliSense hints, because the global context macro definitions don't give any source-level hints for arguments. This change allows Visual Studio to do this:
image

Anyway, the multi-context support for EGL can be used in practice something like this:

GladEGLContext s_contextEGL[2];
[...]
gladSetEGLContext(&s_contextEGL[0]);
gladLoadEGL(EGL_NO_DISPLAY, (GLADloadfunc)SDL_EGL_GetProcAddress);
gladSetEGLContext(&s_contextEGL[1]);
gladLoadEGL(eglDisplay, (GLADloadfunc)SDL_EGL_GetProcAddress);

So the context at index 0 includes the supported client extensions, while index 1 contains the supported display extensions.

As I'm writing this, I had an afterthought that maybe an alternative to doing this (and possibly a more usable one) would be to make the EGL loader discover the client and display extensions at the same time. That is, if EGL_NO_DISPLAY is provided, only discover client extensions, and if a real EGLDisplay handle is provided, do one pass to discover client extensions via EGL_NO_DISPLAY and then do a second pass to discover display extensions with the provided EGLDisplay, and store both of them within the same GladEGLContext structure.

@Dav1dde
Copy link
Owner

Dav1dde commented Nov 2, 2022

Please note my EGL knowledge is very limited, but I still wanted to respond before looking further into the details.

Also I had to restore the --mx-global feature, I'm not sure why that's gone in the glad2 branch right now?)

This came up before releasing version 2.0 that the feature may actually be not useful. If you want to have multiple contexts, why not also get rid of the global state and handle it properly through the context struct? There were also 1-2 things not sound in the implementation and overall it adds a lot of problems to the code generation. That's why I disabled it for 2.0 and to reconsider if a usecase comes up. I am curious about your opinion on mx-global and why you need it.

Regardless of the quality of my changes (man, that templating stuff is a headache),

It unfortunately is.

tycho@ba3c786 Implement plain C API function declarations as MSVC IntelliSense hints, because the global context macro definitions don't give any source-level hints for arguments. This change allows Visual Studio to do this:

I don't understand why an IDE/LSP can't resolve 1 layer of #define's...

I'd like to share these changes with you in case you can get them into better shape!

Thanks! This was always on the TODO, but I never personally needed it and I havent heard from anyone (until now) that this is actually something they would use.

That is, if EGL_NO_DISPLAY is provided, only discover client extensions, and if a real EGLDisplay handle is provided, do one pass to discover client extensions via EGL_NO_DISPLAY and then do a second pass to discover display extensions with the provided EGLDisplay, and store both of them within the same GladEGLContext structure.

This would be the way to go if all extension with EGL_NO_DISPLAY are also available with a EGLDisplay. Why does discovering extensions with a valid EGLDisplay not include all extensions you would also get with EGL_NO_DISPLAY?

This beahviour would also be similar to Vulkan. Vulkan loads device pointers with the device, instance pointers with the instance and passes null when necessary.

Anyway, the multi-context support for EGL can be used in practice something like this:

GladEGLContext s_contextEGL[2];
[...]
gladSetEGLContext(&s_contextEGL[0]);
gladLoadEGL(EGL_NO_DISPLAY, (GLADloadfunc)SDL_EGL_GetProcAddress);
gladSetEGLContext(&s_contextEGL[1]);
gladLoadEGL(eglDisplay, (GLADloadfunc)SDL_EGL_GetProcAddress);

Why do you need different contexts for EGL_NO_DISPLAY and eglDisplay? This comes back to the previous point, why is a context with a display potentially less powerful than one without?

@tycho
Copy link
Author

tycho commented Nov 2, 2022

I don't understand why an IDE/LSP can't resolve 1 layer of #define's...

Yes, it's really dumb.

This came up before releasing version 2.0 that the feature may actually be not useful. If you want to have multiple contexts, why not also get rid of the global state and handle it properly through the context struct? There were also 1-2 things not sound in the implementation and overall it adds a lot of problems to the code generation. That's why I disabled it for 2.0 and to reconsider if a usecase comes up. I am curious about your opinion on mx-global and why you need it.

I technically don't actually want multiple contexts, at least in the GL case.

I just want two things:

  • A Glad{api}Context structure, instead of tons of individual globals since it aids in debugging especially
  • Macro wrappers which dereference a global GladGLContext pointer to call GL functions

I prefer to have the multi-context support just for the GladGLContext structure type definition. It's trivial to reset it after unload (via memset), which has aided in debugging when my program didn't do something I expected. I found it's easier to debug a null pointer dereference than a dereference of pointers into an unloaded library's former address space (right now glad doesn't zero those out on unload, it just unloads the library).

But I do want the global multi-context support as well. With non-global multi-context, I have none of the API wrapper macros, which sucks for usability, and there's no way I'm going to go through my code just to replace glBindTexture -> someGlobal->BindTexture or whatever.

This would be the way to go if all extension with EGL_NO_DISPLAY are also available with a EGLDisplay. Why does discovering extensions with a valid EGLDisplay not include all extensions you would also get with EGL_NO_DISPLAY?

Why do you need different contexts for EGL_NO_DISPLAY and eglDisplay? This comes back to the previous point, why is a context with a display potentially less powerful than one without?

I think I explained it poorly...

If you do eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS) you will get client extensions, and if you do eglQueryString(realEglDisplay, EGL_EXTENSIONS) you get display extensions -- but there is no overlap between the two.

For example, here's what ANGLE gives for client extensions on Windows:

EGL_ANGLE_device_creation
EGL_ANGLE_device_creation_d3d11
EGL_ANGLE_experimental_present_path
EGL_ANGLE_feature_control
EGL_ANGLE_platform_angle
EGL_ANGLE_platform_angle_d3d
EGL_ANGLE_platform_angle_d3d11on12
EGL_ANGLE_platform_angle_device_id
EGL_ANGLE_platform_angle_opengl
EGL_ANGLE_platform_angle_vulkan
EGL_EXT_client_extensions
EGL_EXT_device_query
EGL_EXT_platform_base
EGL_EXT_platform_device
EGL_KHR_client_get_all_proc_addresses
EGL_KHR_debug

And here's the display extensions list when using the ANGLE Vulkan backend:

EGL_ANDROID_blob_cache
EGL_ANDROID_recordable
EGL_ANGLE_create_context_backwards_compatible
EGL_ANGLE_create_context_client_arrays
EGL_ANGLE_create_context_extensions_enabled
EGL_ANGLE_create_context_webgl_compatibility
EGL_ANGLE_create_surface_swap_interval
EGL_ANGLE_display_semaphore_share_group
EGL_ANGLE_display_texture_share_group
EGL_ANGLE_program_cache_control
EGL_ANGLE_robust_resource_initialization
EGL_ANGLE_surface_orientation
EGL_ANGLE_vulkan_image
EGL_CHROMIUM_create_context_bind_generates_resource
EGL_EXT_buffer_age
EGL_EXT_create_context_robustness
EGL_EXT_gl_colorspace_scrgb_linear
EGL_EXT_image_gl_colorspace
EGL_EXT_pixel_format_float
EGL_IMG_context_priority
EGL_KHR_create_context
EGL_KHR_create_context_no_error
EGL_KHR_fence_sync
EGL_KHR_get_all_proc_addresses
EGL_KHR_gl_colorspace
EGL_KHR_gl_renderbuffer_image
EGL_KHR_gl_texture_2D_image
EGL_KHR_gl_texture_cubemap_image
EGL_KHR_image
EGL_KHR_image_base
EGL_KHR_no_config_context
EGL_KHR_partial_update
EGL_KHR_reusable_sync
EGL_KHR_surfaceless_context
EGL_KHR_swap_buffers_with_damage
EGL_KHR_wait_sync

So in order to represent all client and display extensions within a single GladEGLContext, you would need to query once with eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS) and again with eglQueryString(realEglDisplay, EGL_EXTENSIONS), concatenate the two strings, and use that as the full extension list for the rest of the detection process.

I did a test with this idea here tycho@fc5c724 and it seems to work, creating an amalgamated client + display extension context.

EDIT: Cleaning up some poor wording and adding some newer findings.

@tycho
Copy link
Author

tycho commented Nov 2, 2022

I missed a bunch when I was doing the EGL multi-context stuff, this is a much better change, though probably still not complete: tycho@d6d562c

@lewa-j
Copy link

lewa-j commented Dec 22, 2022

tycho@ba3c786 Implement plain C API function declarations as MSVC IntelliSense hints, because the global context macro definitions don't give any source-level hints for arguments.

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

3 participants