Restore Lost WebGL Context After Hardware Reset
Handling WebGL context loss is an essential requirement for building resilient web graphics applications. When a GPU experiences a hardware reset, driver update, or resource exhaustion, the browser discards the WebGL context and wipes all stored GPU resources. Restoring the context involves capturing context-loss events, preventing the browser's default abort behavior, reinitializing rendering pipelines, and reloading all textures, buffers, and shaders once the hardware becomes available again.
1. Intercept the Context Lost Event
When the graphics card resets, the canvas fires the
webglcontextlost event. By default, browsers treat this
event as fatal and will not attempt to restore the context. To allow
recovery, you must add an event listener and call
event.preventDefault().
At this stage, you must also stop your render loop to prevent your application from issuing commands to an invalid context.
const canvas = document.getElementById("glcanvas");
let animationFrameId;
canvas.addEventListener("webglcontextlost", (event) => {
event.preventDefault();
cancelAnimationFrame(animationFrameId);
console.warn("WebGL context lost. Pausing rendering...");
}, false);2. Listen for Context Restoration
Once the operating system and GPU stabilize, the browser creates a
new underlying graphics context and dispatches the
webglcontextrestored event to the canvas.
Attach an event listener for webglcontextrestored to
trigger your resource reconstruction logic:
canvas.addEventListener("webglcontextrestored", () => {
console.log("WebGL context restored. Rebuilding resources...");
reinitializeWebGL();
}, false);3. Re-create All GPU Resources
A restored WebGL context is completely blank. The original
WebGLRenderingContext or
WebGL2RenderingContext instance remains the same JavaScript
reference, but all previously allocated WebGL objects are invalid.
Your initialization routine must explicitly re-execute the following tasks:
- Shaders and Programs: Recompile vertex and fragment shaders, attach them to new program objects, and re-link them.
- Uniform Locations: Query and cache all uniform and attribute locations from the newly linked programs.
- Buffers: Generate new vertex buffer objects (VBOs) and index buffers (IBOs), binding them and repopulating them with your geometry data.
- Textures: Recreate texture objects, set texture parameters (filtering, wrapping), and re-upload image data to the GPU.
- Framebuffers and Renderbuffers: Reallocate any off-screen render targets and depth/stencil buffers.
- State Settings: Re-enable required states, such as
depth testing (
gl.DEPTH_TEST), blending modes, cull face settings, and clear colors.
4. Restart the Render Loop
After all assets and states are fully loaded back into the GPU, resume the application's render loop.
function reinitializeWebGL() {
const gl = canvas.getContext("webgl2") || canvas.getContext("webgl");
initShaders(gl);
initBuffers(gl);
initTextures(gl);
// Restart animation loop
render();
}
function render() {
drawScene();
animationFrameId = requestAnimationFrame(render);
}Testing the Restoration Workflow
You can simulate hardware resets without crashing your system by
using the WEBGL_lose_context extension. This extension
allows you to programmatically trigger context loss and restoration to
ensure your application recovers smoothly:
const ext = gl.getExtension("WEBGL_lose_context");
// Simulate context loss
ext.loseContext();
// Simulate recovery after 2 seconds
setTimeout(() => {
ext.restoreContext();
}, 2000);