diff --git a/webgpu-cts/aggregate-dawn-node.mjs b/webgpu-cts/aggregate-dawn-node.mjs new file mode 100755 index 00000000..43a4a02d --- /dev/null +++ b/webgpu-cts/aggregate-dawn-node.mjs @@ -0,0 +1,92 @@ +#!/usr/bin/env node +// Reads every results/dawn-node//*.json (one per CTS query, written by +// run-shard.sh with --print-json) and tallies per-case status, overall and +// broken down by top-level CTS area (the first path segment after +// "webgpu:", e.g. "api", "shader", "idl", "web_platform"). Only walks +// results/dawn-node/, so it reflects whatever fraction of the sharded run +// has finished when it's run -- rerun it any time for a progress snapshot, +// not just once the full run is done. +import { readdirSync, readFileSync, statSync } from 'node:fs'; +import { join } from 'node:path'; + +const SELF_DIR = new URL('.', import.meta.url).pathname; +const ROOT = join(SELF_DIR, 'results', 'dawn-node'); + +function areaOf(testName) { + // "webgpu:api,validation,...:..." -> "api,validation"; take the first two + // comma-separated segments after the suite name, since "api" and "shader" + // alone are too coarse (validation vs operation, validation vs execution). + const afterSuite = testName.split(':')[1] ?? ''; + const segments = afterSuite.split(','); + return segments.slice(0, 2).join(',') || '(unknown)'; +} + +const overall = new Map(); +const byArea = new Map(); + +function bump(map, key, status) { + if (!map.has(key)) map.set(key, new Map()); + const counts = map.get(key); + counts.set(status, (counts.get(status) ?? 0) + 1); +} + +let filesRead = 0; +let shardDirs = []; +try { + shardDirs = readdirSync(ROOT).filter(name => /^\d+$/.test(name)); +} catch (e) { + console.error(`no results yet under ${ROOT}: ${e.message}`); + process.exit(1); +} + +for (const shard of shardDirs) { + const shardDir = join(ROOT, shard); + let entries; + try { + entries = readdirSync(shardDir); + } catch { + continue; + } + for (const entry of entries) { + if (!entry.endsWith('.json')) continue; + const path = join(shardDir, entry); + if (statSync(path).size === 0) continue; + let parsed; + try { + parsed = JSON.parse(readFileSync(path, 'utf8')); + } catch { + // A query still mid-write, or one that crashed before printing valid + // JSON; run-shard.sh's shard.log has the detail. Skip it here. + continue; + } + filesRead++; + for (const [testName, result] of parsed.results ?? []) { + const status = result.status ?? '(no status)'; + bump(overall, '(all)', status); + bump(byArea, areaOf(testName), status); + } + } +} + +function printTable(map) { + const statuses = new Set(); + for (const counts of map.values()) { + for (const s of counts.keys()) statuses.add(s); + } + const statusList = [...statuses].sort(); + for (const [key, counts] of [...map.entries()].sort()) { + const total = [...counts.values()].reduce((a, b) => a + b, 0); + const parts = statusList + .filter(s => counts.has(s)) + .map(s => `${s}=${counts.get(s)}`); + console.log(`${key}: total=${total} ${parts.join(' ')}`); + } +} + +console.log(`query files read: ${filesRead} of ${shardDirs.length} shards`); +console.log(''); +console.log('overall:'); +printTable(overall); +console.log(''); +console.log('by area:'); +printTable(byArea); diff --git a/webgpu-cts/probe-browser-webgpu.cjs b/webgpu-cts/probe-browser-webgpu.cjs index 184f778e..c8107d81 100644 --- a/webgpu-cts/probe-browser-webgpu.cjs +++ b/webgpu-cts/probe-browser-webgpu.cjs @@ -22,11 +22,14 @@ async function main() { '--enable-features=Vulkan', '--use-angle=vulkan', '--use-gl=angle', + '--use-vulkan=native', '--ignore-gpu-blocklist', ] : []; + // Firefox does not enable WebGPU by default even when it's compiled in. + const firefoxUserPrefs = name === 'firefox' ? { 'dom.webgpu.enabled': true } : undefined; - const browser = await launcher.launch({ headless: true, args: launchArgs }); + const browser = await launcher.launch({ headless: true, args: launchArgs, firefoxUserPrefs }); try { const page = await browser.newPage(); page.on('console', msg => console.log(`[console] ${msg.text()}`));