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

Bevy should recover from WebGL Context Lost or WebGPU Device Lost #10456

Open
Maximetinu opened this issue Nov 8, 2023 · 2 comments · May be fixed by #12690
Open

Bevy should recover from WebGL Context Lost or WebGPU Device Lost #10456

Maximetinu opened this issue Nov 8, 2023 · 2 comments · May be fixed by #12690
Labels
A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior O-Web Specific to web (WASM) builds O-WebGL2 Specific to the WebGL2 render API O-WebGPU Specific to the WebGPU render API P-Crash A sudden unexpected crash

Comments

@Maximetinu
Copy link
Contributor

Maximetinu commented Nov 8, 2023

My experience described below is based on WebGL2, but apparently this is the equivalent in WebGPU: losing a device https://developer.mozilla.org/en-US/docs/Web/API/GPUDevice/lost

[...] devices can be lost at any time after creation for a variety of reasons (such as browser resource management or driver updates)

What problem does this solve or what need does it fill?

According to this MDN web spec: https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/isContextLost#usage_notes

There are several reasons why a WebGL context may be lost, making it necessary to re-establish the context before resuming rendering. Examples include:

  • Two or more pages are using the GPU, but together place too high a demand on the GPU, so the browser tells the two contexts that they've lost the connection, then selects one of the two to restore access for.
  • The user's computer has multiple graphics processors (such as a laptop with both mobile and desktop class GPUs, the former used primarily when on battery power), and the user or system decides to switch GPUs. In this case, all contexts are lost, then restored after switching GPUs.
  • Another page running in the user's browser performs an operation using the GPU that takes too long, causing the browser to decide to reset the GPU in order to break the stall. This would cause every WebGL context to be lost throughout the entire browser.
  • The user updates their graphics driver on an operating system that allows graphics drivers to be updated without restarting the system.

There can be natural, expected, reasons why a graphic context in an HTML canvas can be lost, so a web-app built on top of Bevy should be able to handle these scenarios without crashing.

Other web game engines, like Babylon.js, support automatically recovering from a context lost: see here for a live example of that

In the case of Bevy, in any of the examples at version 0.11.3 targeting wasm, running on WebGL2, if we simulate a context lost like that, the whole Bevy app will crash. This is an example running move_sprite.rs:

image

What solution would you like?

Ideally, when the context is lost, Bevy should try to restore it instead of crashing. And, if it succeeds, Bevy should re-create all the previous graphic resources to the GPU (because, when the context is lost, all the graphic resources are lost too).

This seems to be what Babylon.js is doing.

What alternative(s) have you considered?

Since re-creating all the resources is a hard task, a good enough solution, at least for my use case, would be to halt all the rendering, to at least prevent the app from crashing, even if it has to keep running without graphics. This is ideal in my scenario as a fallback emergency mode to not kick the user off in the middle of a work session from other features happening on the web, that depend on the Bevy app running on the HTML canvas. As long as the simulation keeps running, they'd be fine until they're able to refresh the tab and regain the graphics.

So, a valid alternative could be to opt-in to not crash upon graphic context lost, and instead disable all the rendering. However, disabling the rendering may be coupled with this ongoing PR about separating tick updates and redraws

Additional context

Since I'm not familiar with WebGPU, I don't know how this all applies to it, or if it has any sense of losing/recovering context like WebGL2 have.

This mainly applies to WebGL2. I have seen comments suggesting that, even if in theory the graphics context should be restorable and re-creatable, in practice it isn't most of the times, requiring a full reload of the tab, and hence a full reload of the app. So, maybe WebGPU has a better way to handle this.

In my experience, I didn't even considered worth it implementing a full recover. But halting the graphics to not crash the whole app is a more than good alternative in most of the cases.

This conversation started in this Discord message.

@Maximetinu Maximetinu added C-Enhancement A new feature S-Needs-Triage This issue needs to be labelled labels Nov 8, 2023
@Maximetinu Maximetinu changed the title Bevy should recover from WebGL Context Lost Bevy should recover from WebGL Context Lost or WebGPU Device Lost Nov 10, 2023
@nicopap nicopap added C-Bug An unexpected or incorrect behavior O-Web Specific to web (WASM) builds P-Crash A sudden unexpected crash A-Rendering Drawing game state to the screen O-WebGPU Specific to the WebGPU render API O-WebGL2 Specific to the WebGL2 render API and removed C-Enhancement A new feature S-Needs-Triage This issue needs to be labelled labels Nov 10, 2023
@Maximetinu
Copy link
Contributor Author

Update, I have some good news:

I said above:

My experience described below is based on WebGL2, but apparently this is the equivalent in WebGPU: losing a device https://developer.mozilla.org/en-US/docs/Web/API/GPUDevice/lost

Since the method I was using to simulate a GL context lost was the same as Babylon.js:

document.querySelector("#my_canvas_id").getContext('webgl2').getExtension("WEBGL_lose_context").loseContext()

I was never able to check if webgpu was crashing as well when losing access to the GPU, because webgpu didn't have such extension to simulate a context loss.

I have now discovered a new way to simulate it, which works in Google Chrome: to write chrome://gpucrash/ on the address bar and press enter.

If I do that in a WebGL2 example, it crashes as usual.

But, here comes the news: if I do that in a WebGPU example, it works, the app just keep working as usual, the systems keeps running, the browser just prints a warning like GPU connection lost and the app shows a black canvas, but everything keeps working.

You can check this at the example https://bevyengine.org/examples-webgpu/Application/logs/ and see how the logs keep showing even after the GPU crash 🎉

@Maximetinu
Copy link
Contributor Author

This makes me wonder: if wgpu (or webgpu itself) is already handling such event... Wouldn't it be wgpu crate responsibility to handle WebGL2 context losses in the same way as well, to have the same functionality between the 2 web rendering backends? 🤔

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-Web Specific to web (WASM) builds O-WebGL2 Specific to the WebGL2 render API O-WebGPU Specific to the WebGPU render API P-Crash A sudden unexpected crash
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants