Skip to content

Commit

Permalink
Skinned extraction speedup (bevyengine#4428)
Browse files Browse the repository at this point in the history
# Objective

- While animating 501 https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/BrainStem, I noticed things were getting a little slow
- Looking in tracy, the system `extract_skinned_meshes` is taking a lot of time, with a mean duration of 15.17ms

## Solution

- ~~Use `Vec` instead of a `SmallVec`~~
- ~~Don't use an temporary variable~~
- Compute the affine matrix as an `Affine3A` instead
- Remove the `temp` vec

| |mean|
|---|---|
|base|15.17ms|
|~~vec~~|~~9.31ms~~|
|~~no temp variable~~|~~11.31ms~~|
|removing the temp vector|8.43ms|
|affine|13.21ms|
|all together|7.23ms|
  • Loading branch information
mockersf authored and ItsDoot committed Feb 1, 2023
1 parent ecfa22c commit 098471f
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 9 deletions.
1 change: 0 additions & 1 deletion crates/bevy_pbr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,3 @@ bevy_window = { path = "../bevy_window", version = "0.7.0-dev" }
bitflags = "1.2"
# direct dependency required for derive macro
bytemuck = { version = "1", features = ["derive"] }
smallvec = "1.0"
14 changes: 7 additions & 7 deletions crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ use bevy_render::{
RenderApp, RenderStage,
};
use bevy_transform::components::GlobalTransform;
use smallvec::SmallVec;
use std::num::NonZeroU64;

#[derive(Default)]
Expand Down Expand Up @@ -192,15 +191,16 @@ impl SkinnedMeshJoints {
let inverse_bindposes = inverse_bindposes.get(&skin.inverse_bindposes)?;
let bindposes = inverse_bindposes.iter();
let skin_joints = skin.joints.iter();
let mut temp =
SmallVec::<[Mat4; MAX_JOINTS]>::with_capacity(bindposes.len().min(MAX_JOINTS));
let start = buffer.len();
for (inverse_bindpose, joint) in bindposes.zip(skin_joints).take(MAX_JOINTS) {
let joint_matrix = joints.get(*joint).ok()?.compute_matrix();
temp.push(joint_matrix * *inverse_bindpose);
if let Ok(joint) = joints.get(*joint) {
buffer.push(joint.compute_affine() * *inverse_bindpose);
} else {
buffer.truncate(start);
return None;
}
}

let start = buffer.len();
buffer.extend(temp);
// Pad to 256 byte alignment
while buffer.len() % 4 != 0 {
buffer.push(Mat4::ZERO);
Expand Down
9 changes: 8 additions & 1 deletion crates/bevy_transform/src/components/global_transform.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::Transform;
use bevy_ecs::{component::Component, reflect::ReflectComponent};
use bevy_math::{const_vec3, Mat3, Mat4, Quat, Vec3};
use bevy_math::{const_vec3, Affine3A, Mat3, Mat4, Quat, Vec3};
use bevy_reflect::Reflect;
use std::ops::Mul;

Expand Down Expand Up @@ -128,6 +128,13 @@ impl GlobalTransform {
Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation)
}

/// Returns the 3d affine transformation from this transforms translation,
/// rotation, and scale.
#[inline]
pub fn compute_affine(&self) -> Affine3A {
Affine3A::from_scale_rotation_translation(self.scale, self.rotation, self.translation)
}

/// Get the unit vector in the local x direction
#[inline]
pub fn local_x(&self) -> Vec3 {
Expand Down

0 comments on commit 098471f

Please sign in to comment.