Cost sweep
Where a frame goes, measured on the device it runs on. The sweep switches one thing off at a time (a group of meshes, the render targets, the shadows), or turns a resolution lever (hardware scaling flat; in a headset it puts the viewport scale and the foveation back to full, so the row is what each is saving), holds it for a couple of seconds, and records the frame time. What comes back is a ranked list: the things whose absence bought the most.
It exists because a headset has no GPU timer and no profiler, and guesses about its fill cost made on a desktop are wrong in both directions. It is a button in the Perf Stats panel (Cost sweep), so it runs inside the session.
const rows = await document.querySelector('tosi-b3d').costSweep()
// [{ name: 'baseline', ms: 71.4, p95: 83.3, saved: 0 }, { name: '- water', ms: 55.6, saved: 15.8 }, …]
Reading it
msis the median interval between frames;savedis the baseline minus that.- A headset's frame time moves in steps. The compositor shows a frame on a refresh or the one after, so at 72 Hz the readings are 13.9, 27.8, 41.7, 55.6 ms and so on. A saving smaller than a step can read as zero, and two small savings can add up to a step that neither shows alone.
- everythingis the floor: what the session costs with nothing drawn. If it is close to the baseline, the scene is not the problem.baseline againis the first measurement repeated at the end. If it differs from the first, the device drifted during the sweep (heat, a background task) and the rows are that much in doubt: run it again.- Groups are meshes sharing a material, named after it. The sweep takes the
twelve that could cover most of the view and lumps the rest as
other.
Each experiment is restored before the next. A sweep changes nothing for good.
Shader sweep, the button beside it, measures the ground shader's other
forms (costSweep(2, 'shaders')). It is separate because each row recompiles
every ground and decoration shader twice, which is the heaviest thing either
sweep does.
If it hangs the device
The first run on a Quest did. The sweep writes what it has measured, and the
name of the experiment it is about to start, to localStorage before each
one, once as it switches the experiment on and once as it starts measuring.
Reload the page and Perf Stats shows the rows it got and STOPPED with the
experiment that never finished. Runs are numbered and the last four are kept:
a run that hangs at once does not replace the rows of the one before it. The two headset levers run last for that
reason: they are the part no emulator can exercise.