About bevy-voxel-runtime
A Bevy 0.19 skill for developers implementing production voxel runtimes. It defines how edits, background meshing, and main-thread presentation work together, with revision checks and bounded queues to prevent stale results and frame spikes.
Key features
- 01Dirty-section tracking from mesh reads
- 02Revision and lifecycle token validation
- 03Coalesced priority work queues
- 04Bounded task starts and uploads
- 05Atomic mesh and collider swaps
- 06Runtime diagnostics and metrics
Use cases
- 01Handling boundary edits and halo samples
- 02Preventing stale results after unload and reload
- 03Managing bursts of voxel edits
- 04Budgeting mesh and collider uploads per frame
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ chrisgliddon/ bevy-skills --skill bevy-voxel-runtimeAfter installing, type/bevy-voxel-runtimein Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
references/apply-and-telemetry.mddirtying-and-revisions.mdqueues-and-priorities.mdDetails
From the project READMEBevy 0.19 — production voxel runtime
When to use this skill
- Edits can cross section boundaries or affect AO/lighting halo samples.
- Background remesh results can arrive after newer edits or unload/reload.
- Mesh/collider uploads, queue growth, or visible-section latency cause frame spikes.
- A prototype currently spawns one
AsyncComputeTaskPooltask per edit.
Use this skill after the block catalog and mesher are correct. It owns the runtime contract between edits, background meshing, and main-thread presentation. A worker result is only a proposal: the world revision must still accept it.
Canonical pattern
use bevy::prelude::*;
use std::collections::{BinaryHeap, HashMap, VecDeque};
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
struct SectionCoord { x: i32, y: i32, z: i32 }
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
struct WorkToken {
coord: SectionCoord,
revision: u64,
epoch: u64,
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
enum WorkState {
#[default]
Idle,
Queued,
Running,
RunningAndDirty,
Ready,
}
#[derive(Resource, Default)]
struct RemeshRuntime {
state: HashMap<SectionCoord, WorkState>,
latest: HashMap<SectionCoord, WorkToken>,
queued: BinaryHeap<PriorityEntry>,
completed: VecDeque<MeshResult>,
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
struct PriorityEntry {
// Include the token or queue generation so obsolete heap entries can be skipped.
priority: i64,
queue_generation: u64,
token: WorkToken,
}
struct MeshResult {
token: WorkToken,
mesh: MeshPayload,
collider: ColliderPayload,
}
struct MeshPayload;
struct ColliderPayload;
The worker input must own an immutable snapshot of the section plus required halo. Do not hold ECS borrows, asset borrows, or world locks across background work.
Gotchas and invariants
- Derive dirty fan-out from the mesher's actual read stencil. An interior edit dirties one section; a face-boundary edit also dirties the orthogonal neighbour. Ambient occlusion, smooth lighting, or other halo reads can require edge/corner neighbours too.
- Give every section a monotonic content revision and a lifecycle epoch. Capture both in each job and result. Never identify validity by coordinates alone.
- Keep at most one queued/running/pending-result intent per section. An edit during a running job marks that section dirty again; it does not spawn an equivalent job.
- Bound worker starts, completed-result storage, mesh/collider applications, upload bytes, and apply time. A thread pool is not backpressure.
- Re-check revision and epoch immediately before replacing presentation state. Reject stale results and count them; never let an old task overwrite a new edit.
- Swap the visible mesh and matching collider as one accepted revision. Do not show geometry from revision N while collision still represents N-1.
Runtime flow
edit -> compute dirty footprint -> bump revisions -> coalesce queue intent
-> priority scheduler -> bounded task starts -> completed-result queue
-> validate token -> bounded main-thread upload -> mesh+collider swap
\-> stale reject + metric
- Run edit collection and dirty marking in an explicitly ordered simulation set.
- Snapshot only when a worker slot is available; otherwise queued edits continue to coalesce without allocating task inputs.
- Prioritise visible collision-critical sections, then visible near-to-far sections, then off-screen work. Add age so distant work cannot starve forever.
- Apply uploads in
Update/PostUpdateor an exclusive system with a measured per-frame budget. GPU asset creation is main-world work, not worker work. - If a task finishes after unload/reload, the epoch mismatch rejects it even when the new section happens to have the same revision number.
Choose the relevant deep dive
| Problem | Read |
|---|---|
| Dirty footprints, halo semantics, revision and lifecycle tokens | Dirtying and revisions |
| Coalescing, priority heaps, task ownership, and queue bounds | Queues and priorities |
| Stale rejection, atomic presentation swaps, and diagnostics | Apply and telemetry |
Production review checklist
- A boundary edit remeshes every section whose mesh reads the changed sample.
- A same-coordinate unload/reload invalidates earlier results.
- A burst of 1,000 edits to one section creates bounded work, not 1,000 tasks.
- A stale result cannot mutate mesh, collider, revision, or readiness state.
- Catch-up work respects both count and byte/time budgets.
- Visible collision holes outrank distant cosmetic work without permanent starvation.
- Queue depth, age, task latency, stale count, coalesced count, upload bytes, and accepted revision are observable in a representative build.
See also
bevy-voxel-data— stable serialized block IDs and dense runtime palettes.bevy-voxel-pipeline— mesh generation andblock-mesh-rs.bevy-diagnostics-profiling— diagnostics, spans, and platform budgets.bevy-physics— collider ownership and physics scheduling.