-
-
Notifications
You must be signed in to change notification settings - Fork 36k
Closed
Description
Description
For some reason WebGL fallback renderer massively allocates webgl buffers each frame (1000+/sec) and never frees them when using bloom postprocessing.
Eventually this leads to WebGL context crash.
There does not seem to be any indication of leakage inside BloomNode.js as everything looks to be cached.
Measurement is done by trapping the createBuffer / deleteBuffer method usage on WebGL2RenderingContext.prototype.
Reproduction steps
See code.
Also reproducible by changing the renderer to fallback in:
https://threejs.org/examples/?q=bloom#webgpu_postprocessing_bloom
Code
import { vec4, vec3, pass } from 'three/tsl'
import { BoxGeometry, Mesh, MeshBasicMaterial, PerspectiveCamera, Scene, WebGPURenderer, PostProcessing, Color } from 'three/webgpu'
import { bloom } from 'three/addons/tsl/display/BloomNode.js';
const usage = new Map();
window["$usage"] = usage;
function incUsage(name) {
usage.set(name, (usage.get(name) || 0) + 1);
}
function decUsage(name) {
usage.set(name, (usage.get(name) || 0) - 1);
}
function overrideFunc(func, action) {
const orig = func[0][func[1]];
func[0][func[1]] = function(...args) {
action();
return orig.apply(this, args);
}
}
function trapUsage(name, createFunc, deleteFunc) {
overrideFunc(createFunc, () => incUsage(name));
overrideFunc(deleteFunc, () => decUsage(name));
}
const obj = WebGL2RenderingContext.prototype;
trapUsage('buffer', [obj, 'createBuffer'], [obj, 'deleteBuffer']);
const renderer = new WebGPURenderer({ forceWebGL: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const scene = new Scene();
const camera = new PerspectiveCamera(50, window.innerWidth / window.innerHeight);
camera.position.set(3, 3, 3);
camera.lookAt(0, 0, 0);
const geometry = new BoxGeometry();
const material = new MeshBasicMaterial({ color: new Color(0, 1, 1, 1) });
const mesh = new Mesh(geometry, material)
scene.add(mesh)
const postProcessing = new PostProcessing(renderer);
const scenePass = pass(scene, camera);
const scenePassColor = scenePass.getTextureNode('output');
const bloomPass = bloom(scenePassColor);
bloomPass.threshold.value = 0;
bloomPass.strength.value = 2;
bloomPass.radius.value = 0;
postProcessing.outputNode = scenePassColor.add(bloomPass);
//postProcessing.outputNode = scenePassColor;
renderer.setAnimationLoop(() => {
postProcessing.render(scene, camera)
});
Live example
N/A
Screenshots
No response
Version
r179
Device
No response
Browser
Chrome
OS
No response