Skinned extraction speedup (#4428)

# 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|
This commit is contained in:
François 2022-04-07 16:16:36 +00:00
parent c5963b4fd5
commit 9d54f33974
3 changed files with 15 additions and 9 deletions

View file

@ -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"

View file

@ -26,7 +26,6 @@ use bevy_render::{
RenderApp, RenderStage,
};
use bevy_transform::components::GlobalTransform;
use smallvec::SmallVec;
use std::num::NonZeroU64;
#[derive(Default)]
@ -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);

View file

@ -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;
@ -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 {