Skip to content

feat: read only script system parameters (+ access declaration fixes) - #648

Open
makspll wants to merge 6 commits into
agent/script-systems-stabilisefrom
agent/script-systems-read-access
Open

makspll wants to merge 6 commits into
agent/script-systems-stabilisefrom
agent/script-systems-read-access

Conversation

@makspll

@makspll makspll commented Oct 22, 2026 •

Copy link
Copy Markdown
Owner

Stacked on #647. Second of the script system PRs.

Feature

  • system_builder(..):resource_read(R) and world.query():component_read(C) are declared to Bevy as reads, so readers can run in parallel. resource / component stay read + write.
  • The guard enforces this with a read-only bitset in AccessByteSet (from_allowed_lists(read_write, read_only)), checked only by component write claims, so read claims pay nothing.

Fixes found on the way (all pre-existing)

  • Query components were declared as reads (ref_id) while scripts could write them, so two script systems writing C ran in parallel. Written components now use mut_id. as_query_state takes declare_writes, because world.query() builds an EntityRef query, which can't mix with writes.
  • Resources were declared as FilteredAccess::matches_nothing() + write. An access matching nothing is compatible with everything, so two script systems writing the same resource ran in parallel. They now use add_resource_read / add_resource_write, like Res / ResMut.
  • get_all_access_ids reported every access as a write: the read and write sets were swapped. The flag was unused until now.
  • Claim count overflow: the 64th concurrent claim wrapped the count to 0, letting a write alias live reads. Claims now fail at the max count (63).

Tests

  • Rust: readers are compatible with each other, writers are not.
  • Rust: read-only map entries reject writes, also after release_all_accesses, and claims stop at the max count.
  • Lua: read_only_parameters_cannot_be_written.lua.

Perf

A/B against #647, medians of 6 interleaved rounds: field get 418 → 387 ns, field set 454 → 450 ns, component/access 2514 → 2417 ns, resource/access 2185 → 2145 ns, i.e. no regression. A first version put a write-forbidden bit into AccessBitField, which made field get 8% slower and field set 4% slower, so it was replaced by the bitset.

🤖 Generated with Claude Code

@makspll
makspll added this pull request to stack #649 October 22, 2026 13:33
@semanticdiff-com

semanticdiff-com Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

🐰 Bencher Report

ProjectBevy Scripting
Branchagent/script-systems-read-access
Testbedlinux-gha

⚠️ WARNING: Truncated view!

The full continuous benchmarking report exceeds the maximum length allowed on this platform.

🐰 View full continuous benchmarking report in Bencher

- `resource_read` / `component_read` declare read access to bevy and to the
  guard, `resource` / `component` stay read and write
- the guard's AccessBitField gets a write forbidden bit (count: 5 bits) and
  claims fail at the max count instead of overflowing to 0
- fix: query components were declared to bevy as reads while scripts could
  write them, resources as accessing nothing (never conflicting)
- fix: get_all_access_ids reported every access as a write
…rite claims

The write forbidden bit in AccessBitField made field get/set 4-8% slower,
the bitset leaves read claims untouched and keeps the max claim count at 63.
@makspll
makspll force-pushed the agent/script-systems-read-access branch from ef09487 to ee5f700 Compare October 23, 2026 12:07
@makspll
makspll marked this pull request as ready for review October 23, 2026 15:00

This branch has not been deployed

No deployments
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