From df8e2b5ffc4fee568711791b8abad9351c808b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Thu, 7 Apr 2022 16:16:36 +0000 Subject: [PATCH] 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| --- crates/bevy_pbr/Cargo.toml | 1 - crates/bevy_pbr/src/render/mesh.rs | 14 +++++++------- .../src/components/global_transform.rs | 9 ++++++++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/crates/bevy_pbr/Cargo.toml b/crates/bevy_pbr/Cargo.toml index e1496ac67c0a33..04f01ab963f6e0 100644 --- a/crates/bevy_pbr/Cargo.toml +++ b/crates/bevy_pbr/Cargo.toml @@ -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" diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 7743524eea7f30..7cff3f9d9fca8a 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -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); diff --git a/crates/bevy_transform/src/components/global_transform.rs b/crates/bevy_transform/src/components/global_transform.rs index f1bce519939149..c0e0aeac786e49 100644 --- a/crates/bevy_transform/src/components/global_transform.rs +++ b/crates/bevy_transform/src/components/global_transform.rs @@ -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 {