Skip to content

Conversation

alextechcc
Copy link

NOTE: This is a DRAFT and is based off of several WIP branches/pull requests, including one for WGPU. The commits are ugly, the code is ugly. I hope this can serve as a way to discuss if/how to get a raw display handle over to wgpu when initializing the wgpu instance.

Objective

WGPU GL appears to be completely broken on Wayland because if you enumerate adapters before creating a surface (which passes a wl_display handle from winit to the instance) - the GLES backend is forced to create a dummy display connection (https://github.com/gfx-rs/wgpu/blob/trunk/wgpu-hal/src/gles/egl.rs#L901) - and these handles and all resources created with each-other are not compatible, so it is forced to reinitialize its contexts when it is passed the handle (https://github.com/gfx-rs/wgpu/blob/trunk/wgpu-hal/src/gles/egl.rs#L1057), it does this in an unsound way which terminates GL sessions and other ugly side effects.

There is a WIP gfx-rs/wgpu#8012 to allow passing a RawDisplayHandle to a wgpu instance when constructing it - sidestepping all the ugly context re-initialization - making sure that the contexts are all valid.

Currently bevy does not seem to be set up to get a valid surface before creating the wgpu instance or requesting adapters. The order seems to be:

  1. WinitPlugin is added, build() creates the event loop immediately (https://github.com/bevyengine/bevy/blob/main/crates/bevy_winit/src/lib.rs#L136), but does not create windows yet. At this point, it creates a DisplayHandleWrapper which would be perfect to throw into the wgpu instance, but unfortunately bevy_winit depends on bevy_render and not the other way around, so it is not possible for it to access this resource.
  2. RenderPlugin is added, build() queries for a window that already exists to create a surface for, and to use the surface as a compatible_surface to pass to wgpu. I don't see how this could happen. It misses this, and thus initializes wgpu, doesn't make any surfaces or pass compatible surfaces. https://github.com/bevyengine/bevy/blob/main/crates/bevy_render/src/lib.rs#L384
  3. It then enumerates adapters, locking us into the buggy path that will create BadDisplay.
  4. about_to_wait() is called by winit, which creates windows
    create_windows(event_loop, create_window.get_mut(self.world_mut()));
    - but I believe this can only happen in the WinitAppRunner - after the app is started and running the event loop and gets a resumed event from Winit. At this point it's far too late to use this window handle.

So, the goal of this PR is to figure out a way to throw a RawDisplayHandle over to wgpu when initializing the instance so that the egl backend can function.

Solution

Testing

  • This works on my AMDGPU machine when running any example: WGPU_BACKEND=gl cargo run --features wayland,bevy_render/decoupled_naga --example 2d_gizmos

@alextechcc alextechcc marked this pull request as draft July 27, 2025 22:35
@alice-i-cecile alice-i-cecile added C-Bug An unexpected or incorrect behavior A-Rendering Drawing game state to the screen O-OpenGL Specific to the OpenGL render API labels Jul 27, 2025
@alice-i-cecile alice-i-cecile added the S-Needs-Design This issue requires design work to think about how it would best be accomplished label Jul 27, 2025
@alextechcc alextechcc closed this Aug 7, 2025
@github-project-automation github-project-automation bot moved this to Done in Rendering Aug 7, 2025
@alextechcc
Copy link
Author

Closing due to #20358

@alextechcc alextechcc deleted the myfork/fix_opengl_baddisplay branch August 7, 2025 23:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior O-OpenGL Specific to the OpenGL render API S-Needs-Design This issue requires design work to think about how it would best be accomplished
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

REGRESSION: wgpu panic BadDisplay after winit 0.30 on Wayland OpenGL
3 participants