Split The code is public; the app answers only to the crew.

The renderer owns the frame and nobody counts it: a per-frame draw budget the recording WebGL2 context enforces #196

open told opened this
opened this

The README says it outright in Measuring the tick: the simulation is 1% of a 64 Hz tick and "the renderer owns the rest of it". Nothing measures the rest of it. scripts/cost.ts alarms on world.update, #120 asks for the HUD's 2D call budget, and the 3D renderer — the thing that actually decides whether a laptop holds 60 fps — has no ceiling anywhere in the suite.

The harness is already built: renderer.test.ts drives createRenderer against a recording WebGL2 context (recorder()) and its frame() helper already counts drawElements/drawArrays per frame to prove relative claims ("one fewer body when you are the one being drawn"). What is missing is an absolute number for a stated worst case, written down and asserted, so that a change that doubles the draw calls fails the check instead of arriving in production as a stutter on somebody's laptop.

Done looks like

  • [ ] One named worst-case frame, built from a seeded world and documented in the test: ten players alive, the bomb planted, decals at capacity, a grenade in the air, tracers live, the radar and the scope both on.
  • [ ] A budget test asserting a ceiling for that frame on each of the counts that matter — draw calls (drawElements + drawArrays), useProgram, buffer uploads (bufferData/bufferSubData) and uniform sets — each ceiling a named constant with today's measured number in a comment beside it, set with the same "regression alarm, not a target" headroom scripts/cost.test.ts uses.
  • [ ] The counts are a pure function over the recorded calls, so the budget test reads as data and not as four hand-rolled filters.
  • [ ] A per-batch claim, not just a total: the ten bodies are still one draw each and the lines are still one batch, so a regression that stops batching fails with a message that says which batch broke.
  • [ ] No clock in any assertion — this counts calls, not milliseconds, so it cannot fail because CI was busy.
  • [ ] README's Measuring the tick gains the other half: the counted frame, the numbers, and the sentence that they are an alarm.

Files

src/client/renderer.test.ts (or a new src/client/draws.ts + test if the counting is worth its own concept), README.md.

Risks

  • A ceiling set too tight becomes a tax on every legitimate feature; set it with headroom and say what headroom you chose.
  • The worst case has to be reachable through the public API (createWorld + the renderer's draw) — if a state needs poking at internals to reach, it is the wrong worst case.
  • renderer.ts is 855 lines and #110's flashbang will add a pass to it; the budget must be a number a new pass can raise on purpose, with the raise visible in a diff.

Suggested: scout.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs