Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to free and garbage collect a WebGL context?

I'm developing a WebGL application for web and mobile. I often use hard-refreshs to test the results of my WebGL implementation. After a view tries, I get the error:

Error: WebGL: Exceeded 16 live WebGL contexts for this principal, losing the least recently used one.

This does not appear on a fresh started browser, but after refreshing the site multiple times. I guess the WebGL contexts are not finished, released, destroyed, cleaned up, freed correctly.

How can I do this?

Khronos Group created a test suite for freeing and garbage collecting WebGL context here: https://www.khronos.org/registry/webgl/sdk/tests/conformance/context/context-creation-and-destruction.html (Note: This might crash your browser!)

The test runs through with PASS and TEST COMPLETE, so basicly the test does not detect any issues. However, opening the JavaScript console, it reads 33 instances of:

Error: WebGL: Exceeded 16 live WebGL contexts for this principal, losing the least recently used one.

Is this a bug in how WebGL is handled by the browser? Or am I doing anything wrong? I never thought about freeing any WebGL contexts.

I'm using Firefox Developer Edition 48.0a2 and Firefox 46.0.1.

How to free and garbage collect a WebGL context?

like image 843
Afr Avatar asked May 06 '16 12:05

Afr


People also ask

How do I get rid of WebGL context?

Refreshing a webpage should free all resources. There is no official way to dispose of a WebGL context just like there's no official way to dispose an Image or a <video> or pretty much anything else in JavaScript.

Why does WebGL lose context?

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.


1 Answers

I think maybe I misunderstood your question

You say you're doing hard refreshes. Meaning you're pressing refresh in the browser? In that case first I'd disable all extensions and see if the issue is still there. If it is I'd file a bug with mozilla

Otherwise if you are trying to free canvases and create knew ones and hoping for garbage collection well.. here's the answer I wrote before I re-read your question


The short answer is you can't force garbage collection. You'd be better off re-using the same canvases.

There's a solution here to freeing all the data and resetting the canvas

How do I clean up and unload a WebGL canvas context from GPU after use?

In your particular case though are you 100% sure you're not holding on to some reference to the WebGL context or canvas? For example if you do this

canvas.addEventListener('click', function(..) {});

You've just made a canvas that can NEVER be garbage collected. It has an event listener function attached. You have no way to remove that function since you didn't keep a reference to it. You need to remove all listeners as just one example of many ways you might be leaking references.

There's tons of ways to accidentally keep references to HTML elements like the canvas as well as WebGL objects. Keep more than zero references and it will never be garbage collected.

Here's some hints on finding the leaks

On the other hand if it was me I'd try to re-use the canvases. To make sure I freed everything I might call my own creation/deletion functions that track all the resources. Example

var textures = [];
function createTexture(gl) {
  var tex = gl.createTexture();
  textures.push(txt);
}

function deleteTexture(gl, tex) {
  gl.deleteTexture(tex);
  textures.splice(textures.indexOf(tex), 1);
}

Now because I'm tracking all the textures I can easily delete all the remaining ones

while (textures.length) {
  gl.deleteTexture(textures.pop());
}
like image 106
gman Avatar answered Nov 05 '22 06:11

gman