Skip to content

Commit 2893fc3

Browse files
authored
Using simple approx round up in ui_layout_system (#14079)
# Objective - built-in `f32::round `is slow - splits from #14064 ## Solution - using a simple floor instead of round ## Testing - I am not an expert on floating-point values, but I enumerated all f32 values to test for potential errors compared to the previous function. [rust playground](https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=0d8ed5604499e7bd9c61ce57d47e8c06) three cases where the behavior differs between the new and previous functions: | value | previous | new | |---|---|---| | [-0.5,0) | -0 | +0 | | 0.49999997 | 0 | 1 | | +-8388609 | 8388609 | 8388610 | ## Performance ![image](https://github.com/bevyengine/bevy/assets/45868716/1910f342-e55b-4f5c-851c-24a142d5c72e)
1 parent 160bcc7 commit 2893fc3

File tree

1 file changed

+13
-17
lines changed
  • crates/bevy_ui/src/layout

1 file changed

+13
-17
lines changed

crates/bevy_ui/src/layout/mod.rs

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -254,11 +254,11 @@ pub fn ui_layout_system(
254254

255255
absolute_location += layout_location;
256256

257-
let rounded_size = round_layout_coords(absolute_location + layout_size)
258-
- round_layout_coords(absolute_location);
257+
let rounded_size = approx_round_layout_coords(absolute_location + layout_size)
258+
- approx_round_layout_coords(absolute_location);
259259

260260
let rounded_location =
261-
round_layout_coords(layout_location) + 0.5 * (rounded_size - parent_size);
261+
approx_round_layout_coords(layout_location) + 0.5 * (rounded_size - parent_size);
262262

263263
// only trigger change detection when the new values are different
264264
if node.calculated_size != rounded_size || node.unrounded_size != layout_size {
@@ -315,15 +315,8 @@ pub fn resolve_outlines_system(
315315

316316
#[inline]
317317
/// Round `value` to the nearest whole integer, with ties (values with a fractional part equal to 0.5) rounded towards positive infinity.
318-
fn round_ties_up(value: f32) -> f32 {
319-
if value.fract() != -0.5 {
320-
// The `round` function rounds ties away from zero. For positive numbers "away from zero" is towards positive infinity.
321-
// So for all positive values, and negative values with a fractional part not equal to 0.5, `round` returns the correct result.
322-
value.round()
323-
} else {
324-
// In the remaining cases, where `value` is negative and its fractional part is equal to 0.5, we use `ceil` to round it up towards positive infinity.
325-
value.ceil()
326-
}
318+
fn approx_round_ties_up(value: f32) -> f32 {
319+
(value + 0.5).floor()
327320
}
328321

329322
#[inline]
@@ -334,10 +327,10 @@ fn round_ties_up(value: f32) -> f32 {
334327
/// Example: The width between bounds of -50.5 and 49.5 before rounding is 100, using:
335328
/// - `f32::round`: width becomes 101 (rounds to -51 and 50).
336329
/// - `round_ties_up`: width is 100 (rounds to -50 and 50).
337-
fn round_layout_coords(value: Vec2) -> Vec2 {
330+
fn approx_round_layout_coords(value: Vec2) -> Vec2 {
338331
Vec2 {
339-
x: round_ties_up(value.x),
340-
y: round_ties_up(value.y),
332+
x: approx_round_ties_up(value.x),
333+
y: approx_round_ties_up(value.y),
341334
}
342335
}
343336

@@ -376,7 +369,7 @@ mod tests {
376369
use bevy_window::WindowResolution;
377370
use bevy_window::WindowScaleFactorChanged;
378371

379-
use crate::layout::round_layout_coords;
372+
use crate::layout::approx_round_layout_coords;
380373
use crate::layout::ui_surface::UiSurface;
381374
use crate::prelude::*;
382375
use crate::ui_layout_system;
@@ -385,7 +378,10 @@ mod tests {
385378

386379
#[test]
387380
fn round_layout_coords_must_round_ties_up() {
388-
assert_eq!(round_layout_coords(vec2(-50.5, 49.5)), vec2(-50., 50.));
381+
assert_eq!(
382+
approx_round_layout_coords(vec2(-50.5, 49.5)),
383+
vec2(-50., 50.)
384+
);
389385
}
390386

391387
// these window dimensions are easy to convert to and from percentage values

0 commit comments

Comments
 (0)