Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix NonMesh draw command item queries #17893

Merged
merged 1 commit into from
Mar 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/bevy_render/src/batching/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ where
phase.multidrawable_meshes.sort_unstable_keys();
phase.batchable_meshes.sort_unstable_keys();
phase.unbatchable_meshes.sort_unstable_keys();
phase.non_mesh_items.sort_unstable_keys();
}
}

Expand Down
28 changes: 17 additions & 11 deletions crates/bevy_render/src/render_phase/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ where
/// entity are simply called in order at rendering time.
///
/// See the `custom_phase_item` example for an example of how to use this.
pub non_mesh_items: IndexMap<(BPI::BatchSetKey, BPI::BinKey), RenderBin>,
pub non_mesh_items: IndexMap<(BPI::BatchSetKey, BPI::BinKey), NonMeshEntities>,

/// Information on each batch set.
///
Expand Down Expand Up @@ -291,6 +291,12 @@ pub struct UnbatchableBinnedEntities {
pub(crate) buffer_indices: UnbatchableBinnedEntityIndexSet,
}

/// Information about [`BinnedRenderPhaseType::NonMesh`] entities.
pub struct NonMeshEntities {
/// The entities.
pub entities: MainEntityHashMap<Entity>,
}

/// Stores instance indices and dynamic offsets for unbatchable entities in a
/// binned render phase.
///
Expand Down Expand Up @@ -350,8 +356,6 @@ pub enum BinnedRenderPhaseType {

/// The item is a mesh that's eligible for indirect rendering, but can't be
/// batched with other meshes of the same type.
///
/// At the moment, this is used for skinned meshes.
UnbatchableMesh,

/// The item isn't a mesh at all.
Expand Down Expand Up @@ -495,10 +499,12 @@ where
.entry((batch_set_key.clone(), bin_key.clone()).clone())
{
indexmap::map::Entry::Occupied(mut entry) => {
entry.get_mut().insert(main_entity, input_uniform_index);
entry.get_mut().entities.insert(main_entity, entity);
}
indexmap::map::Entry::Vacant(entry) => {
entry.insert(RenderBin::from_entity(main_entity, input_uniform_index));
let mut entities = MainEntityHashMap::default();
entities.insert(main_entity, entity);
entry.insert(NonMeshEntities { entities });
}
}
}
Expand Down Expand Up @@ -750,14 +756,14 @@ where
let draw_functions = world.resource::<DrawFunctions<BPI>>();
let mut draw_functions = draw_functions.write();

for ((batch_set_key, bin_key), bin) in &self.non_mesh_items {
for &entity in bin.entities.keys() {
for ((batch_set_key, bin_key), non_mesh_entities) in &self.non_mesh_items {
for (main_entity, entity) in non_mesh_entities.entities.iter() {
// Come up with a fake batch range and extra index. The draw
// function is expected to manage any sort of batching logic itself.
let binned_phase_item = BPI::new(
batch_set_key.clone(),
bin_key.clone(),
(Entity::PLACEHOLDER, entity),
(*entity, *main_entity),
0..1,
PhaseItemExtraIndex::None,
);
Expand Down Expand Up @@ -868,7 +874,7 @@ fn remove_entity_from_bin<BPI>(
multidrawable_meshes: &mut IndexMap<BPI::BatchSetKey, IndexMap<BPI::BinKey, RenderBin>>,
batchable_meshes: &mut IndexMap<(BPI::BatchSetKey, BPI::BinKey), RenderBin>,
unbatchable_meshes: &mut IndexMap<(BPI::BatchSetKey, BPI::BinKey), UnbatchableBinnedEntities>,
non_mesh_items: &mut IndexMap<(BPI::BatchSetKey, BPI::BinKey), RenderBin>,
non_mesh_items: &mut IndexMap<(BPI::BatchSetKey, BPI::BinKey), NonMeshEntities>,
) where
BPI: BinnedPhaseItem,
{
Expand Down Expand Up @@ -931,10 +937,10 @@ fn remove_entity_from_bin<BPI>(
entity_bin_key.batch_set_key.clone(),
entity_bin_key.bin_key.clone(),
)) {
bin_entry.get_mut().remove(entity);
bin_entry.get_mut().entities.remove(&entity);

// If the bin is now empty, remove the bin.
if bin_entry.get_mut().is_empty() {
if bin_entry.get_mut().entities.is_empty() {
bin_entry.swap_remove();
}
}
Expand Down