Skip to content

Commit 2bf2a63

Browse files
authored
Merge pull request #26 from aevyrie/v0.8.0
Update for bevy 0.9
2 parents 337695a + 90ed15c commit 2bf2a63

File tree

6 files changed

+69
-45
lines changed

6 files changed

+69
-45
lines changed

Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bevy_framepace"
3-
version = "0.7.0"
3+
version = "0.8.0"
44
edition = "2021"
55
resolver = "2"
66
description = "Frame pacing and frame limiting for Bevy"
@@ -11,7 +11,7 @@ documentation = "https://docs.rs/bevy_framepace"
1111
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1212

1313
[dependencies]
14-
bevy = { version = "0.8", default-features = false, features = [
14+
bevy = { version = "0.9", default-features = false, features = [
1515
"bevy_render",
1616
"bevy_winit",
1717
] }
@@ -21,8 +21,8 @@ default = ["x11"]
2121
x11 = ["bevy/x11"]
2222

2323
[dev-dependencies]
24-
bevy_mod_picking = "0.9"
25-
bevy = { version = "0.8", default-features = false, features = [
24+
bevy_mod_picking = "0.10"
25+
bevy = { version = "0.9", default-features = false, features = [
2626
"bevy_ui",
2727
"bevy_text",
2828
"bevy_core_pipeline",

README.md

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
[![crates.io](https://img.shields.io/crates/v/bevy_framepace)](https://crates.io/crates/bevy_framepace)
88
[![docs.rs](https://docs.rs/bevy_framepace/badge.svg)](https://docs.rs/bevy_framepace)
99
[![CI](https://github.com/aevyrie/bevy_framepace/workflows/CI/badge.svg?branch=main)](https://github.com/aevyrie/bevy_framepace/actions?query=workflow%3A%22CI%22+branch%3Amain)
10-
[![Bevy tracking](https://img.shields.io/badge/Bevy%20tracking-main-lightblue)](https://github.com/bevyengine/bevy/blob/main/docs/plugins_guidelines.md#main-branch-tracking)
10+
[![Bevy](https://img.shields.io/badge/Bevy%20tracking-main-lightblue)](https://github.com/bevyengine/bevy/blob/main/docs/plugins_guidelines.md#main-branch-tracking)
1111

12-
<video src = "https://user-images.githubusercontent.com/2632925/164378172-faa136d5-e78f-4328-9962-afbf410753ce.mp4"></video>
12+
<video src =
13+
"https://user-images.githubusercontent.com/2632925/164378172-faa136d5-e78f-4328-9962-afbf410753ce.mp4"></video>
1314

1415
</div>
1516

@@ -23,10 +24,11 @@ app.add_plugin(bevy_framepace::FramepacePlugin::default())
2324

2425
By default, the plugin will automatically measure your framerate and use this for framepacing.
2526

26-
You can adjust the framerate limit when adding the plugin, or at runtime by modifying the`FramepacePlugin` resource. For example, to set the framerate limit to 30fps:
27+
You can adjust the framerate limit at runtime by modifying the`FramepaceSettings` resource. For
28+
example, to set the framerate limit to 30fps:
2729

2830
```rs
29-
settings.framerate_limit = FramerateLimit::Manual(30),
31+
settings.limiter = Limiter::from_framerate(30.0),
3032
```
3133

3234
See `demo.rs` in the examples folder, or run with:
@@ -36,7 +38,14 @@ cargo run --release --example demo
3638

3739
## How it works
3840

39-
The plugin works by recording how long it takes to render each frame, and sleeping the main thread until the desired frametime is reached. This ensures the next frame isn't started until the very last moment, delaying the event loop from restarting. By delaying the event loop, and thus input collection, this reduces motion-to-photon latency by moving reading input closer to rendering the frame.
41+
The plugin works by recording how long it takes to render each frame, and sleeping the main thread
42+
until the desired frametime is reached. This ensures the next frame isn't started until the very
43+
last moment, delaying the event loop from restarting. By delaying the event loop, and thus input
44+
collection, this reduces motion-to-photon latency by moving reading input closer to rendering the
45+
frame.
46+
47+
The `spin_sleep` dependency is needed for precise sleep times. The sleep function in the standard
48+
library is not accurate enough for this application, especially on Windows.
4049

4150

4251
## Bevy Version Support
@@ -45,24 +54,27 @@ I intend to track the `main` branch of Bevy. PRs supporting this are welcome!
4554

4655
| bevy | bevy_framepace |
4756
| ---- | -------------- |
57+
| 0.9 | 0.7 |
4858
| 0.8 | 0.5, 0.6 |
4959
| 0.7 | 0.4 |
5060
| 0.6 | 0.3 |
5161

5262

5363
## License
5464

55-
`bevy_framepace` is free, open source and permissively licensed! Except where noted (below and/or in individual files), all code in this repository is dual-licensed under either:
65+
`bevy_framepace` is free, open source and permissively licensed! Except where noted (below and/or in
66+
individual files), all code in this repository is dual-licensed under either:
5667

57-
* MIT License ([LICENSE-MIT](LICENSE-MIT) or [http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
58-
* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
68+
* MIT License ([LICENSE-MIT](LICENSE-MIT) or
69+
[http://opensource.org/licenses/MIT](http://opensource.org/licenses/MIT))
70+
* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
71+
[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0))
5972

60-
at your option. This means you can select the license you prefer! This dual-licensing approach is the de-facto standard in the Rust ecosystem and there are very good reasons to include both.
73+
at your option. This means you can select the license you prefer! This dual-licensing approach is
74+
the de-facto standard in the Rust ecosystem and there are very good reasons to include both.
6175

6276
### Your contributions
6377

64-
Unless you explicitly state otherwise,
65-
any contribution intentionally submitted for inclusion in the work by you,
66-
as defined in the Apache-2.0 license,
67-
shall be dual licensed as above,
68-
without any additional terms or conditions.
78+
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the
79+
work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
80+
additional terms or conditions.

assets/fonts/FiraMono-Medium.ttf

169 KB
Binary file not shown.

assets/fonts/FiraSans-Bold.ttf

-428 KB
Binary file not shown.

examples/demo.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fn toggle_plugin(mut settings: ResMut<FramepaceSettings>, input: Res<Input<KeyCo
3535
}
3636

3737
fn update_ui(mut text: Query<&mut Text, With<EnableText>>, settings: Res<FramepaceSettings>) {
38-
text.single_mut().sections[1].value = format!("{:?}", settings.limiter);
38+
text.single_mut().sections[1].value = format!("{}", settings.limiter);
3939
}
4040

4141
/// set up the scene
@@ -50,34 +50,36 @@ fn setup(
5050
.get_primary_mut()
5151
.unwrap()
5252
.set_cursor_icon(CursorIcon::Crosshair);
53-
commands
54-
.spawn_bundle(PbrBundle {
53+
commands.spawn((
54+
PbrBundle {
5555
mesh: meshes.add(Mesh::from(shape::Plane { size: 25.0 })),
56-
material: materials.add(Color::GRAY.into()),
56+
material: materials.add(Color::BLACK.into()),
5757
..Default::default()
58-
})
59-
.insert_bundle(PickableBundle::default());
60-
commands
61-
.spawn_bundle(Camera3dBundle {
58+
},
59+
PickableBundle::default(),
60+
));
61+
commands.spawn((
62+
Camera3dBundle {
6263
transform: Transform::from_xyz(0.0, 10.0, 0.0).looking_at(Vec3::ZERO, Vec3::Z),
6364
projection: Projection::Orthographic(OrthographicProjection {
6465
scale: 0.01,
6566
..Default::default()
6667
}),
6768
..Default::default()
68-
})
69-
.insert_bundle(PickingCameraBundle::default());
69+
},
70+
PickingCameraBundle::default(),
71+
));
7072
// UI
71-
let font = asset_server.load("fonts/FiraSans-Bold.ttf");
73+
let font = asset_server.load("fonts/FiraMono-Medium.ttf");
7274
let style = TextStyle {
73-
font: font,
75+
font,
7476
font_size: 40.0,
7577
color: Color::WHITE,
7678
};
77-
commands
78-
.spawn_bundle(TextBundle {
79+
commands.spawn((
80+
TextBundle {
7981
style: Style {
80-
align_self: AlignSelf::FlexEnd,
82+
align_self: AlignSelf::FlexStart,
8183
..default()
8284
},
8385
text: Text {
@@ -99,6 +101,7 @@ fn setup(
99101
..default()
100102
},
101103
..default()
102-
})
103-
.insert(EnableText);
104+
},
105+
EnableText,
106+
));
104107
}

src/lib.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,13 @@ impl Plugin for FramepacePlugin {
5858
.add_system_to_stage(
5959
RenderStage::Cleanup,
6060
// We need this system to run at the end, immediately before the event loop restarts
61-
framerate_limiter.exclusive_system().at_end(),
61+
framerate_limiter.at_end(),
6262
);
6363
}
6464
}
6565

6666
/// Framepacing plugin configuration.
67-
#[derive(Debug, Clone)]
67+
#[derive(Debug, Clone, Resource)]
6868
pub struct FramepaceSettings {
6969
/// Configures the framerate limiting strategy.
7070
pub limiter: Limiter,
@@ -109,10 +109,21 @@ impl Limiter {
109109
}
110110
}
111111

112-
#[derive(Debug, Default, Clone)]
112+
impl std::fmt::Display for Limiter {
113+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
114+
let output = match self {
115+
Limiter::Auto => "Auto".into(),
116+
Limiter::Manual(t) => format!("{:.2} fps", 1.0 / t.as_secs_f32()),
117+
Limiter::Off => "Off".into(),
118+
};
119+
write!(f, "{}", output)
120+
}
121+
}
122+
123+
#[derive(Debug, Default, Clone, Resource)]
113124
struct FrametimeLimit(Duration);
114125

115-
#[derive(Debug)]
126+
#[derive(Debug, Resource)]
116127
struct FrameTimer {
117128
render_end: Instant,
118129
}
@@ -155,11 +166,9 @@ fn detect_frametime(winit: NonSend<WinitWindows>, windows: Res<Windows>) -> Opti
155166
let monitor = winit
156167
.get_window(windows.get_primary()?.id())?
157168
.current_monitor()?;
158-
// We need to subtract 0.5 here because winit only reports framerate to the nearest integer. To
159-
// prevent frames building up, adding latency, we need to use the most conservative possible
160-
// refresh rate that could round up to the integer value reported by winit.
161-
let best_framerate = bevy::winit::get_best_videomode(&monitor).refresh_rate() as f64 - 0.5;
162-
let best_frametime = Duration::from_secs_f64(1.0 / best_framerate);
169+
let best_framerate_mhz =
170+
bevy::winit::get_best_videomode(&monitor).refresh_rate_millihertz() as f32;
171+
let best_frametime = Duration::from_secs_f32(1000.0 / best_framerate_mhz);
163172
Some(best_frametime)
164173
}
165174

@@ -175,7 +184,7 @@ fn extract_resources(
175184
}
176185

177186
/// Holds frame time measurements for framepacing diagnostics
178-
#[derive(Clone, Debug)]
187+
#[derive(Clone, Debug, Resource)]
179188
pub struct FramePaceStats {
180189
oversleep: Arc<Mutex<VecDeque<Duration>>>,
181190
frametime: Arc<Mutex<Duration>>,

0 commit comments

Comments
 (0)