rdkcentral / Lightning

Lightning - The WPE UI Framework for developing Apps and UX
Apache License 2.0
190 stars 109 forks source link

Handle loss of WebGL context #469

Open LMestre14 opened 1 year ago

LMestre14 commented 1 year ago

When we run our app in low powered devices we've had issues with missing context on WebGL, and when that happens the function createTexture for example ends up returning null instead of a texture. This will cause a crash on WebGLRenderer - in uploadTextureSource, this is one of the examples where this might happen. Since glTexture is null, trying to set params on it results in a Cannot set property 'params' of null error.

By looking up on WebGL documentation there are ways to listen to when the context is lost and recovered (event listener webglcontextlost and webglcontextrestored)

And according to the WebGL wiki we should prevent putting attributes on WebGL resource objects when the context is loss

Note: The way I was able to test this out was by using gl.getExtension("WEBGL_lose_context").loseContext(); to simulate the loss of context.

uguraslan commented 1 year ago

Hey @LMestre14, thank you for bringing this issue to our attention and for providing a detailed explanation of the problem you're encountering. We understand and acknowledge the issues caused by missing context in WebGL due to properties being directly set to the WebGL object. We also appreciate the time you have taken to investigate this matter.

After discussing the issue with our development team, we realised that this is a challenging issue to fix because it requires substantial changes to critical parts of the codebase. While we recognise the importance of this issue, unfortunately, we are currently unable to dedicate the necessary time and effort to develop and thoroughly test a fix.

However, we will be adding this issue to our backlog, and if there's an opportunity for someone on our team to address it in the future, we'll definitely consider it.

guilhermesimoes commented 1 year ago

Yeah, we figured this would be very hard to fix. The way we are now handling this issue on Peacock is to add an event listener for webglcontextlost and then reload the app when it happens. Perhaps this issue and this "solution" of ours could be added to Lightning's documentation so that others are also aware.

In any case, thank you @uguraslan.

erikhaandrikman commented 1 year ago

Seems like a fair suggestion to add to the docs. We could also consider adding this logic to the core so users can enable it by simply attaching a listener to a contextLost event. This approach would allow us to manage the lost of a WebGLRenderingContext instance on a per-platform basis.

guilhermesimoes commented 1 year ago

Just for awareness, here's our final solution:

stage.getCanvas().addEventListener('webglcontextlost', (event) => {
  event.preventDefault();

  // Stop Lightning loop so that it doesn't error out by trying to access a property of a null texture
  stage.stop();

  Logger.error('WebGL context lost, reloading app');

  window.location.reload();
});

Notice that we're calling: https://github.com/rdkcentral/Lightning/blob/b17b3a5f09b5366e33755091e7d7e1da364394bd/src/tree/Stage.mjs#L228-L230 in order to avoid Lightning from crashing here: https://github.com/rdkcentral/Lightning/blob/b17b3a5f09b5366e33755091e7d7e1da364394bd/src/renderer/webgl/WebGLRenderer.mjs#L91 And that's it. It ended up being pretty simple on our side, but I imagine properly solving this will be a huge effort.

HazAnwar commented 1 month ago

Hi @uguraslan, just to provide a quick/small update on this as it appears there are new findings related to this issue

It appears that as on v123 Chromium, there is a change that cleans up the GPU when the app has been backgrounded for more than 5 seconds on devices where there is less than 1GB of physical/hardware RAM (it is not based on available memory) which leads to the WebGL being lost on all lower-end devices using newer versions of Chromium

We're seeing this issue is quite prevalent on Android TV and Fire TV already as they both normally use the latest and greatest versions of Chromium and I suspect it will only get worse as more devices/platforms use newer versions of Chromium

I believe you should be able to replicate this almost 100% of the time on a virtual machine by limiting the available RAM and running v123 or above of Chrome/Chromium

wouterlucas commented 1 month ago

Hi @uguraslan, just to provide a quick/small update on this as it appears there are new findings related to this issue

It appears that as on v123 Chromium, there is a change that cleans up the GPU when the app has been backgrounded for more than 5 seconds on devices where there is less than 1GB of physical/hardware RAM (it is not based on available memory) which leads to the WebGL being lost on all lower-end devices using newer versions of Chromium

We're seeing this issue is quite prevalent on Android TV and Fire TV already as they both normally use the latest and greatest versions of Chromium and I suspect it will only get worse as more devices/platforms use newer versions of Chromium

I believe you should be able to replicate this almost 100% of the time on a virtual machine by limiting the available RAM and running v123 or above of Chrome/Chromium

Super helpful information, thank you! Though solving this in L2 might be a bit of an undertaking. I've copied the issue in the Lightning 3 issue tracker, which we can experiment with a L3 based solution as its much easier to iterate/experiment with a L3 based solution for this (and we need it anyway). Once we have that covered, we can re-evaluate what it would take to backport or take that experience to L3 and apply it here.

HazAnwar commented 1 month ago

Amazon have raised a bug report (on our behalf) with Google/Chromium as well/FYI

https://issues.chromium.org/issues/366045334