mirror of
https://github.com/bevyengine/bevy
synced 2024-11-25 22:20:20 +00:00
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)
This commit is contained in:
parent
160bcc787c
commit
2893fc3e8b
1 changed files with 13 additions and 17 deletions
|
@ -254,11 +254,11 @@ pub fn ui_layout_system(
|
|||
|
||||
absolute_location += layout_location;
|
||||
|
||||
let rounded_size = round_layout_coords(absolute_location + layout_size)
|
||||
- round_layout_coords(absolute_location);
|
||||
let rounded_size = approx_round_layout_coords(absolute_location + layout_size)
|
||||
- approx_round_layout_coords(absolute_location);
|
||||
|
||||
let rounded_location =
|
||||
round_layout_coords(layout_location) + 0.5 * (rounded_size - parent_size);
|
||||
approx_round_layout_coords(layout_location) + 0.5 * (rounded_size - parent_size);
|
||||
|
||||
// only trigger change detection when the new values are different
|
||||
if node.calculated_size != rounded_size || node.unrounded_size != layout_size {
|
||||
|
@ -315,15 +315,8 @@ pub fn resolve_outlines_system(
|
|||
|
||||
#[inline]
|
||||
/// Round `value` to the nearest whole integer, with ties (values with a fractional part equal to 0.5) rounded towards positive infinity.
|
||||
fn round_ties_up(value: f32) -> f32 {
|
||||
if value.fract() != -0.5 {
|
||||
// The `round` function rounds ties away from zero. For positive numbers "away from zero" is towards positive infinity.
|
||||
// So for all positive values, and negative values with a fractional part not equal to 0.5, `round` returns the correct result.
|
||||
value.round()
|
||||
} else {
|
||||
// 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.
|
||||
value.ceil()
|
||||
}
|
||||
fn approx_round_ties_up(value: f32) -> f32 {
|
||||
(value + 0.5).floor()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -334,10 +327,10 @@ fn round_ties_up(value: f32) -> f32 {
|
|||
/// Example: The width between bounds of -50.5 and 49.5 before rounding is 100, using:
|
||||
/// - `f32::round`: width becomes 101 (rounds to -51 and 50).
|
||||
/// - `round_ties_up`: width is 100 (rounds to -50 and 50).
|
||||
fn round_layout_coords(value: Vec2) -> Vec2 {
|
||||
fn approx_round_layout_coords(value: Vec2) -> Vec2 {
|
||||
Vec2 {
|
||||
x: round_ties_up(value.x),
|
||||
y: round_ties_up(value.y),
|
||||
x: approx_round_ties_up(value.x),
|
||||
y: approx_round_ties_up(value.y),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -376,7 +369,7 @@ mod tests {
|
|||
use bevy_window::WindowResolution;
|
||||
use bevy_window::WindowScaleFactorChanged;
|
||||
|
||||
use crate::layout::round_layout_coords;
|
||||
use crate::layout::approx_round_layout_coords;
|
||||
use crate::layout::ui_surface::UiSurface;
|
||||
use crate::prelude::*;
|
||||
use crate::ui_layout_system;
|
||||
|
@ -385,7 +378,10 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn round_layout_coords_must_round_ties_up() {
|
||||
assert_eq!(round_layout_coords(vec2(-50.5, 49.5)), vec2(-50., 50.));
|
||||
assert_eq!(
|
||||
approx_round_layout_coords(vec2(-50.5, 49.5)),
|
||||
vec2(-50., 50.)
|
||||
);
|
||||
}
|
||||
|
||||
// these window dimensions are easy to convert to and from percentage values
|
||||
|
|
Loading…
Reference in a new issue