Advance WebGPU volume and bounded workflows
This commit is contained in:
36
web/tests/e2e/texture-8k-performance.spec.ts
Normal file
36
web/tests/e2e/texture-8k-performance.spec.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("decodes, uploads and renders a validated 8K texture in Chromium", async ({ page }) => {
|
||||
test.setTimeout(60_000);
|
||||
await page.goto("/");
|
||||
const result = await page.evaluate(async () => {
|
||||
const { createGPUTextureAsset } = await import("/src/render/RenderAssets.ts");
|
||||
const { GPUTextureStore } = await import("/src/three-adapter/texture-assets.ts");
|
||||
const { Mesh, MeshBasicMaterial, OrthographicCamera, PlaneGeometry, Scene, WebGLRenderer } = await import("/src/vendor/three/three.module.js");
|
||||
const target = document.createElement("canvas"); target.width = 64; target.height = 64; document.body.append(target);
|
||||
const renderer = new WebGLRenderer({ canvas: target, preserveDrawingBuffer: true }); renderer.setSize(64, 64, false);
|
||||
const gl = renderer.getContext(); const maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE) as number;
|
||||
if (maxTextureSize < 8192) { renderer.dispose(); target.remove(); return { supported: false, maxTextureSize, byteLength: 0, colored: 0, elapsedMs: 0, status: { loaded: 0, rejected: 0, bytes: 0 } }; }
|
||||
const source = document.createElement("canvas"); source.width = 8192; source.height = 8192;
|
||||
const context = source.getContext("2d", { alpha: false });
|
||||
if (!context) throw new Error("2D texture fixture context is unavailable");
|
||||
context.fillStyle = "#2266dd"; context.fillRect(0, 0, 4096, 8192);
|
||||
context.fillStyle = "#ddcc22"; context.fillRect(4096, 0, 4096, 8192);
|
||||
const blob = await new Promise<Blob>((resolve, reject) => source.toBlob((value) => value ? resolve(value) : reject(new Error("8K PNG encoding failed")), "image/png"));
|
||||
const data = await blob.arrayBuffer();
|
||||
const asset = await createGPUTextureAsset({ assetId: "asset:8k", imageId: "image:8k", mimeType: "image/png", width: 8192, height: 8192, usage: "BASE_COLOR", colorSpace: "SRGB" }, data);
|
||||
const started = performance.now(); const store = new GPUTextureStore(); const status = await store.upload([asset]);
|
||||
const scene = new Scene(); const camera = new OrthographicCamera(-1, 1, 1, -1, 0.1, 10); camera.position.z = 1;
|
||||
const material = new MeshBasicMaterial({ map: store.get("image:8k", "BASE_COLOR") }); scene.add(new Mesh(new PlaneGeometry(2, 2), material)); renderer.render(scene, camera);
|
||||
const pixels = new Uint8Array(64 * 64 * 4); gl.readPixels(0, 0, 64, 64, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
|
||||
let colored = 0; for (let index = 0; index < pixels.length; index += 4) if (pixels[index] > 60 || pixels[index + 1] > 60 || pixels[index + 2] > 60) colored += 1;
|
||||
const elapsedMs = Math.round(performance.now() - started);
|
||||
material.dispose(); renderer.dispose(); store.dispose(); target.remove();
|
||||
return { supported: true, maxTextureSize, status, byteLength: data.byteLength, colored, elapsedMs };
|
||||
});
|
||||
expect(result.supported, `WebGL MAX_TEXTURE_SIZE=${result.maxTextureSize}`).toBe(true);
|
||||
expect(result.status).toMatchObject({ loaded: 1, rejected: 0, bytes: result.byteLength });
|
||||
expect(result.byteLength).toBeGreaterThan(0);
|
||||
expect(result.colored).toBeGreaterThan(3_000);
|
||||
expect(result.elapsedMs).toBeLessThan(45_000);
|
||||
});
|
||||
Reference in New Issue
Block a user