WebGPU pixel look: GPU colours the world, CPU only rare cells (t88 phase 2a)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+14
-4
@@ -54,14 +54,14 @@ def report(result, baseline=None):
|
||||
m = result['machine']
|
||||
print(f"GPU: {m['renderer']}\nCores: {m['cores']} | isolated: {m['crossOriginIsolated']} | navigator.gpu: {m['webgpu']}")
|
||||
print(f"Viewport {result['options']['viewport']} | world {result['options']['world']} | seed 424242 | ms (CPU wall time)")
|
||||
print('\nScene Look Zoom Light Grains World Light Prep Colour Upload Blit Overlays Scale')
|
||||
print('\nScene Look Zoom Light Grains World Frame Light Prep Colour Upload Blit Overlays Scale')
|
||||
for scene, data in result['scenes'].items():
|
||||
for key, view in data['views'].items():
|
||||
look, zoom = key.split('/')
|
||||
for light, r in view['lighting'].items():
|
||||
p = r['marks_ms']
|
||||
print(f"{scene:8} {look:6} {zoom:>4} {light:>5} {view['grains']:6d} "
|
||||
f"{r['drawWorld_ms']:7.2f} {p['light']:6.2f} {p['prepare']:5.2f} {p['color']:6.2f} "
|
||||
f"{r['drawWorld_ms']:7.2f} {r.get('frame_ms', 0):6.2f} {p['light']:6.2f} {p['prepare']:5.2f} {p['color']:6.2f} "
|
||||
f"{p['upload']:6.2f} {p['blit']:6.2f} {r['overlay_ms']:8.3f} {r['scale']:5.2f}")
|
||||
print('\nSimulation: average ms/tick (periodic work amortized over 240 ticks)')
|
||||
names = list(next(iter(result['scenes'].values()))['sim']['steps'])
|
||||
@@ -125,8 +125,10 @@ def main():
|
||||
options = dict(viewport=list(args.viewport), world=list(args.world), zooms=zooms,
|
||||
looks=looks, scenes=scenes, seconds=args.seconds)
|
||||
baseline = json.loads(args.compare.read_text()) if args.compare else None
|
||||
if baseline and (baseline.get('schema') != 1 or baseline['options'] != options):
|
||||
ap.error('baseline schema/options differ; use the same matrix, dimensions and seconds')
|
||||
if baseline and (baseline.get('schema') != 1
|
||||
or any(baseline['options'].get(k) != v for k, v in options.items() if k not in ('looks', 'scenes', 'zooms'))
|
||||
or any(not set(options[k]).issubset(baseline['options'][k]) for k in ('looks', 'scenes', 'zooms'))):
|
||||
ap.error('baseline schema/options differ; use a subset of the baseline matrix with the same dimensions and seconds')
|
||||
ensure_playwright()
|
||||
started = time.monotonic()
|
||||
subprocess.run([sys.executable, str(ROOT / 'build.py')], cwd=ROOT, check=True, stdout=sys.stderr)
|
||||
@@ -154,6 +156,9 @@ def main():
|
||||
const id = raf(t => { pending.delete(id); f(t); }); pending.add(id); return id;
|
||||
};''')
|
||||
pg.goto(url)
|
||||
pg.evaluate('CAPS_CHECK')
|
||||
if not pg.evaluate('GPU.ok'):
|
||||
raise RuntimeError('WebGPU unavailable: ' + pg.evaluate('GPU.error'))
|
||||
pg.add_script_tag(content=(ROOT / 'tools/perf-scenes.js').read_text())
|
||||
pg.add_script_tag(content=(ROOT / 'tools/perf-measure.js').read_text())
|
||||
result['machine'] = pg.evaluate('''() => {
|
||||
@@ -162,6 +167,7 @@ def main():
|
||||
return { renderer: dbg ? gl.getParameter(dbg.UNMASKED_RENDERER_WEBGL) : gl.getParameter(gl.RENDERER),
|
||||
vendor: dbg ? gl.getParameter(dbg.UNMASKED_VENDOR_WEBGL) : gl.getParameter(gl.VENDOR),
|
||||
cores: navigator.hardwareConcurrency, crossOriginIsolated, webgpu: !!navigator.gpu,
|
||||
adapter: CAPS.adapterInfo, timestamp_query: !!GPU.queries,
|
||||
user_agent: navigator.userAgent, dpr: devicePixelRatio };
|
||||
}''')
|
||||
if not result['machine']['crossOriginIsolated']:
|
||||
@@ -185,6 +191,8 @@ def main():
|
||||
view['lighting'][light] = pg.evaluate('([l,o]) => perfRender(l,o)', [light, overlays])
|
||||
if view['lighting']['full']['actual_look'] != look or view['lighting']['off']['actual_look'] != look:
|
||||
raise RuntimeError('Look fell back while measuring')
|
||||
if look == 'pixel' and any(r['renderer'] != 'webgpu' for r in view['lighting'].values()):
|
||||
raise RuntimeError('WebGPU fell back while measuring: ' + pg.evaluate('GPU.error'))
|
||||
data['views'][f'{look}/{zoom:g}'] = view
|
||||
for look in looks:
|
||||
for zoom in [2, 6]:
|
||||
@@ -193,6 +201,8 @@ def main():
|
||||
r = pg.evaluate('seconds => perfRun(seconds)', args.seconds)
|
||||
if r['actual_look'] != look:
|
||||
raise RuntimeError('Look fell back during real run')
|
||||
if look == 'pixel' and r['renderer'] != 'webgpu':
|
||||
raise RuntimeError('WebGPU fell back during real run: ' + pg.evaluate('GPU.error'))
|
||||
for key in ['interval', 'work', 'sim']:
|
||||
r[key + '_ms'] = quantiles([s[key] for s in r['samples']])
|
||||
data['runs'][f'{look}/{zoom}'] = r
|
||||
|
||||
Reference in New Issue
Block a user