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:
root committed 2026-09-09 15:55:28 +02:00
1 parent 88ec367ab0
commit 75be133374
3 files changed
+83 -25

No files matched your search

+20 -11
View File
@@ -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));