Skip to content

BuildETA: skip labels that cannot be on screen, keep the label text - #5886

Open
moss-orbit-9f339e wants to merge 1 commit into
ZeroK-RTS:masterfrom
moss-orbit-9f339e:upstream/buildeta
Open

moss-orbit-9f339e wants to merge 1 commit into
ZeroK-RTS:masterfrom
moss-orbit-9f339e:upstream/buildeta

Conversation

@moss-orbit-9f339e

Copy link
Copy Markdown
Contributor

BuildETA formatted a label and made six GL calls for every unit under construction on every drawn frame, also far off screen. This change skips labels that cannot touch the view, and keeps the formatted text until its value changes.

Behaviour: no visible change. A skipped label cannot make a pixel, and the kept text is the same as the formatted text.

Testing (Windows, RTX 3080, master ee8950e):

  • Replay of a ~1500-unit game (Tartar Steppe, 18:00), 60 s at 1x, CPU-bound settings (1920x1080, no MSAA), two interleaved pairs: FPS 76.3 → 82.4 and 77.1 → 82.6 (+8.0%, +7.2%). The slowest 1% of frames: 41.6 → 43.0 and 42.6 → 43.4 FPS.
  • Nuclear Winter replay at full graphics: no Lua errors. The checksums, unit counts and screenshot are the same as master.
  • Offline test: old and new widget with random builds and views (20 seeds × 600 frames). Every label that can touch the view draws the same.
  • I watched these test runs.

Related: #3781

AI disclosure: Claude Code wrote this change and its tests. I reviewed the change.

DrawWorld formatted a new label string, read two unit rules params and issued
PushMatrix/Translate/Billboard/Translate/Text/PopMatrix for every tracked unit
on every drawn frame, including units far off screen. In a ~1100-unit replay
the widget cost 41 ms per second of main thread at 1x (widget profiler,
62 FPS), and turning it off gave +3% FPS.

- Labels are skipped when a sphere around the label anchor (the same
  x, y + yoffset*heightMult, z the label is drawn at) is outside the view
  (Spring.IsSphereInView, the camera frustum the world is drawn with). The
  radius, 5 + fontSize * (#label + 2), contains the whole billboarded label:
  the 5 elmo offset, a centred line of at most #label glyphs (bytes, including
  colour codes) of under 1 em each, and its height. A skipped label cannot
  produce a pixel. The unit-icon and no_eta_display checks follow for labels
  that pass, so only on-screen units read no_eta_display.
- The label string is cached per unit and rebuilt only when its whole-second
  value, the reversing flag or the translation changes. %d truncates, and
  timeLeft stays above -1 (it is a positive estimate, averaged with the
  previous one minus dt < 2 s), where truncation and floor give the same text
  for the same floor(timeLeft). An unknown ETA ("???") has its own key.

Rules params are still read on every drawn frame, so a scale or
no_eta_display change shows exactly when it did before.

Verified with a stub-engine A/B harness (old vs new widget, random builds,
reverse builds, stockpilers, model scales, hidden/icon flags, translation
changes, random view boxes; 20 seeds x 600 frames): every label of the old
widget that can touch the view is drawn by the new one with the same string
and transform, and the new draws are an ordered subset of the old ones
(118k labels drawn by the old widget, 9.4k by the new). Mutants with a
smaller sphere or a shared "???" key are caught. lua5.1 syntax check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant