§5's GPU bullet now meets the tier for a decoder's wai-ops/1-i32 graphs on
the adapters and backends a run showed equal, lists them by backend, PCI
vendor and device and driver, and claims nothing for any other adapter or for
an NPU; jpegai's scale path keeps its entropy-consistency claim there, and
its synthesis graphs run on the CPU. §6 records the runs: the probe, the
corpus at both widths, the width test, the mutants, and the capability
decodes compared graph by graph. SPEC.md's fabric sentence and the
integer-operators header point to it; CHANGELOG entry.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The capability test now holds the device to the interpreter graph by graph,
as well as through each decode's bytes: every graph the device ran was
compared, and none differed.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The metal job runs the arithmetic probe, the corpus at both widths and the
mutants on the host's GPU, every capability that runs a wai-ops/1 graph with
its graphs there (the jpegai/v1 inputs fetched and required), and the corpus
in a headless browser's WebGPU. WAI_OPS_GPU_EXPECT declares the adapter and
WAI_OPS_GPU_REQUIRE makes its absence a failure; each step then requires its
report lines with their counts. The checks job, on a runner with no GPU,
requires that the device tests skip without WAI_OPS_GPU_REQUIRE and fail with
it, and builds the browser module, wai-rs's GPU target and the bench tool.
The arith test now appends its result line to the report as the others do.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
browser/ is a wasm32 module that runs every graph vector of ops-conformance
on the WebGPU adapter a page is offered, the kernels compiled by the
browser's own WGSL compiler, and holds each decode to the committed result
and to the interpreter running in the same page. run.mjs serves it with the
corpus and drives a headless browser (on macOS through Metal), and fails on a
mismatch, a device error or a page error, or, under WAI_OPS_GPU_REQUIRE=1,
when no adapter ran the corpus.
tests/support/corpus.rs now parses a file apart from reading it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A separate crate with its own lockfile, as quantum-meter is. Per committed
vector and per path (the CPU's default kernels on every core, then each
adapter found): two warm-up decodes, then decodes back to back for at least
the given seconds and count, each compared byte for byte with the CPU's
output; the line gives the count, median and 10th/90th percentiles. Energy is
read at the two ends of the timed loop only: on macOS this process's CPU
energy and GPU share (IOReport, which gives no GPU figure where the GPU was
shared) with the GPU rail over the window as an upper bound; on Linux RAPL
package-0 and, with the NVIDIA driver, its cumulative board energy counter,
after an idle window that gives each counter's idle power.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
int_ops::run_graph is now the one place the integer decoders run a graph
(run1 and jpegai_ops's networks go through it). With the ops_gpu feature,
inside int_ops::gpu::with_gpu, it runs each graph on a wai_ops_gpu device at
the width its certificate admits, and on the interpreter where the device
does not run it (an operator outside wai-ops/1-i32), counting both by width
and by reason. Off by default; a default build has no GPU interface.
tests/ops_gpu.rs decodes every committed vector and refusal fixture of every
capability that runs a wai-ops/1 graph with its graphs on each adapter found,
and requires the CPU decode's bytes or refusal code: int_hyper and its video
keyframe, the audio and splat codecs, int_synth, int_mlicpp, the world
renderer, and wai.image.jpegai's exact decoder on the jpegai/v1 inputs when
they are given.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
tests/mutants.rs runs the corpus on a device compiled from an edited kernel:
a rounding shift or its addend off by one, a tie rule flipped, a clamp bound
moved by one, a check that misses values above its range, a dropped carry or
cross term of a product, a sign rule, a post bias dropped, an index rule of
the transposed convolution, the convolution's padding edge, igdn's term
floor, the leaky shift of 32 or more, and two data-movement orders. Each must
give a result that differs from the committed one.
tests/corpus.rs also runs the 32-bit kernels on the graphs whose
certificate does not meet acc32, through a hidden entry point (run_at
refuses them): some differ from the interpreter, so the width a graph runs
at is load-bearing.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The integer operator set's graph operators on GPUs. WGSL has no 64-bit
integer, so the kernels use 32-bit words only: a graph whose certificate
meets acc32 runs on one word per value, with its two product intermediates
formed from 16-bit halves; every other graph of wai-ops/1-i32 meets acc64 and
runs on exact 64- and 128-bit arithmetic built from 32-bit words
(integer-operators §7.3). A graph with layernorm_c, l2norm, softmax, sigmoid
or elu runs on the CPU, and support() says which operator sent it there.
The host makes the interpreter's run-time checks in its order before the
device runs anything; a check tensor that leaves its range sets its
operator's flag, and the first flagged operator refuses the decode. Every
device passes an arithmetic probe against the host before it runs a graph.
Tests: the probe on a million cases, an edited product caught by it, and
every graph vector of ops-conformance that the subset covers, at both
widths, held to the committed expectations and the CPU interpreter.
Co-Authored-By: Claude Opus 5.5 <[email protected]>