From 272e02992d2380001826febc5780a8ea23b01965 Mon Sep 17 00:00:00 2001 From: james7132 <contact@jamessliu.com> Date: Fri, 2 Dec 2022 22:06:22 -0800 Subject: [PATCH 1/5] Directly extract skinned mesh joints into the BufferVec --- crates/bevy_pbr/src/render/mesh.rs | 31 ++++++------------- .../src/render_resource/buffer_vec.rs | 4 +++ 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 15fa70b81e8df..7892697c36e31 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -172,11 +172,6 @@ pub fn extract_meshes( commands.insert_or_spawn_batch(not_caster_commands); } -#[derive(Resource, Debug, Default)] -pub struct ExtractedJoints { - pub buffer: Vec<Mat4>, -} - #[derive(Component)] pub struct SkinnedMeshJoints { pub index: u32, @@ -188,7 +183,7 @@ impl SkinnedMeshJoints { skin: &SkinnedMesh, inverse_bindposes: &Assets<SkinnedMeshInverseBindposes>, joints: &Query<&GlobalTransform>, - buffer: &mut Vec<Mat4>, + buffer: &mut BufferVec<Mat4>, ) -> Option<Self> { let inverse_bindposes = inverse_bindposes.get(&skin.inverse_bindposes)?; let bindposes = inverse_bindposes.iter(); @@ -221,13 +216,13 @@ impl SkinnedMeshJoints { pub fn extract_skinned_meshes( mut commands: Commands, mut previous_len: Local<usize>, - mut previous_joint_len: Local<usize>, + mut uniform: ResMut<SkinnedMeshUniform>, query: Extract<Query<(Entity, &ComputedVisibility, &SkinnedMesh)>>, inverse_bindposes: Extract<Res<Assets<SkinnedMeshInverseBindposes>>>, joint_query: Extract<Query<&GlobalTransform>>, ) { + uniform.buffer.clear(); let mut values = Vec::with_capacity(*previous_len); - let mut joints = Vec::with_capacity(*previous_joint_len); let mut last_start = 0; for (entity, computed_visibility, skin) in &query { @@ -236,7 +231,7 @@ pub fn extract_skinned_meshes( } // PERF: This can be expensive, can we move this to prepare? if let Some(skinned_joints) = - SkinnedMeshJoints::build(skin, &inverse_bindposes, &joint_query, &mut joints) + SkinnedMeshJoints::build(skin, &inverse_bindposes, &joint_query, &mut uniform.buffer) { last_start = last_start.max(skinned_joints.index as usize); values.push((entity, skinned_joints.to_buffer_index())); @@ -244,13 +239,11 @@ pub fn extract_skinned_meshes( } // Pad out the buffer to ensure that there's enough space for bindings - while joints.len() - last_start < MAX_JOINTS { - joints.push(Mat4::ZERO); + while uniform.buffer.len() - last_start < MAX_JOINTS { + uniform.buffer.push(Mat4::ZERO); } *previous_len = values.len(); - *previous_joint_len = joints.len(); - commands.insert_resource(ExtractedJoints { buffer: joints }); commands.insert_or_spawn_batch(values); } @@ -779,20 +772,14 @@ impl Default for SkinnedMeshUniform { pub fn prepare_skinned_meshes( render_device: Res<RenderDevice>, render_queue: Res<RenderQueue>, - extracted_joints: Res<ExtractedJoints>, mut skinned_mesh_uniform: ResMut<SkinnedMeshUniform>, ) { - if extracted_joints.buffer.is_empty() { + if skinned_mesh_uniform.buffer.is_empty() { return; } - skinned_mesh_uniform.buffer.clear(); - skinned_mesh_uniform - .buffer - .reserve(extracted_joints.buffer.len(), &render_device); - for joint in &extracted_joints.buffer { - skinned_mesh_uniform.buffer.push(*joint); - } + let len = skinned_mesh_uniform.buffer.len(); + skinned_mesh_uniform.buffer.reserve(len, &render_device); skinned_mesh_uniform .buffer .write_buffer(&render_device, &render_queue); diff --git a/crates/bevy_render/src/render_resource/buffer_vec.rs b/crates/bevy_render/src/render_resource/buffer_vec.rs index 1d3086796dbc5..d920afbf397dd 100644 --- a/crates/bevy_render/src/render_resource/buffer_vec.rs +++ b/crates/bevy_render/src/render_resource/buffer_vec.rs @@ -131,6 +131,10 @@ impl<T: Pod> BufferVec<T> { } } + pub fn truncate(&mut self, len: usize) { + self.values.truncate(len); + } + pub fn clear(&mut self) { self.values.clear(); } From f07dccb43b3c4f958633dddd1e5d8ffbd8807a2a Mon Sep 17 00:00:00 2001 From: james7132 <contact@jamessliu.com> Date: Thu, 8 Dec 2022 21:48:35 -0800 Subject: [PATCH 2/5] Use extend instead of push --- crates/bevy_pbr/src/render/mesh.rs | 19 ++++++++++--------- .../src/render_resource/buffer_vec.rs | 7 +++++++ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 5efb3fd29329f..0c09d8c040fc4 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -186,16 +186,17 @@ impl SkinnedMeshJoints { buffer: &mut BufferVec<Mat4>, ) -> Option<Self> { let inverse_bindposes = inverse_bindposes.get(&skin.inverse_bindposes)?; - let bindposes = inverse_bindposes.iter(); - let skin_joints = skin.joints.iter(); let start = buffer.len(); - for (inverse_bindpose, joint) in bindposes.zip(skin_joints).take(MAX_JOINTS) { - if let Ok(joint) = joints.get(*joint) { - buffer.push(joint.affine() * *inverse_bindpose); - } else { - buffer.truncate(start); - return None; - } + let target = start + skin.joints.len().min(MAX_JOINTS); + buffer.extend( + joints + .iter_many(&skin.joints) + .zip(inverse_bindposes.iter()) + .map(|(joint, bindpose)| joint.affine() * *bindpose), + ); + if buffer.len() != target { + buffer.truncate(start); + return None; } // Pad to 256 byte alignment diff --git a/crates/bevy_render/src/render_resource/buffer_vec.rs b/crates/bevy_render/src/render_resource/buffer_vec.rs index d920afbf397dd..4684e65b27b4d 100644 --- a/crates/bevy_render/src/render_resource/buffer_vec.rs +++ b/crates/bevy_render/src/render_resource/buffer_vec.rs @@ -139,3 +139,10 @@ impl<T: Pod> BufferVec<T> { self.values.clear(); } } + +impl<T: Pod> Extend<T> for BufferVec<T> { + #[inline] + fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) { + self.values.extend(iter) + } +} From 935fe6c397df2eb9461227a6617e3847bf20688b Mon Sep 17 00:00:00 2001 From: james7132 <contact@jamessliu.com> Date: Sat, 10 Dec 2022 22:32:02 -0800 Subject: [PATCH 3/5] Formatting --- crates/bevy_render/src/render_resource/buffer_vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/render_resource/buffer_vec.rs b/crates/bevy_render/src/render_resource/buffer_vec.rs index 4684e65b27b4d..72f1b08a9b503 100644 --- a/crates/bevy_render/src/render_resource/buffer_vec.rs +++ b/crates/bevy_render/src/render_resource/buffer_vec.rs @@ -142,7 +142,7 @@ impl<T: Pod> BufferVec<T> { impl<T: Pod> Extend<T> for BufferVec<T> { #[inline] - fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) { + fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { self.values.extend(iter) } } From 4c203b3ccb92b4d0fc4af58c5130cddf2bddae5c Mon Sep 17 00:00:00 2001 From: james7132 <contact@jamessliu.com> Date: Sun, 11 Dec 2022 23:09:31 -0800 Subject: [PATCH 4/5] Explain why we're truncating. --- crates/bevy_pbr/src/render/mesh.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 0c09d8c040fc4..bf3b181913a70 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -194,6 +194,8 @@ impl SkinnedMeshJoints { .zip(inverse_bindposes.iter()) .map(|(joint, bindpose)| joint.affine() * *bindpose), ); + // iter_many will skip any failed fetches. This will cause it to assign the wrong bones, + // so just bail by truncating to the start. if buffer.len() != target { buffer.truncate(start); return None; From 92b13ef19a0e9e9896aab4e3ee1b368c987ce436 Mon Sep 17 00:00:00 2001 From: james7132 <contact@jamessliu.com> Date: Sun, 11 Dec 2022 23:12:22 -0800 Subject: [PATCH 5/5] Fix CI --- crates/bevy_render/src/render_resource/buffer_vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/render_resource/buffer_vec.rs b/crates/bevy_render/src/render_resource/buffer_vec.rs index 72f1b08a9b503..4a3c744e071c9 100644 --- a/crates/bevy_render/src/render_resource/buffer_vec.rs +++ b/crates/bevy_render/src/render_resource/buffer_vec.rs @@ -143,6 +143,6 @@ impl<T: Pod> BufferVec<T> { impl<T: Pod> Extend<T> for BufferVec<T> { #[inline] fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { - self.values.extend(iter) + self.values.extend(iter); } }