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

New platform backend: imgui_impl_emscripten #8178

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

slowriot
Copy link
Contributor

What is it?

A new platform back-end, similar to imgui_impl_glfw, removing any dependency on GLFW, for use when building with Emscripten running in a web browser. Instead of using Emscripten's GLFW compatibility wrapper for input to imgui, it uses Emscripten's HTML5 API directly.

Motivation

The primary motivation for this is the development of WebGPU, and relative obsolescence of GLFW in that context.

Imgui has a rendering backend which allows one to build web applications with Emscripten rendering with WebGPU instead of WebGL. When rendering with WebGPU instead of WebGL, most of GLFW's functionality is no longer required. However, GLFW remains the standard way of processing input for imgui when running on web, building with Emscripten. The version of GLFW shipped with Emscripten is actually a compatibility wrapper around the HTML5 javascript API, so when the imgui_impl_glfw platform backend creates its callbacks to pass data to imgui, it adds another layer of translation and indirection from the underlying API itself, which isn't really necessary.

This platform backend seeks to replace the GLFW backend when building with Emscripten for the web, in situations where rendering with WebGL is not necessary - either when rendering with WebGPU, or other hypothetical rendering backends.

What's added

The proposed imgui_impl_emscripten backend uses Emscripten's HTML5 API to set callbacks directly, to trigger relevant state changes in imgui:

  • Keyboard input
  • Window resizing
  • Cursor position
  • Cursor enters and leaves the window
  • Application focus
  • Browser cursors (native browser cursor changes using a cut-down version of my emscripten-browser-cursor library)

What is omitted

  • Anything render-related. You would typically use this alongside a rendering backend like imgui_impl_wgpu.
  • Touch event support. At the moment I don't have a mobile device with touch support capable of running a version of any browser that supports WebGPU on mobile devices, so this isn't something I can currently test. I'll aim to add this as support for WebGPU develops.
  • Gamepad support. This is by design; any application that wants to pass input to imgui with a gamepad is certainly also going to want to process gamepad input for its own purposes, so processing this input twice is just going to add inefficiency. Additionally, every application will want different ways to handle deadzones, saturation, analogue input curves, and selecting one out of multiple gamepads for input at any given time. Instead of attempting to handle any of that in this backend, an external example is provided for how to use the Emscripten HTML5 gamepad API to collect both in-game events and pass controls to imgui: https://github.com/Armchair-Software/webgpu-demo2/blob/master/main.cpp#L113

Demo

@ocornut
Copy link
Owner

ocornut commented Nov 26, 2024

Thank you Eugene for the PR!

I intuitively agree that a raw Emscripten port may be desirable, but I am not sure we are aligned on the motives.
Some thoughts:

  • GLFW works well with WGPU.
  • There is a contrib GLFW port for Emscripten https://github.com/pongasoft/emscripten-glfw that doesn't have many of the issues the default port has (see link).
  • SDL generally works better with Emscripten than the default GLFW port, so don't agree with the premise that "GLFW remains the standard way of processing input for imgui when running on web".
  • "it adds another layer of translation and indirection from the underlying API itself, which isn't really necessary." it's true that it is not necessary but it is not a meaningful problem IMHO.
  • I am not sure I understand why you suggest that this new backend wouldn't work with WebGL? I believe if we have a raw emscripten backend it should probably support the imgui_impl_opengl backend as well. What is preventing this to happen?

I believe we need to be clear on the benefits.

  • Pros: Being more lightweight is a little bit of benefit.
  • Pros: Being able to more easily experiment with Emscripten specific needs and features before SDL/GLFW can adopt them is an hypothetical benefit.
  • Cons: Having to maintain a new backend for a platform (that happens to a little bit esoteric to me) has a cost.
  • Cons: WebGL not supported? (I believe this may be fixed)

On the submitted code:

  • I would need the code to be written closely in the style of other backends. I can provide more detailed feedback, but right now it is straying away from our coding convention quite a lot. If you can put that work it would likely make merging faster/easier otherwise I will have eventually have a pass.
  • Please note that the repository has a CLA https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#copyright--contributor-license-agreement which appears to be contradicted by your headers. You first would need to decide if you prefer to agree to the CLA or not in order to move forward.

Thanks!

@slowriot
Copy link
Contributor Author

Hey Omar, thanks for the initial review! Your thoughts are all valid, I think there are a couple of misunderstandings though - let me address in-line.

* GLFW works well with WGPU.

Absolutely - in so far as it doesn't not work. What it provides is simply entirely orthogonal to WebGPU. When working on desktop, GLFW creates windows and manages interaction with them, but under Emscripten on the web, none of that applies. When working with WebGL, GLFW is still relevant for creating and managing an GL context. With WebGPU there is no equivalent GLFW functionality (some was recently discussed at glfw/glfw#2333 - tying in WebGPU surface creation - but this is the sum total of interaction GLFW would have with WebGPU).

Don't get me wrong, I love GLFW, I've been working with it for about 12 years now. For writing cross-platform code it can't be beaten. But right now I'm writing single-platform code for the web with Emscripten, and in that situation, all GLFW provides is a compatibility layer - creating windows isn't a concept that exists on the web, and when there's no longer a GL context to manage, all it provides is translation between HTML5 inputs via its own input system. The rationale for this PR is just to close that loop, short-circuiting the need for GLFW in this specific situation entirely.

* There is a contrib GLFW port for Emscripten https://github.com/pongasoft/emscripten-glfw that doesn't have many of the issues the default port has (see link).

Sure. My point is just that the whole weight of GLFW isn't always necessary.

* SDL generally works better with Emscripten than the default GLFW port, so don't agree with the premise that "GLFW remains the standard way of processing input for imgui when running on web".

Sure, absolutely - it was not my intention to make any statements or implications about GLFW vs SDL or anything else. This is intended to be a much lighter weight alternative to those full-service platforms.

* "it adds another layer of translation and indirection from the underlying API itself, which isn't really necessary." it's true that it is not necessary but it is not a meaningful problem IMHO.

I agree it's not a big deal. But some developers, myself included, like to squeeze every drop of performance out of a given frame. For example, the ImGui_ImplGlfw_NewFrame function does quite a lot of work, none of which is actually needed in a callback-driven Emscripten environment - all of this can be omitted in this version.

* I am not sure I understand why you suggest that this new backend wouldn't work with WebGL? I believe if we have a raw emscripten backend it should probably support the imgui_impl_opengl backend as well. What is preventing this to happen?

I didn't mean to imply that this backend wouldn't work with WebGL - I don't think I said anything like that in my description, I'd be happy to revise any misleading wording if you point it out! It just doesn't handle rendering at all. Other rendering backends will interoperate very well with it. It's just that in that situation, GLFW makes (more) sense, because it provides all of the GL context management glue already. Before recently adopting WebGPU, my Emscripten projects all use GLFW for WebGL rendering, and this new backend is my migration path to WebGPU where I no longer need GLFW. I'm not trying to prescribe any specific way of doing things for other developers, this is just something that I wrote for my own utility, that I feel might be useful for others too.

I believe we need to be clear on the benefits.

* Pros: Being more lightweight is a little bit of benefit.

* Pros: Being able to more easily experiment with Emscripten specific needs and features before SDL/GLFW can adopt them is an hypothetical benefit.

I definitely wouldn't sell it on that basis! The Emscripten features are well established where they're used in those platforms already. But WebGPU is a new way of doing things from a rendering standpoint, which only really makes sense on the web. Whereas Emscripten allows you to write classic OpenGL and execute as WebGL, so a project can support Emscripten as well as native platforms with the same code; with WebGPU on Emscripten you're really going to be writing for the web only. I know there are desktop implementations of WebGPU as well, but the real benefit for me is being able to write code once and have it run on all platforms that support a browser, with near-native performance, and using just one set of APIs without any translation layers.

* Cons: Having to maintain a new backend for a platform (that happens to a little bit esoteric to me) has a cost.

Agreed. But Emscripten is already supported in several backends such as those for GLFW, the result sometimes producing a complex forest of #ifdefs (such as https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_glfw.cpp#L572 downwards) - from a maintenance standpoint, I feel single-platform, single-purpose backends tend to be cleaner and easier to maintain.

* Cons: WebGL not supported? (I believe this may be fixed)

As above, I think this is a misunderstanding. This backend simply doesn't attempt to do anything rendering-related.

On the submitted code:

* I would need the code to be written closely in the style of other backends. I can provide more detailed feedback, but right now it is straying away from our coding convention quite a lot. If you can put that work it would likely make merging faster/easier otherwise I will have eventually have a pass.

Absolutely, I expected that - please let me know if there's a style guide somewhere that I've missed, or if you have specific feedback. No problem to adapt this however is required.

* Please note that the repository has a CLA https://github.com/ocornut/imgui/blob/master/docs/CONTRIBUTING.md#copyright--contributor-license-agreement which appears to be contradicted by your headers. You first would need to decide if you prefer to agree to the CLA or not in order to move forward.

Yep, no problem of course, all transferable rights are hereby granted to the project maintainer as per the CLA. I didn't see any copyright statements in the existing backend source, so please let me know how you'd like this to be rephrased, or if you just require it to be deleted entirely.

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

Successfully merging this pull request may close these issues.

2 participants