bevy/crates
Patrick Walton d55f47d00a Unify RenderMaterialInstances and RenderMeshMaterialIds, and fix an associated race condition. (#18734)
Currently, `RenderMaterialInstances` and `RenderMeshMaterialIds` are
very similar render-world resources: the former maps main world meshes
to typed material asset IDs, and the latter maps main world meshes to
untyped material asset IDs. This is needlessly-complex and wasteful, so
this patch unifies the two in favor of a single untyped
`RenderMaterialInstances` resource.

This patch also fixes a subtle issue that could cause mesh materials to
be incorrect if a `MeshMaterial3d<A>` was removed and replaced with a
`MeshMaterial3d<B>` material in the same frame. The problematic pattern
looks like:

1. `extract_mesh_materials<B>` runs and, seeing the
`Changed<MeshMaterial3d<B>>` condition, adds an entry mapping the mesh
to the new material to the untyped `RenderMeshMaterialIds`.

2. `extract_mesh_materials<A>` runs and, seeing that the entity is
present in `RemovedComponents<MeshMaterial3d<A>>`, removes the entry
from `RenderMeshMaterialIds`.

3. The material slot is now empty, and the mesh will show up as whatever
material happens to be in slot 0 in the material data slab.

This commit fixes the issue by splitting out `extract_mesh_materials`
into *three* phases: *extraction*, *early sweeping*, and *late
sweeping*, which run in that order:

1. The *extraction* system, which runs for each material, updates
`RenderMaterialInstances` records whenever `MeshMaterial3d` components
change, and updates a change tick so that the following system will know
not to remove it.

2. The *early sweeping* system, which runs for each material, processes
entities present in `RemovedComponents<MeshMaterial3d>` and removes each
such entity's record from `RenderMeshInstances` only if the extraction
system didn't update it this frame. This system runs after *all*
extraction systems have completed, fixing the race condition.

3. The *late sweeping* system, which runs only once regardless of the
number of materials in the scene, processes entities present in
`RemovedComponents<ViewVisibility>` and, as in the early sweeping phase,
removes each such entity's record from `RenderMeshInstances` only if the
extraction system didn't update it this frame. At the end, the late
sweeping system updates the change tick.

Because this pattern happens relatively frequently, I think this PR
should land for 0.16.
2025-04-10 01:19:34 +02:00
..
bevy_a11y Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_animation Add PartialEq and Hash reflections for AnimationNodeIndex (#18718) 2025-04-04 23:16:49 +02:00
bevy_app Add Default for all schedule labels (#18731) 2025-04-09 00:21:40 +02:00
bevy_asset Add #[deprecated(since = "0.16.0", ...)] to items missing it (#18702) 2025-04-03 21:46:46 +02:00
bevy_audio Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_color Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_core_pipeline Remove WebGL padding from MotionBlur (#18727) 2025-04-09 00:21:41 +02:00
bevy_derive Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_dev_tools Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_diagnostic Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_dylib Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_ecs Change with_related to work with a Bundle and added with_relationships method (#18699) 2025-04-10 01:19:33 +02:00
bevy_encase_derive Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_gilrs Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_gizmos Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_gltf Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_image Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_input Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_input_focus Switch ChildOf back to tuple struct (#18672) 2025-04-03 21:45:43 +02:00
bevy_internal Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_log Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_macro_utils Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_math Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_mesh Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_mikktspace Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_pbr Unify RenderMaterialInstances and RenderMeshMaterialIds, and fix an associated race condition. (#18734) 2025-04-10 01:19:34 +02:00
bevy_picking Newtype hashbrown (#18694) 2025-04-09 00:21:41 +02:00
bevy_platform_support Newtype hashbrown (#18694) 2025-04-09 00:21:41 +02:00
bevy_ptr Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_reflect Add accessors to DynamicEnum for the DynamicVariant (#18693) 2025-04-09 00:21:40 +02:00
bevy_remote Add Default for all schedule labels (#18731) 2025-04-09 00:21:40 +02:00
bevy_render Initialize pre-processing pipelines only when culling is enabled. (#18759) 2025-04-10 01:19:34 +02:00
bevy_scene Newtype hashbrown (#18694) 2025-04-09 00:21:41 +02:00
bevy_sprite Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_state Add Default for all schedule labels (#18731) 2025-04-09 00:21:40 +02:00
bevy_tasks Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_text Switch ChildOf back to tuple struct (#18672) 2025-04-03 21:45:43 +02:00
bevy_time Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_transform Switch ChildOf back to tuple struct (#18672) 2025-04-03 21:45:43 +02:00
bevy_ui Fix AccessKit node bounds (#18706) 2025-04-09 00:21:41 +02:00
bevy_utils Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_window Release 0.16.0-rc.3 2025-03-31 23:07:43 +02:00
bevy_winit Switch ChildOf back to tuple struct (#18672) 2025-04-03 21:45:43 +02:00