- The dungeon framerate reports were right about the mechanism: the cost is CPU-side and it scales with NPC count, not with what's drawn. Two per-unit lanes were each 30–100x more expensive than the work they do. Measured at the reported Lower Blackrock Spire spot: 29.7 ms/frame, 72 CPU ms, before. - "Which room is this NPC in" scanned whole dungeon groups triangle by triangle — a spire stacks several 15k-face groups into any vertical column, so 37 moving NPCs cost 1.2 million triangle tests per frame. Each group's faces now sit in a column index built at load; same verdicts (pinned by exactness tests), 88k tests, the lane drops from 11.3 ms to 1.1 ms. - Animating one creature cost ~190 microseconds per frame in generic per-bone animation machinery — hash lookups and boxed curves per bone, mostly to produce constants. A direct pose evaluator now does the same math into the same joints for ~16 microseconds per rig, checked bone-for-bone against the old output across crossfades, overlays and masks. The reference animates every in-range unit with no view cull, and now so can we: a raid's worth of animating rigs (~450) costs ~4 CPU ms where it used to cost ~85. - Net at the reported spot: a flat 60 fps. The performance probes also learned to report CPU work (ms and %) instead of wall-clock fps, which is what makes these numbers repeatable on a busy machine — and comparable to the Mac report's own units. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
98 lines
5.7 KiB
TOML
98 lines
5.7 KiB
TOML
[package]
|
|
name = "benilla"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
license.workspace = true
|
|
description = "The Bevy app: terrain viewer -> integrated debug client"
|
|
|
|
[features]
|
|
# Opt-in Tracy profiling: `cargo run --features tracy` streams per-system `info_span!` markers (on the
|
|
# hot systems) + render-pass CPU timings to a Tracy capture (decision 0026 — the dev/player seam;
|
|
# a `docs/howto/running.md` this once cited never landed).
|
|
tracy = ["bevy/trace_tracy"]
|
|
|
|
[dependencies]
|
|
anyhow.workspace = true
|
|
# OS clipboard access for the UI EditBox copy/cut/paste chords (chat input). Already in the tree via
|
|
# bevy_egui; pinned to the same 3.x so there's one copy. Read on the main thread (the UI key feed is
|
|
# a NonSend system) — required for the macOS NSPasteboard path. Covers macOS, Windows, and Linux/BSD
|
|
# under X11; the Wayland backend is `smithay-clipboard` below (decision 0702).
|
|
arboard = "3"
|
|
benilla-ui = { path = "../benilla-ui" }
|
|
bevy.workspace = true
|
|
bevy_egui = "0.39"
|
|
# Zero-copy POD→bytes for the shared light storage buffer (one per-frame write_buffer). Already in
|
|
# the tree transitively; pinned to the same version as the dev-dep below.
|
|
bytemuck = { version = "1", features = ["derive"] }
|
|
# `getrusage` — whole-process CPU time (all threads), the perf probes' `cpu_ms`/`cpu_pct` metric
|
|
# (`perf::process_cpu_secs`). Wall-clock fps is unusable as a regression instrument on a machine
|
|
# running parallel sessions' builds; CPU-per-frame is, and it is also the number the Mac report
|
|
# is about ("250 % CPU at 59 fps"). Already in the tree transitively; declared so the call site is
|
|
# an honest dependency.
|
|
libc = "0.2"
|
|
# Resample varying-size layer BLPs to a uniform size for the terrain texture array; `png` so we can
|
|
# encode the cursor image into data an NSImage can load (macOS hardware cursor).
|
|
image = { version = "0.25", default-features = false, features = ["png"] }
|
|
# The net↔ECS bridge: a background IO thread streams typed `SessionEvent`s to the ECS over a
|
|
# channel, and outbound `ClientCommand`s back. crossbeam's Sender/Receiver are `Send + Sync + Clone`
|
|
# (std's mpsc Sender is `!Sync`, so it can't be a Bevy resource without a mutex — the very thing this
|
|
# bridge deletes). The canonical Bevy background-thread→channel→system idiom. See decision 0006.
|
|
crossbeam-channel = "0.5"
|
|
benilla-assets = { path = "../benilla-assets" }
|
|
benilla-formats = { path = "../benilla-formats" }
|
|
benilla-protocol = { path = "../benilla-protocol" }
|
|
# ECS-native physics: collider storage + broadphase BVH + shape-casts, with a thin custom kinematic
|
|
# character controller on top (decision 0009). Pinned 0.6: it targets Bevy 0.18 (verified single,
|
|
# unified bevy 0.18.1 in the tree); 0.7.0 jumps to Bevy 0.19 and would duplicate bevy. avian wraps
|
|
# parry under the hood, so adopting it lets us drop the *direct* parry3d dep once the bespoke
|
|
# CollisionWorld is gone. See docs… (decision 0007 superseded by 0009).
|
|
avian3d = "0.6"
|
|
# The glyph shaper + rasterizer for `FontString` text (decision 0068 §2, probe-verified in
|
|
# `probes/text-glyph`). Pinned to 0.16 — the exact version already in the tree transitively
|
|
# (`bevy_text`'s own dependency, see `Cargo.lock`) — so this is the *same* `cosmic-text` the decision
|
|
# already commits to, not a second copy. Used as a standalone shaper/rasterizer (`FontSystem` +
|
|
# `Buffer` + `SwashCache`) in `ui_text.rs`, never `bevy_text`'s `Text2d`/ECS integration (that path
|
|
# doesn't feed our custom z-ordered `UiQuad` stream).
|
|
cosmic-text = "0.16"
|
|
# The font database `cosmic-text` 0.16 uses (its `Source`/`ID`/`FaceInfo` appear in `ui_text.rs`'s
|
|
# public-in-crate types). Pinned to the exact version `cosmic-text` 0.16 depends on so there's one
|
|
# `fontdb` in the graph.
|
|
fontdb = "0.23"
|
|
kira = { version = "0.12", default-features = false, features = ["cpal", "mp3", "wav", "pcm", "adpcm"] }
|
|
mint = "0.5"
|
|
# The gossip greeting is a weighted random DRAW per menu-open, not a fixed pick (wow-re
|
|
# `gossip-npctext-law.md` — the reference re-rolls in its gossip handler), so the app needs a uniform
|
|
# source. Pinned to 0.8: the version `benilla-srp` already depends on, so this adds no crate.
|
|
rand = "0.8"
|
|
|
|
# Linux/BSD: the Wayland clipboard (decision 0702). We build with bevy's `wayland` feature, so on a
|
|
# Wayland session winit gives us a native Wayland window and `arboard` — X11-only without its
|
|
# non-default `wayland-data-control` feature — finds no X11 CLIPBOARD owner and every paste fails.
|
|
# smithay-clipboard is the right crate for a windowed app: it drives the *standard* `wl_data_device`
|
|
# off our own `wl_display`/seat, which every compositor supports. arboard's own Wayland feature would
|
|
# not do: it speaks `wlr-data-control`, a privileged manager protocol GNOME/Mutter deliberately
|
|
# doesn't implement. `raw-window-handle` (pinned to the 0.6 already in the tree via bevy_window, so
|
|
# this adds no crate) is only needed to read the `wl_display` out of bevy's `RawHandleWrapper`.
|
|
[target.'cfg(all(unix, not(any(target_os = "macos", target_os = "android"))))'.dependencies]
|
|
raw-window-handle = "0.6"
|
|
smithay-clipboard = "0.7"
|
|
|
|
# macOS: drive a native NSCursor for a crisp hardware cursor. winit drives the cursor via AppKit
|
|
# cursor-rects, which our continuous Metal render loop doesn't honor on mouse-move (custom cursor /
|
|
# hide revert to the arrow); we bypass it with NSCursor + NSWindow::disableCursorRects. See
|
|
# docs/knowledge/camera-control.md.
|
|
[target.'cfg(target_os = "macos")'.dependencies]
|
|
objc2 = "0.5"
|
|
objc2-app-kit = { version = "0.2", features = [
|
|
"NSApplication",
|
|
"NSResponder",
|
|
# NSApplicationActivationPolicy (bgwin's Accessory demotion) is declared in this header.
|
|
"NSRunningApplication",
|
|
"NSWindow",
|
|
"NSView",
|
|
"NSImage",
|
|
"NSCursor",
|
|
"NSEvent",
|
|
] }
|
|
objc2-foundation = { version = "0.2", features = ["NSArray", "NSData", "NSGeometry"] }
|