mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 17:43:47 +00:00
perf: fix critical WebGL GPU resource leaks in Aurora
- Fix isWebglAvailable() leaking a full WebGL context on every check by replacing OGL Renderer with raw canvas.getContext() + loseContext() - Add visibilitychange listener to fully stop rAF loop when tab hidden and restart on visibility restore (was running 24/7 in background) - Properly destroy WebGL context on unmount via WEBGL_lose_context extension and gl.deleteProgram() (was only nulling JS refs) - Reduce target FPS from 20 to 10 (slow gradient, visually identical)
This commit is contained in:
@@ -132,12 +132,13 @@ let _webglAvailable: boolean | null = null;
|
|||||||
function isWebglAvailable(): boolean {
|
function isWebglAvailable(): boolean {
|
||||||
if (_webglAvailable === null) {
|
if (_webglAvailable === null) {
|
||||||
try {
|
try {
|
||||||
const renderer = new Renderer({
|
const canvas = document.createElement('canvas');
|
||||||
alpha: true,
|
const gl = canvas.getContext('webgl2') || canvas.getContext('webgl');
|
||||||
antialias: false,
|
_webglAvailable = !!gl;
|
||||||
powerPreference: 'low-power',
|
if (gl) {
|
||||||
});
|
const loseCtx = gl.getExtension('WEBGL_lose_context');
|
||||||
_webglAvailable = !!renderer.gl;
|
if (loseCtx) loseCtx.loseContext();
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
_webglAvailable = false;
|
_webglAvailable = false;
|
||||||
}
|
}
|
||||||
@@ -258,15 +259,16 @@ function AuroraImpl() {
|
|||||||
resize();
|
resize();
|
||||||
|
|
||||||
let lastTime = 0;
|
let lastTime = 0;
|
||||||
const targetFPS = 20;
|
const targetFPS = 10;
|
||||||
const frameInterval = 1000 / targetFPS;
|
const frameInterval = 1000 / targetFPS;
|
||||||
const speed = 0.3;
|
const speed = 0.3;
|
||||||
|
|
||||||
function animate(currentTime: number) {
|
function animate(currentTime: number) {
|
||||||
animationFrameRef.current = requestAnimationFrame(animate);
|
|
||||||
|
|
||||||
const delta = currentTime - lastTime;
|
const delta = currentTime - lastTime;
|
||||||
if (delta < frameInterval) return;
|
if (delta < frameInterval) {
|
||||||
|
animationFrameRef.current = requestAnimationFrame(animate);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
lastTime = currentTime - (delta % frameInterval);
|
lastTime = currentTime - (delta % frameInterval);
|
||||||
|
|
||||||
@@ -274,15 +276,45 @@ function AuroraImpl() {
|
|||||||
programRef.current.uniforms.uTime.value += speed * 0.01;
|
programRef.current.uniforms.uTime.value += speed * 0.01;
|
||||||
rendererRef.current.render({ scene: mesh });
|
rendererRef.current.render({ scene: mesh });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
animationFrameRef.current = requestAnimationFrame(animate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleVisibilityChange() {
|
||||||
|
if (document.hidden) {
|
||||||
|
cancelAnimationFrame(animationFrameRef.current);
|
||||||
|
animationFrameRef.current = 0;
|
||||||
|
} else {
|
||||||
|
lastTime = 0;
|
||||||
|
animationFrameRef.current = requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||||
|
|
||||||
animationFrameRef.current = requestAnimationFrame(animate);
|
animationFrameRef.current = requestAnimationFrame(animate);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||||
window.removeEventListener('resize', resize);
|
window.removeEventListener('resize', resize);
|
||||||
cancelAnimationFrame(animationFrameRef.current);
|
cancelAnimationFrame(animationFrameRef.current);
|
||||||
if (rendererRef.current && container.contains(rendererRef.current.gl.canvas)) {
|
|
||||||
container.removeChild(rendererRef.current.gl.canvas);
|
if (rendererRef.current) {
|
||||||
|
const glCtx = rendererRef.current.gl;
|
||||||
|
|
||||||
|
// Delete GPU resources
|
||||||
|
if (programRef.current) {
|
||||||
|
glCtx.deleteProgram(programRef.current.program);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force-release the WebGL context
|
||||||
|
const loseCtx = glCtx.getExtension('WEBGL_lose_context');
|
||||||
|
if (loseCtx) loseCtx.loseContext();
|
||||||
|
|
||||||
|
if (container.contains(glCtx.canvas)) {
|
||||||
|
container.removeChild(glCtx.canvas);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rendererRef.current = null;
|
rendererRef.current = null;
|
||||||
programRef.current = null;
|
programRef.current = null;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user