Material, mesh, skin extraction optimization (#17976)
# Objective The extraction systems for materials, meshes, and skins previously iterated over `RemovedComponents<ViewVisibility>` in addition to more specific variants like `RemovedComponents<MeshMaterial3d<M>>`. This caused each system to loop through and check many irrelevant despawned entities—sometimes multiple times. With many material types, this overhead added up and became noticeable in frames with many despawns. <img width="1091" alt="Screenshot 2025-02-21 at 10 28 01 AM" src="https://github.com/user-attachments/assets/63fec1c9-232c-45f6-9150-daf8751ecf85" /> ## Solution This PR removes superfluous `RemovedComponents` iteration for `ViewVisibility` and `GlobalTransform`, ensuring that we only iterate over the most specific `RemovedComponents` relevant to the system (e.g., material components, mesh components). This is guaranteed to match what the system originally collected. ### Before (red) / After (yellow): <img width="838" alt="Screenshot 2025-02-21 at 10 46 17 AM" src="https://github.com/user-attachments/assets/0e06b06d-7e91-4da5-a919-b843eb442a72" /> Log plot to highlight the long tail that this PR is addressing.
This commit is contained in:
parent
6fc4bc126d
commit
d40c5b54ae
@ -746,11 +746,11 @@ fn early_sweep_material_instances<M>(
|
||||
/// preparation for a new frame.
|
||||
pub(crate) fn late_sweep_material_instances(
|
||||
mut material_instances: ResMut<RenderMaterialInstances>,
|
||||
mut removed_visibilities_query: Extract<RemovedComponents<ViewVisibility>>,
|
||||
mut removed_meshes_query: Extract<RemovedComponents<Mesh3d>>,
|
||||
) {
|
||||
let last_change_tick = material_instances.current_change_tick;
|
||||
|
||||
for entity in removed_visibilities_query.read() {
|
||||
for entity in removed_meshes_query.read() {
|
||||
if let Entry::Occupied(occupied_entry) = material_instances.instances.entry(entity.into()) {
|
||||
// Only sweep the entry if it wasn't updated this frame. It's
|
||||
// possible that a `ViewVisibility` component was removed and
|
||||
|
@ -1452,8 +1452,6 @@ pub fn extract_meshes_for_gpu_building(
|
||||
>,
|
||||
>,
|
||||
all_meshes_query: Extract<Query<GpuMeshExtractionQuery>>,
|
||||
mut removed_visibilities_query: Extract<RemovedComponents<ViewVisibility>>,
|
||||
mut removed_global_transforms_query: Extract<RemovedComponents<GlobalTransform>>,
|
||||
mut removed_meshes_query: Extract<RemovedComponents<Mesh3d>>,
|
||||
gpu_culling_query: Extract<Query<(), (With<Camera>, Without<NoIndirectDrawing>)>>,
|
||||
meshes_to_reextract_next_frame: ResMut<MeshesToReextractNextFrame>,
|
||||
@ -1509,11 +1507,7 @@ pub fn extract_meshes_for_gpu_building(
|
||||
}
|
||||
|
||||
// Also record info about each mesh that became invisible.
|
||||
for entity in removed_visibilities_query
|
||||
.read()
|
||||
.chain(removed_global_transforms_query.read())
|
||||
.chain(removed_meshes_query.read())
|
||||
{
|
||||
for entity in removed_meshes_query.read() {
|
||||
// Only queue a mesh for removal if we didn't pick it up above.
|
||||
// It's possible that a necessary component was removed and re-added in
|
||||
// the same frame.
|
||||
|
@ -309,7 +309,6 @@ pub fn extract_skins(
|
||||
skinned_mesh_inverse_bindposes: Extract<Res<Assets<SkinnedMeshInverseBindposes>>>,
|
||||
changed_transforms: Extract<Query<(Entity, &GlobalTransform), Changed<GlobalTransform>>>,
|
||||
joints: Extract<Query<&GlobalTransform>>,
|
||||
mut removed_visibilities_query: Extract<RemovedComponents<ViewVisibility>>,
|
||||
mut removed_skinned_meshes_query: Extract<RemovedComponents<SkinnedMesh>>,
|
||||
) {
|
||||
let skin_uniforms = skin_uniforms.into_inner();
|
||||
@ -335,10 +334,7 @@ pub fn extract_skins(
|
||||
);
|
||||
|
||||
// Delete skins that became invisible.
|
||||
for skinned_mesh_entity in removed_visibilities_query
|
||||
.read()
|
||||
.chain(removed_skinned_meshes_query.read())
|
||||
{
|
||||
for skinned_mesh_entity in removed_skinned_meshes_query.read() {
|
||||
// Only remove a skin if we didn't pick it up in `add_or_delete_skins`.
|
||||
// It's possible that a necessary component was removed and re-added in
|
||||
// the same frame.
|
||||
|
@ -331,7 +331,6 @@ pub fn extract_mesh_materials_2d<M: Material2d>(
|
||||
Or<(Changed<ViewVisibility>, Changed<MeshMaterial2d<M>>)>,
|
||||
>,
|
||||
>,
|
||||
mut removed_visibilities_query: Extract<RemovedComponents<ViewVisibility>>,
|
||||
mut removed_materials_query: Extract<RemovedComponents<MeshMaterial2d<M>>>,
|
||||
) {
|
||||
for (entity, view_visibility, material) in &changed_meshes_query {
|
||||
@ -342,10 +341,7 @@ pub fn extract_mesh_materials_2d<M: Material2d>(
|
||||
}
|
||||
}
|
||||
|
||||
for entity in removed_visibilities_query
|
||||
.read()
|
||||
.chain(removed_materials_query.read())
|
||||
{
|
||||
for entity in removed_materials_query.read() {
|
||||
// Only queue a mesh for removal if we didn't pick it up above.
|
||||
// It's possible that a necessary component was removed and re-added in
|
||||
// the same frame.
|
||||
|
Loading…
Reference in New Issue
Block a user