Skip to content

Commit

Permalink
Increment FrameCount in CoreStage::Last. (#7477)
Browse files Browse the repository at this point in the history
# Objective

During testing, I observed that the `FrameCount` resource (`bevy_core`) was being incremented by `FrameCountPlugin` non-deterministically, during update, subject to the whims of the execution order.

The effect was that the counter could and did change while a frame was still in flight, while user-systems were still executing.

## Solution

I have delayed the incrementing of the `FrameCount` resource to `CoreStage::Last`. The resource was described in the documentation as "*a count of rendered frames*" and, after my change, it actually will match that description.

## Changes

- `CoreStage::Last` was chosen so that the counter will be `0` during all earlier stages of the very first execution of the schedule.
- Documentation added declaring *when* the counter is incremented.
- Hint added, directing users towards `u32::wrapping_sub()` because integer overflow is reasonable to expect.

## Note

Even though this change might have a short time-to-live in light of the upcoming *Stageless* changes, I think this is worthwhile – at least as an in-code reminder that this counter should behave predictably.
  • Loading branch information
stephenmartindale committed Feb 2, 2023
1 parent e039825 commit be46d15
Showing 1 changed file with 10 additions and 3 deletions.
13 changes: 10 additions & 3 deletions crates/bevy_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,16 @@ impl Plugin for TaskPoolPlugin {
}
}

/// Keeps a count of rendered frames since the start of the app
/// Maintains a count of frames rendered since the start of the application.
///
/// Wraps to 0 when it reaches the maximum u32 value
/// [`FrameCount`] is incremented during [`CoreStage::Last`], providing predictable
/// behaviour: it will be 0 during the first update, 1 during the next, and so forth.
///
/// # Overflows
///
/// [`FrameCount`] will wrap to 0 after exceeding [`u32::MAX`]. Within reasonable
/// assumptions, one may exploit wrapping arithmetic to determine the number of frames
/// that have elapsed between two observations – see [`u32::wrapping_sub()`].
#[derive(Default, Resource, Clone, Copy)]
pub struct FrameCount(pub u32);

Expand All @@ -127,7 +134,7 @@ pub struct FrameCountPlugin;
impl Plugin for FrameCountPlugin {
fn build(&self, app: &mut App) {
app.init_resource::<FrameCount>();
app.add_system(update_frame_count);
app.add_system_to_stage(CoreStage::Last, update_frame_count);
}
}

Expand Down

0 comments on commit be46d15

Please sign in to comment.