Advance M8-M11 parity workflows
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

This commit is contained in:
mes123456
2026-08-17 04:37:07 -04:00
parent 7c16b279ae
commit 0fe8d2bb56
324 changed files with 31920 additions and 863 deletions

View File

@@ -0,0 +1,103 @@
import { expect, test } from "@playwright/test";
import fs from "node:fs";
import path from "node:path";
const root = path.resolve(import.meta.dirname, "../../..");
const goldenRoot = path.join(root, "tests/golden/M11-04");
const manifest = JSON.parse(fs.readFileSync(path.join(goldenRoot, "manifest.json"), "utf8"));
const blend = fs.readFileSync(path.join(root, manifest.source.fixture));
const referencePng = fs.readFileSync(path.join(goldenRoot, manifest.reference.file));
async function decodeAndCompare(page: import("@playwright/test").Page, reference: Buffer, actual: Buffer) {
return page.evaluate(async ({ referenceBytes, actualBytes, thresholds }) => {
const { compareRenderImages } = await import("/src/three-adapter/render-image-comparison.ts");
const decode = async (bytes: number[]) => {
const bitmap = await createImageBitmap(new Blob([Uint8Array.from(bytes)], { type: "image/png" }), {
colorSpaceConversion: "none",
premultiplyAlpha: "none",
});
const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
const context = canvas.getContext("2d", { willReadFrequently: true });
if (!context) throw new Error("2D decode context is unavailable");
context.drawImage(bitmap, 0, 0);
const pixels = new Uint8Array(context.getImageData(0, 0, bitmap.width, bitmap.height).data);
const result = { width: bitmap.width, height: bitmap.height, pixels };
bitmap.close();
return result;
};
const [referenceFrame, actualFrame] = await Promise.all([decode(referenceBytes), decode(actualBytes)]);
if (referenceFrame.width !== actualFrame.width || referenceFrame.height !== actualFrame.height) {
throw new Error("render frame dimensions differ");
}
return compareRenderImages(
referenceFrame.pixels,
actualFrame.pixels,
referenceFrame.width,
referenceFrame.height,
thresholds,
);
}, { referenceBytes: Array.from(reference), actualBytes: Array.from(actual), thresholds: manifest.thresholds });
}
for (const offscreen of [false, true]) {
test(`M11-04 ${offscreen ? "Offscreen" : "main-thread"} production render matches the Blender reference metrics`, async ({ page }) => {
test.setTimeout(60_000);
await page.goto("/");
await page.evaluate(async ({ input, useOffscreen }) => {
const { WebEngineClient } = await import("/src/engine-client/WebEngineClient.ts");
const { ViewportRenderer } = await import("/src/three-adapter/viewport.ts");
const { OffscreenViewportRenderer } = await import("/src/three-adapter/offscreen-viewport.ts");
document.body.replaceChildren();
document.body.style.margin = "0";
const canvas = document.createElement("canvas");
canvas.id = "m11-reference-canvas";
canvas.style.width = "256px";
canvas.style.height = "256px";
document.body.append(canvas);
const client = new WebEngineClient({ timeoutMs: 30_000 });
const opened = await client.openBlend(Uint8Array.from(input).buffer);
opened.snapshot.activeObjectId = null;
const renderer = useOffscreen ? new OffscreenViewportRenderer(canvas) : new ViewportRenderer(canvas);
renderer.setSnapshot(opened.snapshot, opened.geometryBuffers, opened.nonMeshGeometryBuffers ?? []);
for (let attempt = 0; attempt < 300; attempt++) {
if (!useOffscreen || (Number(canvas.dataset.rendererPixels) > 0 && canvas.dataset.renderBudgetStatus === "ready")) break;
await new Promise((resolve) => setTimeout(resolve, 10));
}
await new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)));
(globalThis as typeof globalThis & { __m11Reference?: { renderer: { dispose(): void }; client: { terminate(): void } } }).__m11Reference = { renderer, client };
}, { input: Array.from(blend), useOffscreen: offscreen });
const canvas = page.locator("#m11-reference-canvas");
await expect(canvas).toHaveAttribute("data-render-budget-status", "ready");
const actualPng = await canvas.screenshot({ animations: "disabled" });
const report = await decodeAndCompare(page, referencePng, actualPng);
console.log(`m11-render-reference-${offscreen ? "offscreen" : "main"}`, JSON.stringify(report));
expect(report.status).toBe("READY");
expect(report.errorCode).toBeNull();
expect(report.checks.every((item) => item.passed)).toBe(true);
await page.evaluate(() => {
const state = (globalThis as typeof globalThis & { __m11Reference?: { renderer: { dispose(): void }; client: { terminate(): void } } }).__m11Reference;
state?.renderer.dispose();
state?.client.terminate();
delete (globalThis as typeof globalThis & { __m11Reference?: unknown }).__m11Reference;
});
});
}
test("M11-04 rejects a non-empty frame with the wrong composition", async ({ page }) => {
await page.goto("/");
const wrong = await page.evaluate(async () => {
const canvas = new OffscreenCanvas(256, 256);
const context = canvas.getContext("2d")!;
context.fillStyle = "rgb(58,58,58)";
context.fillRect(0, 0, 256, 256);
context.fillStyle = "rgb(255,0,0)";
context.fillRect(0, 0, 32, 32);
return Array.from(new Uint8Array(await (await canvas.convertToBlob({ type: "image/png" })).arrayBuffer()));
});
const report = await decodeAndCompare(page, referencePng, Buffer.from(wrong));
expect(report.status).toBe("BLOCKED");
expect(report.errorCode).toBe("RENDER_REFERENCE_MISMATCH");
expect(report.checks.some((item) => !item.passed)).toBe(true);
});