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

Eframe : Support for experimental webGPU backend #2137

Closed
WeiPhil opened this issue Oct 11, 2022 · 13 comments · Fixed by #2945
Closed

Eframe : Support for experimental webGPU backend #2137

WeiPhil opened this issue Oct 11, 2022 · 13 comments · Fixed by #2945

Comments

@WeiPhil
Copy link

WeiPhil commented Oct 11, 2022

Hi,
Recently quite a lot of development has been made on the webGPU side of things on egui (yay!), but right now, only the webgl2 backend seems supported on the web. I know this is probably very early, but I would be interested in getting compute shaders in the pipeline, which can only be done with webGPU. There is a great introduction to webGPU compute shaders here.
I spent some time trying to get a working webGPU backend (diregarding any compute pipeline for now) with Eframe but couldn't manage to get it to work.

First of all, is this something that would be relevant for Egui ? And has anybody tried something similar with any success? (Maybe @Wumpf which worked on #2107 ?)
Best,
Philippe

@Wumpf
Copy link
Collaborator

Wumpf commented Oct 11, 2022

switching from webgl to webgpu is actually trivial now - just change this field here https://github.com/emilk/egui/blob/master/crates/eframe/src/web/web_painter_wgpu.rs#L36
That said, I didn't get it to work so far because one needs to essentially align the used wgpu version with the browser canary/beta/nightly. The issue is that WebGPU is still evolving and sometimes either browser implementations are ahead or wgpu is behind. Since wgpu implements WebGPU for it should be just a matter of downgrading wgpu far enough to the current Firefox Nightly, but in practice that means that some places in the code needs to be patched up.

That said, what needs to be done is to either patch through the backend setting into the WebOptions struct or just be clever about selecting the backend (probably best to detect if wgpu was compiled with webgl feature or not and then decide)

@WeiPhil
Copy link
Author

WeiPhil commented Oct 11, 2022

I'm not sure if my issue lies in getting the right combination. I used the latest version of canary and wgpu but I got some panicked at 'condvar wait not supported', library/std/src/sys/wasm/../unsupported/locks/condvar.rs:21:9
I'm not sure if this means wasm compilation still has unimplemented bits, in which case maybe there is some additional change to egui that would need to be added to support this.

@Wumpf
Copy link
Collaborator

Wumpf commented Oct 11, 2022

hmm that rings a bell, but don't recall where I saw this recently in this context. It's definitely not about the pecularities of WebGPU versions, but something on the codepath hits a lock when it really shouldn't.

Can you run with RUST_BACKTRACE=1 and post the full callstack? Also, can you confirm that the same thing works with wgpu targeting webgl?

@WeiPhil
Copy link
Author

WeiPhil commented Oct 11, 2022

I think I see the issue, my current wasm code uses pollster::block_on which I understand is not yet supported (like most async rust stuff). So my question probably turns into a very beginner question...
I used the eframe_template to get my app up and running but it looks like the construct to start a web page with trunk is different to what is suggested in eframe's documentation.

My current main looks like this :

#[cfg(target_arch = "wasm32")]
fn main() {
    // Make sure panics are logged using `console.error`.
    console_error_panic_hook::set_once();

    // Redirect tracing to console.log and friends:
    tracing_wasm::set_as_global_default();
    let web_options = eframe::WebOptions::default();
    // web_options.renderer = eframe::Renderer::Wgpu;
    pollster::block_on(eframe::start_web(
        "the_canvas_id", // hardcode it
        web_options,
        Box::new(|cc| Box::new(Custom3d::new(cc).unwrap())),
    ))
    .ok();
}

How would one adapt this to serve with trunk but correctly handle the async result?

@Wumpf
Copy link
Collaborator

Wumpf commented Oct 12, 2022

ah, yes that's exactly what I hit as well recently! In cases like this one needs to pass control back to the browser. This is achieved by making application entry point itself async. In the egui demo that's done here https://github.com/emilk/egui/blob/master/crates/egui_demo_app/src/lib.rs#L84, i.e. as described in the documentation you linked.
Arguably eframe_template is wrong there and needs fixup

@WeiPhil
Copy link
Author

WeiPhil commented Oct 30, 2022

So I managed to get it to work with WebGPU, however, it looks like only the GL backend works in web assembly. Changing the line at https://github.com/emilk/egui/blob/master/crates/eframe/src/web/web_painter_wgpu.rs#L36 to use wgpu::Backends::all() only works if the limits are set to wgpu::Limits::downlevel_webgl2_defaults(). Anything less restrictive results in the request_device function failing with a Requesting a device failed.
Any idea where this could come from? Note that I'm on an Apple M1, I haven't tried on any other system yet.

@Wumpf
Copy link
Collaborator

Wumpf commented Oct 31, 2022

So I managed to get it to work with WebGPU

The rest of what you're writing sounds like you were still running it on WebGL :). For some reason wgpu figured it can't use a WebGPU wgpu::Device and the remaining WebGL device requires the smaller (downlevel) featuer set.
For enabling WebGPU in your browser you need to follow some steps, see https://github.com/gpuweb/gpuweb/wiki/Implementation-Status - have you tried those already?
Generally, I'd recommend first to try to get some wgpu sample to work on WebGPU and go from there https://github.com/gfx-rs/wgpu/wiki/Running-on-the-Web-with-WebGPU-and-WebGL
As mentioned earlier, depending on Browser and wgpu version, often some WebGPU functions don't match up as the API is still changing. But those errors you should be able to see in the browser console and it's usually fairly clear what's going on.

@WeiPhil
Copy link
Author

WeiPhil commented Oct 31, 2022

Thanks for the quick answer. I did indeed try the boids and cube examples, and they work as expected on my system. As expected, the boids example only works on Chrome Canary, as it uses compute shaders. Which is why I'm puzzled about what is happening. Maybe something related to how the surface is created in eframe? It's the only part that seems handled a bit differently since the wgpu examples use winit to create the window and create a surface.

@Wumpf
Copy link
Collaborator

Wumpf commented Oct 31, 2022

alright then I'm as puzzled as you :). I'll give it another stab myself in the coming days, but can't promise anything.

Meanwhile I'll put in a way to change backend/limits/etc from the outside without touching egui code

@WeiPhil
Copy link
Author

WeiPhil commented Oct 31, 2022

That will probably help a lot for debugging thanks, I'll also check if I can make it work using a different approach for the surface creation.

@WeiPhil
Copy link
Author

WeiPhil commented Oct 31, 2022

Ok I finally found the issue.. eframe's wgpu dependency uses the webgl dependency and therefore the create_surface_from_canvas function would create a WebGL context instead of a WebGPU one. I can remove the wgpu feature in my forked crate but what would be the "cargo way" of removing the webgl feature from my own repository? I'm not sure there is a way to disable nested features in a cargo file.

@emilk
Copy link
Owner

emilk commented Oct 31, 2022

Cargo dependencies are strictly additive. crates/egui-wgpu/Cargo.toml has wgpu = "0.14". If that pulls in a feature you don't want we need to change that to wgpu = { version = "0.14", default-features = false }

@WeiPhil
Copy link
Author

WeiPhil commented Oct 31, 2022

Good to know! I suppose this would be required then in order for people to fully opt into WebGPU support.

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

Successfully merging a pull request may close this issue.

3 participants