-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add SystemGraph as a handle-based method for explicitly creating system dependency graphs #2381
Conversation
It would be nice to add a test to ensue the is working as intended (it looks good to me, but tests always help) |
bors try |
tryBuild failed: |
Added two tests for ensuring that labels were generated in sequence when sequential is enabled and are not present otherwise. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to me. 👍
I'm still not the biggest fan of the global AtomicU32
, however, I don't know of another way to implement this without risks of label collision, so the current impl should suffice :)
Pushed a tentative implementation of a SystemGraph API loosely based on the SystemSet::as_sequential implementation. This should allow creating SystemSets that as_sequential allowed, but also support both of the fan-in/fan-out topologies as well. This implementation uses Arc/Mutex to ensure the resultant types are Send/Sync, but it's not completely necessary and can be done with Rc/RefCell instead. |
If we don't need Arc/Mutex and can get away with Rc/RefCell, we should imo :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like where this is headed 😄
I think using graph-like syntax to define the dependencies of systems is really nice.
Also, I also like the push to move away from a label-based API
Added a |
That will cause it to silently misbehave when adding >2^32 systems to a stage or if you add one system to one stage, 2^32 to another stage and then one to the first stage. Maybe you could have the counter local to each SystemGraph and panic on overflow. The label can then contain the local counter and a global SystemGraph counter. |
Implemented the panicking add and atomic graph/node ID split. Ultimately (as in, not in this PR), however, it's likely desirable to not use labels at all and just opt for writing the metadata to Parallel/ExclusiveSystemContainer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks really good :)
Sorry to be a bother haha, but the last thing I'd add is we should provide an example in the examples/
directory.
While the doc examples is a great start, actually seeing this in a runnable example would be very nice imo 😄
f95db5e
to
066bceb
Compare
bors try |
tryBuild failed: |
Made the main chunk of this PR available as an ecosystem crate in the form of bevy_system_graph. I do want some form of this as a first-party solution since this seems like something users generally need in a standardized way, but with stageless on the horizon I'll be closing this and opening a new PR once stageless has landed in some form. The fixes to |
# Objective `all_tuples` panics when the start count is set to anything other than 0 or 1. Fix this bug. ## Solution Originally part of #2381, this PR fixes the slice indexing used by the proc macro.
# Objective `all_tuples` panics when the start count is set to anything other than 0 or 1. Fix this bug. ## Solution Originally part of bevyengine#2381, this PR fixes the slice indexing used by the proc macro.
Objective
This PR adds
SystemGraph
as way to create system dependency graphs without explicit labeling.Motivation
It is currently difficult to force a strict system dependency graph. Currently the only way is manually set
label
,before
, and/orafter
on each system. This can lead to some particularly boilerplate/non-ergonomic builder code that is difficult to read, harder to think about, and more prone to programmer error. An example of this kind of code can be found here: https://github.com/HouraiTeahouse/FantasyCresendoBevy/blob/master/src/match/mod.rs#L248.Natural ordering invariants in game dev are common, and this should provide a simpler way to define those requirements. One notable case is the common simple sequential execution. Deterministic simulation is much easier to reason about with a single execution order, which should make it easier to create networked games that rely on determinism.
Solution
This PR adds
SystemGraph
. It provides a handle based API for creating dependency graphs, and can be converted into SystemSets. It enforces ordering by generatingNodeId
s, a newtype around u32, as a globally unique system label, that is then used to label and order systems relative to each other.This should be able to be used alongside "normal" SystemLabels to allow for ordering other systems relative any system in the SystemSet.
As for the choice to use AtomicU32, unless a developer is adding >2^32 systems to a stage, there will be no collisions. If multiple Apps are set up and recycled in the same process (i.e. headless server environments spinning up game instances), the static AtomicU32 uses wrapping adds when generating IDs, so there is no risk of crashing from an overflow.