What cause Webgl Context Lost?

When we launch and run PlayCanvas which is under iFrame, it irregularly lost webgl context.

The size of glb file is little bigger than 50mb and the issue occurs most likely on iPad or iOS device.
Sometimes, it occurs on a low performance device. Especially, it occurs when the browser comes back from background mode to foreground

The problem is this issue occurs intermittently and randomly.
I just wonder what causes this issue and how I can prevent it.
Also, I wonders if it’s possible to restore webgl context and reload or rerender the scene.

The context is typically lost when the device goes to sleep and similar, and in most cases that recovers fine.

If you use the prefiltered cubemap for lighting, we have an issue with recovering it, and you should switch to a new type, which uses a 2D texture, which does not have this problem.

In the cubemap prefiltering dialog, delete the data first, and prefilter again, just don’t click on the "Generate legacy cubemap’.

1 Like

Are you talking about “DDS” file?


See this comment for more details perhaps: Move `Texture#getDds` out of the engine · Issue #3960 · playcanvas/engine · GitHub

is there any way to detect “webgl context lost”?
According to the engine code, “devicelost” event occurs when the context is lost.

And, “devicerestored” event is called when the context is restored.

However, it doesn’t work with a custom script.

If it’s possible, I like to know how manually restore the cubemap.

Do you have to use the cubemap? Switching to the new approach is easy and all is handled.

yes, I tried. However, its render result is different from the old DDS.

What happens if you prefilter to the cubemap again? Is that different to the old dds as well?


Below is the material with old DDS cubemap

This is the result with the new cubemap with png.

In our case, we use skybox on the scene level. Also, applied material level skybox.

It looks like the material level skybox is ignored.

I’ve found it from standard-material.js > updateEnvUniforms function.

Hi @sooyong_Kim ,

Are you able to add me to the project so I can take a look? Otherwise if you can create a cut-down repro I can use that too. I’m user slimbuck.


Please take a look at this PR.

1 Like

Hey, it seems we are getting a similar issue when rendering a dynamic cubemap and extracting an environmental map on the fly. Basically very similar to this example:


Latest report was it happens on an Intel Mac and yes, when running in an iframe. Any idea how to work around this @mvaligursky?

What exactly is the problem @Leonidas ? Missing ambient (image) lighting when the device is lost?
If as you say this is stored in dynamically generated texture, you need to re-generate it when the context is restored. The device fires this, which should tell you to update your render targets that are not updated every frame: this.fire('devicerestored');

1 Like

Hmm, now that I think of it, it may not be the exact same issue but related to the generateAtlas method running when requesting the map.

Here is the error that leads to a full page reload (and afterwards a context has been lost etc). Is there a readPixels involved in this?

WebGL-0x12800902900]GL Driver Message (OpenGL, Performance, GL_CLOSE_PATH_NV, High): GPU stall due to ReadPixels (this message will no longer repeat)

It happens when running under an iframe on an Intel Mac, on Google Chrome (latest version).

We don’t use readPixels inside generateAtlas functionality. By looking at the code, only shFromCubemap functions uses it, which we don’t internally call at all.

No idea about that error message at all, really strange. No other errors before this, nor the code stopped i n the debugger is similar I assume?

Yeah, we are trying to reproduce in our own environment, hopefully we will be able and get more insight.

Thanks for the info Martin, much appreciated as always!

1 Like


I found this issue from the apple forum.
Is it related to this issue?

I think I found the root cause in my case.

I called scene._resetSky() while initializing scene.
(Actually it’s called from one of the custom scripts)

I moved the calling action after the system level ‘postInitialize’ event is fired.