Shader: Fingerprint enthaelt Node-Positionen, Verschieben kompiliert neu #65

Closed
opened 2026-09-13 11:27:43 +02:00 by meleki · 1 comment
Owner

Befund

ShaderLibrary (src/editor/...ShaderLibrary.ts) bildet den Fingerprint eines Assets mit JSON.stringify(asset.graph). Der Graph enthaelt die Node-Positionen, ein Verschieben eines Nodes im Shader-Tab loest deshalb einen Recompile aus. Das Ergebnis ist identisch (der Filter bleibt, kein Flackern), aber waehrend eines Drags kompiliert der Compiler bei jedem Redraw.

Dazu der bekannte Punkt aus #62: GlProgram.from cached nach Quelltext, jeder neue Quelltext laesst ein Programm im Cache. Mit Positionen im Fingerprint aendert sich der Quelltext zwar nicht (nur der Fingerprint), aber die Compile-Arbeit faellt an.

Vorschlag

Fingerprint nur ueber das, was den GLSL-Text bestimmt: Node-Typ, params, Kanten. Positionen (und alles andere rein Editor-seitige) bleiben draussen.

Unit-Test: gleicher Fingerprint nach einem MoveNode, anderer nach einer Param-Aenderung.

## Befund `ShaderLibrary` (`src/editor/...ShaderLibrary.ts`) bildet den Fingerprint eines Assets mit `JSON.stringify(asset.graph)`. Der Graph enthaelt die Node-Positionen, ein Verschieben eines Nodes im Shader-Tab loest deshalb einen Recompile aus. Das Ergebnis ist identisch (der Filter bleibt, kein Flackern), aber waehrend eines Drags kompiliert der Compiler bei jedem Redraw. Dazu der bekannte Punkt aus #62: `GlProgram.from` cached nach Quelltext, jeder neue Quelltext laesst ein Programm im Cache. Mit Positionen im Fingerprint aendert sich der Quelltext zwar nicht (nur der Fingerprint), aber die Compile-Arbeit faellt an. ## Vorschlag Fingerprint nur ueber das, was den GLSL-Text bestimmt: Node-Typ, `params`, Kanten. Positionen (und alles andere rein Editor-seitige) bleiben draussen. Unit-Test: gleicher Fingerprint nach einem `MoveNode`, anderer nach einer Param-Aenderung.
meleki added the shader label 2026-09-13 11:27:43 +02:00
admin added this to the Development project 2026-09-13 13:29:59 +02:00
admin moved this to Next in Development on 2026-09-13 14:14:49 +02:00
admin moved this to Queue in Development on 2026-09-13 16:29:00 +02:00
admin moved this to Next in Development on 2026-09-13 17:21:05 +02:00
Author
Owner

Befund

Praeziser als im Issue: nicht nur "bei jedem Redraw", sondern ein Compile pro Vorschau-Schritt eines Drags. GraphCanvas.onPointerMove ruft pro Schritt state.preview() -> project-Ereignis -> ShaderLibrary.sync() -> buildFor, und der Fingerprint JSON.stringify(asset.graph) sah in jedem Schritt neue x/y. Gemessen mit einem neuen Zaehler: ein Harness-drag (12 Schritte) im Shader-Tab kompilierte den Graphen 12-mal (11 -> 23).

Fix

  • shaderFingerprint(graph) in src/core/shader/compile.ts: je Node [id, type, params, ports], je Kante die Endpunkte. x/y, collapsed, folded und edge.id bleiben draussen.
  • ShaderLibrary keyt darauf und zaehlt compiles; Hook __gm.shaderCompiles().

Beweis

./check.sh === CHECK EXIT 0 ===, 867 Tests (+1: Move/Collapse/Fold gleicher Fingerprint, Param/Kante anderer)
e2e Modul 28 ALL PASSED - 51 checks (+2): Node um 60/40 verschoben, Compiles 11 -> 11; Param geaendert -> 12, genau einmal
Gegenprobe x/y wieder in den Fingerprint, neu gebaut: genau der Unit-Test faellt (19 andere gruen) und genau der Drop-Check faellt mit compiledAfterMove: 23; Rueckbau ergibt das byte-gleiche Bundle (index-bRphSWTk.js, e2e- und Commit-Build identisch)

Nicht angefasst: GlProgram.from cached weiterhin nach Quelltext (siehe #62) — mit dem neuen Fingerprint entsteht beim Verschieben aber gar kein Build mehr, also auch kein Cache-Eintrag.

Commit 102a649, Wiki f80df5e (Shaders: Fingerprint-Regel und Hook unter "In the code"; Development: 760 checks).

## Befund Praeziser als im Issue: nicht nur "bei jedem Redraw", sondern **ein Compile pro Vorschau-Schritt eines Drags**. `GraphCanvas.onPointerMove` ruft pro Schritt `state.preview()` -> `project`-Ereignis -> `ShaderLibrary.sync()` -> `buildFor`, und der Fingerprint `JSON.stringify(asset.graph)` sah in jedem Schritt neue `x`/`y`. Gemessen mit einem neuen Zaehler: ein Harness-`drag` (12 Schritte) im Shader-Tab kompilierte den Graphen **12-mal** (11 -> 23). ## Fix - `shaderFingerprint(graph)` in `src/core/shader/compile.ts`: je Node `[id, type, params, ports]`, je Kante die Endpunkte. `x`/`y`, `collapsed`, `folded` und `edge.id` bleiben draussen. - `ShaderLibrary` keyt darauf und zaehlt `compiles`; Hook `__gm.shaderCompiles()`. ## Beweis | | | |---|---| | `./check.sh` | `=== CHECK EXIT 0 ===`, 867 Tests (+1: Move/Collapse/Fold gleicher Fingerprint, Param/Kante anderer) | | e2e Modul 28 | `ALL PASSED - 51 checks` (+2): Node um 60/40 verschoben, Compiles **11 -> 11**; Param geaendert **-> 12**, genau einmal | | Gegenprobe | `x`/`y` wieder in den Fingerprint, neu gebaut: genau der Unit-Test faellt (19 andere gruen) und genau der Drop-Check faellt mit `compiledAfterMove: 23`; Rueckbau ergibt das byte-gleiche Bundle (`index-bRphSWTk.js`, e2e- und Commit-Build identisch) | Nicht angefasst: `GlProgram.from` cached weiterhin nach Quelltext (siehe #62) — mit dem neuen Fingerprint entsteht beim Verschieben aber gar kein Build mehr, also auch kein Cache-Eintrag. Commit `102a649`, Wiki `f80df5e` (*Shaders*: Fingerprint-Regel und Hook unter "In the code"; *Development*: 760 checks).
admin moved this to Done in Development on 2026-09-13 18:02:28 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: meleki/feuerwerk#65