Make the smooth-filter check unable to cover for the hard one
The pixel-art check falls over sporadically, and its follow-up hid it. That one only asked whether some pixel across the border is blended – but in the failing case the `nearest` reading is already blurred, so the `linear` one is too, and the check passed while saying nothing about whether the switch had any effect at all. It now also demands that the picture actually changed against the `nearest` reading: the summed colour distance over the five sample points must exceed 150. Measured on the readings recorded in the note, a working switch drifts 425 and a hung one 0 – and 30 even if every channel were off by two, so the threshold is not brittle against noise. Exact equality was the first draft and would have gone green on a single wobbling bit. Both checks now carry `__gm.textureFilter(file)` in their message, so a failure says by itself whether the model never switched, the switch missed the GPU sampler, or the pixels were measured wrong. The cause of the sporadic failure is still unknown; four hypotheses are measured and ruled out in the note, which is filed with that stated plainly.
This commit is contained in:
1 parent
88ec367ab0
commit
75be133374
3 files changed
+83
-25
No files matched your search
@@ -0,0 +1,63 @@
|
||||
Der E2E-Check `pixel-art filtering keeps the border between two quadrants hard` faellt
|
||||
**sporadisch** um — am 2026-09-09 zweimal in vier Laeufen, jeweils ohne dass eine Aenderung
|
||||
Texturen beruehrt haette.
|
||||
|
||||
- gruen: `["#e63c3c","#e63c3c","#3cc85a","#3cc85a","#3cc85a"]` — harte Kante, `nearest` greift
|
||||
- rot: `["#c65641","#a67047","#868a4c","#66a552","#3cc85a"]` — weicher Verlauf, also `linear`
|
||||
|
||||
## Erledigt: der Folge-Check deckt nichts mehr zu
|
||||
|
||||
Der zweite Check (`switching the filter back to smooth …`) verglich nur `soft.some(c => !pure(c))`
|
||||
und meldete damit auch dann gruen, wenn **beide** Filter denselben Verlauf zeigten — ein haengender
|
||||
Wechsel liess genau einen Check fallen, der zweite verdeckte ihn.
|
||||
|
||||
Er verlangt jetzt zusaetzlich, dass sich das Bild gegenueber `nearest` messbar geaendert hat
|
||||
(Summe der Farbabstaende ueber die fuenf Punkte > 150). An den oben aufgezeichneten Reihen
|
||||
gerechnet: echter Wechsel 425, haengender 0 — und 30 selbst dann, wenn jeder Kanal um zwei
|
||||
danebenlaege. Beide Checks legen ausserdem `__gm.textureFilter(datei)` in ihren Fehlertext.
|
||||
|
||||
## Das Messgeraet
|
||||
|
||||
`__gm.textureFilter(datei)` liest **beides**: was das Modell will (`scaleMode`) und was der Treiber
|
||||
tatsaechlich weiss (`gl.getTexParameter` an der hochgeladenen Textur). Ein FAIL beantwortet damit
|
||||
von selbst, was bisher Deutungssache war:
|
||||
|
||||
| Messung | Bedeutung |
|
||||
|---|---|
|
||||
| `scaleMode` linear, Bild weich | das Modell hat nie umgeschaltet |
|
||||
| `scaleMode` nearest, `gpu` linear | der Wechsel erreichte den Sampler nicht — Produktfehler |
|
||||
| beide nearest, Bild trotzdem weich | der Test misst falsch |
|
||||
|
||||
Es bindet die Source ueber `renderer.texture.bindSource` statt per rohem `bindTexture` — sonst
|
||||
verfaelscht die Messung Pixis Vorstellung davon, was gebunden ist, und stiftet selbst Flakiness.
|
||||
|
||||
## Offen: die Ursache
|
||||
|
||||
Vier Hypothesen sind gemessen und **widerlegt** — nicht erneut probieren:
|
||||
|
||||
| Hypothese | Messung | Ergebnis |
|
||||
|---|---|---|
|
||||
| Der Wechsel erreicht den GPU-Sampler nicht | 30 Wechsel, Modell und `gl.getTexParameter` gelesen | 60/60 einig |
|
||||
| Der Vorlauf der elf Module hinterlaesst etwas | 15 Runden nach echtem Vorlauf | alle gruen |
|
||||
| Verlorener GPU-Prozess (Chrome meldete `exit_code=34`) | Kontext gezielt verloren und wiederhergestellt | `nearest` ueberlebt beides, auch mit Redraw |
|
||||
| Genau **ein** Wechsel auf frischer Seite, wie im Test | 12 Runden, je neuer Seed und Seitenaufbau | alle gruen |
|
||||
|
||||
Dass in ueber 60 gezielten Versuchen nichts faellt, waehrend der echte Lauf in ein bis zwei von
|
||||
vier Laeufen umfaellt, ist der eigentliche Widerspruch.
|
||||
|
||||
Naechste Spur bleibt die Umgebung: Chrome meldet beim Start auf der Windows-Maschine
|
||||
`GPU process exited unexpectedly: exit_code=34`. Wie oft das passiert, ist allerdings **unbekannt** —
|
||||
`harness.mjs` gibt die Browser-stderr nur bei einer Exception oder bei `RUN DIED` aus, in gruenen
|
||||
Laeufen also nie. Solange das so ist, laesst sich gar nicht messen, ob der Absturz mit dem
|
||||
Fehlschlag korreliert. Wer hier weitermacht, protokolliert die stderr zuerst bei jedem Lauf.
|
||||
|
||||
Die Sonden dazu waren Wegwerfware und sind geloescht. Wer weitermacht, baut sie neu — beide
|
||||
waren duenn: die eine fuhr den echten Modul-Vorlauf und danach eine Messschleife aus
|
||||
Filterwechsel + `__gm.textureFilter`, die andere erzwang ueber `WEBGL_lose_context` einen
|
||||
Kontextverlust und mass danach dasselbe.
|
||||
|
||||
## Warum diese Notiz trotz offener Ursache in `done/` liegt
|
||||
|
||||
Abgelegt am 2026-09-09 auf Anweisung. **Erledigt ist der Testmangel**, den die Notiz beschrieb,
|
||||
plus das Messgeraet — die **Ursache der Sporadik nicht**. Faellt der Check wieder um, ist das hier
|
||||
der Stand: vier widerlegte Hypothesen und die einzige offene Spur (stderr zuerst protokollieren).
|
||||
@@ -1,14 +0,0 @@
|
||||
Der E2E-Check `pixel-art filtering keeps the border between two quadrants hard` faellt
|
||||
**sporadisch** um — heute (2026-09-09) zweimal in vier Laeufen, jeweils ohne dass eine Aenderung
|
||||
Texturen beruehrt haette.
|
||||
|
||||
- gruen: `["#e63c3c","#e63c3c","#3cc85a","#3cc85a","#3cc85a"]` — harte Kante, `nearest` greift
|
||||
- rot: `["#c65641","#a67047","#868a4c","#66a552","#3cc85a"]` — weicher Verlauf, also `linear`
|
||||
|
||||
Der Folge-Check (`switching the filter back to smooth …`) meldet im Fehlerfall fuer **beide**
|
||||
Filter denselben Verlauf, ist aber trotzdem gruen — er vergleicht nicht gegen den Erwartungswert.
|
||||
Das heisst: wenn der Filterwechsel haengt, faellt genau ein Check, und der zweite deckt es zu.
|
||||
|
||||
Zu klaeren: laedt der Test die Textur zu frueh aus (Timing), oder wird `scaleMode` beim ersten
|
||||
Setzen manchmal nicht auf die schon hochgeladene GPU-Textur durchgereicht (dann ist es ein echter
|
||||
Produktfehler und kein Testproblem)?
|
||||
+20
-11
@@ -162,28 +162,37 @@ export async function textures(t) {
|
||||
}
|
||||
return points;
|
||||
};
|
||||
const setFilter = (value) =>
|
||||
mutate(
|
||||
// Read the pixels first, then ask the driver what it actually has: a failure then says by
|
||||
// itself whether the model never switched, the switch missed the GPU sampler, or the pixels
|
||||
// were measured wrong. This check has fallen over sporadically without any of the three ever
|
||||
// being distinguishable from the message.
|
||||
const sample = async (value) => {
|
||||
await mutate(
|
||||
`__gm.state.project.assets.find((a) => a.id === ${JSON.stringify(texture.id)}).props.filter = ${JSON.stringify(value)}`,
|
||||
);
|
||||
await sleep(600);
|
||||
const pixels = await acrossBorder();
|
||||
return { pixels, filter: await json(`__gm.textureFilter(${JSON.stringify(texture.file)})`) };
|
||||
};
|
||||
|
||||
await setFilter('nearest');
|
||||
await sleep(600);
|
||||
const hard = await acrossBorder();
|
||||
const hard = await sample('nearest');
|
||||
const pure = (c) => colourDistance(c, '#e63c3c') < 60 || colourDistance(c, '#3cc85a') < 60;
|
||||
check(
|
||||
'pixel-art filtering keeps the border between two quadrants hard',
|
||||
hard.every(pure),
|
||||
hard.pixels.every(pure),
|
||||
JSON.stringify(hard),
|
||||
);
|
||||
|
||||
await setFilter('linear');
|
||||
await sleep(600);
|
||||
const soft = await acrossBorder();
|
||||
const soft = await sample('linear');
|
||||
// The drift — that the picture actually changed — is what makes this a test of the switch.
|
||||
// Were the switch to hang, both readings would be the blurred one, and "some pixel is blended"
|
||||
// alone would pass and hide the failure of the check above. Measured on the recorded readings:
|
||||
// a working switch drifts 425, a hung one 0, and 30 even if every channel were off by two.
|
||||
const drift = hard.pixels.reduce((sum, c, i) => sum + colourDistance(c, soft.pixels[i]), 0);
|
||||
check(
|
||||
'switching the filter back to smooth blends the border without a reload',
|
||||
soft.some((c) => !pure(c)),
|
||||
JSON.stringify({ nearest: hard, linear: soft }),
|
||||
soft.pixels.some((c) => !pure(c)) && drift > 150,
|
||||
JSON.stringify({ drift, nearest: hard, linear: soft }),
|
||||
);
|
||||
await shot('33-texture-filter-smooth');
|
||||
await mutate(enlarge(160, 120));
|
||||
|
||||
Reference in new issue
Block a user