git-subtree-dir: apps/viewer-3d git-subtree-mainline:5e10bb1be4git-subtree-split:a71790070d
96 lines
3.9 KiB
JavaScript
96 lines
3.9 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* tools/adaptive-smoke.mjs — empirically trigger the adaptive-quality downstep.
|
|
*
|
|
* Loads a heavy sample in headless Chrome (software GL = slow) + applies a CDP
|
|
* CPU throttle so the REAL measured fps sustains < 60. Captures the genuine
|
|
* `[hmwebviewer] adaptive quality -> tier N (pr=..)` console logs emitted by
|
|
* src/viewer/adaptiveQuality.ts, plus the live #.fps overlay text. Proves the
|
|
* <60fps → optimize path fires on real frame measurement (no logic patched).
|
|
*
|
|
* USAGE: node tools/adaptive-smoke.mjs [--url URL] [--asset PATH] [--throttle N] [--seconds S]
|
|
*/
|
|
import puppeteer from 'puppeteer-core';
|
|
import { existsSync } from 'node:fs';
|
|
|
|
const CHROME_CANDIDATES = [
|
|
'C:/Program Files/Google/Chrome/Application/chrome.exe',
|
|
'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe',
|
|
'C:/Program Files (x86)/Microsoft/Edge/Application/msedge.exe',
|
|
];
|
|
function findBrowser() {
|
|
if (process.env.PUPPETEER_EXECUTABLE_PATH && existsSync(process.env.PUPPETEER_EXECUTABLE_PATH)) return process.env.PUPPETEER_EXECUTABLE_PATH;
|
|
for (const p of CHROME_CANDIDATES) if (existsSync(p)) return p;
|
|
return null;
|
|
}
|
|
|
|
function parseArgs(argv) {
|
|
const a = argv.slice(2);
|
|
let url = 'http://127.0.0.1:4173', asset = '/samples/ABeautifulGame.ktx2.glb', throttle = 6, seconds = 25;
|
|
for (let i = 0; i < a.length; i++) {
|
|
if (a[i] === '--url') url = a[++i];
|
|
else if (a[i] === '--asset') asset = a[++i];
|
|
else if (a[i] === '--throttle') throttle = Number(a[++i]);
|
|
else if (a[i] === '--seconds') seconds = Number(a[++i]);
|
|
}
|
|
return { url, asset, throttle, seconds };
|
|
}
|
|
|
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
|
|
async function main() {
|
|
const o = parseArgs(process.argv);
|
|
const exe = findBrowser();
|
|
if (!exe) { console.error('[adaptive-smoke] No Chrome/Edge found.'); process.exit(1); }
|
|
|
|
const browser = await puppeteer.launch({
|
|
executablePath: exe,
|
|
headless: 'new',
|
|
args: ['--no-sandbox', '--use-gl=swiftshader', '--enable-webgl', '--ignore-gpu-blocklist'],
|
|
});
|
|
const page = await browser.newPage();
|
|
|
|
const tierLogs = [];
|
|
page.on('console', (m) => {
|
|
const t = m.text();
|
|
if (t.includes('adaptive quality')) { tierLogs.push(t); console.log(' LOG ' + t); }
|
|
});
|
|
|
|
await page.evaluateOnNewDocument(() => {
|
|
window.__hmwReady = null;
|
|
window.addEventListener('hmw:ready', (e) => { window.__hmwReady = e.detail; });
|
|
});
|
|
|
|
const target = o.url + '?model=' + o.asset;
|
|
console.log('[adaptive-smoke] ' + target + ' throttle=' + o.throttle + 'x watch=' + o.seconds + 's browser=' + exe);
|
|
await page.goto(target, { waitUntil: 'domcontentloaded', timeout: 30000 });
|
|
await page.waitForFunction('window.__hmwReady != null', { timeout: 60000 });
|
|
console.log('[adaptive-smoke] model loaded; applying CPU throttle + watching fps...');
|
|
|
|
const client = await page.target().createCDPSession();
|
|
await client.send('Emulation.setCPUThrottlingRate', { rate: o.throttle });
|
|
|
|
const start = Date.now();
|
|
while (Date.now() - start < o.seconds * 1000) {
|
|
await sleep(2000);
|
|
const state = await page.evaluate(() => {
|
|
const el = document.querySelector('.fps');
|
|
return { fps: el ? el.textContent : '(no overlay)', pr: window.__viewer ? undefined : undefined };
|
|
});
|
|
console.log(' t+' + Math.round((Date.now() - start) / 1000) + 's overlay=' + state.fps + ' tierSteps=' + tierLogs.length);
|
|
if (tierLogs.length >= 3) break; // enough proof
|
|
}
|
|
|
|
await browser.close();
|
|
|
|
console.log('\n[adaptive-smoke] tier-change log lines captured: ' + tierLogs.length);
|
|
tierLogs.forEach((l) => console.log(' ' + l));
|
|
if (tierLogs.length === 0) {
|
|
console.error('[adaptive-smoke] NO downstep observed — fps stayed >=60 (raise --throttle or use a heavier asset).');
|
|
process.exit(2);
|
|
}
|
|
console.log('[adaptive-smoke] PASS — adaptive quality degraded on sustained <60fps.');
|
|
}
|
|
|
|
main().catch((e) => { console.error('[adaptive-smoke] Fatal: ' + (e && e.stack ? e.stack : e)); process.exit(1); });
|