From cbe5103f170809dbca2d67138ff2a87ab24c52a2 Mon Sep 17 00:00:00 2001 From: Jack Gallant Date: Mon, 1 Jun 2026 09:57:07 -0700 Subject: [PATCH] webgl: fix ROI/sulci/label overlay toggles racing the texture bake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SVG overlay (ROI boundaries, sulci, labels) is re-baked into a GPU texture asynchronously in SVGOverlay.update(): svg.toDataURL() -> Image -> onload -> new THREE.Texture -> dispatch "update", which the viewer commits to uniforms.overlay.value. There was no sequencing guard, so toggling layers in quick succession started several bakes concurrently that could finish out of order. The last bake to *resolve* (not the last one *requested*) won, leaving a stale overlay texture that disagreed with the checkbox state — the intermittent "switches don't take effect / buffering" bug seen across the make_static viewers. Tag each bake with a per-overlay generation id and discard any bake whose generation is no longer current, so only the most recent toggle's texture is ever committed. Also drops a stray console.log that fired on every update. Co-Authored-By: Claude Opus 4.8 --- cortex/webgl/resources/js/svgoverlay.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cortex/webgl/resources/js/svgoverlay.js b/cortex/webgl/resources/js/svgoverlay.js index db33a0367..bcf951a28 100644 --- a/cortex/webgl/resources/js/svgoverlay.js +++ b/cortex/webgl/resources/js/svgoverlay.js @@ -114,11 +114,17 @@ var svgoverlay = (function(module) { this.svg.setAttribute("height", this.height); }, module.SVGOverlay.prototype.update = function() { - console.log("Updating overlay!"); + // Re-bake the SVG overlay into a GPU texture asynchronously (toDataURL -> Image.onload). + // Rapid layer toggles (ROIs / sulci / labels) can kick off several bakes that finish out + // of order, leaving a stale texture on the surface that disagrees with the switch state. + // Tag each bake with a generation id and commit only the most recent one. + var gen = (this._updateGen = (this._updateGen || 0) + 1); this.svg.toDataURL("image/png", {renderer:"native", callback:function(dataurl) { var img = new Image(); //img.src = dataurl; img.onload = function () { + if (gen !== this._updateGen) + return; // superseded by a newer toggle -- discard this stale bake var tex = new THREE.Texture(img); tex.needsUpdate = true; //tex.anisotropy = 16;