Skip to content

Commit b7ee23a

Browse files
authored
Remove meshlet builder retry queue (#16941)
Revert the retry queue for stuck meshlet groups that couldn't simplify added in #15886. It was a hack that didn't really work, that was intended to help solve meshlets getting stuck and never getting simplified further. The actual solution is a new DAG building algorithm that I have coming in a followup PR. With that PR, there will be no need for the retry queue, as meshlets will rarely ever get stuck (I checked, the code never gets called). I split this off into it's own PR for easier reviewing. Meshlet IDs during building are back to being relative to the overall list of meshlets across all LODs, instead of starting at 0 for the first meshlet in the simplification queue for the current LOD, regardless of how many meshlets there are in the asset total. Not going to bother to regenerate the bunny asset for this PR.
1 parent 8d9a00f commit b7ee23a

File tree

1 file changed

+28
-37
lines changed

1 file changed

+28
-37
lines changed

crates/bevy_pbr/src/meshlet/from_mesh.rs

Lines changed: 28 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use bevy_render::{
99
};
1010
use bevy_utils::HashMap;
1111
use bitvec::{order::Lsb0, vec::BitVec, view::BitView};
12-
use core::iter;
12+
use core::{iter, ops::Range};
1313
use half::f16;
1414
use itertools::Itertools;
1515
use meshopt::{
@@ -105,20 +105,22 @@ impl MeshletMesh {
105105
let mut vertex_locks = vec![false; vertices.vertex_count];
106106

107107
// Build further LODs
108-
let mut simplification_queue = Vec::from_iter(0..meshlets.len());
109-
let mut retry_queue = Vec::new();
108+
let mut simplification_queue = 0..meshlets.len();
110109
while simplification_queue.len() > 1 {
111110
// For each meshlet build a list of connected meshlets (meshlets that share a vertex)
112111
let connected_meshlets_per_meshlet = find_connected_meshlets(
113-
&simplification_queue,
112+
simplification_queue.clone(),
114113
&meshlets,
115114
&position_only_vertex_remap,
116115
position_only_vertex_count,
117116
);
118117

119118
// Group meshlets into roughly groups of size TARGET_MESHLETS_PER_GROUP,
120119
// grouping meshlets with a high number of shared vertices
121-
let groups = group_meshlets(&connected_meshlets_per_meshlet, &simplification_queue);
120+
let groups = group_meshlets(
121+
&connected_meshlets_per_meshlet,
122+
simplification_queue.clone(),
123+
);
122124

123125
// Lock borders between groups to prevent cracks when simplifying
124126
lock_group_borders(
@@ -131,9 +133,8 @@ impl MeshletMesh {
131133

132134
let next_lod_start = meshlets.len();
133135
for group_meshlets in groups.into_iter() {
134-
// If the group only has a single meshlet, we can't simplify it well, so retry later
136+
// If the group only has a single meshlet we can't simplify it
135137
if group_meshlets.len() == 1 {
136-
retry_queue.push(group_meshlets[0]);
137138
continue;
138139
}
139140

@@ -146,8 +147,7 @@ impl MeshletMesh {
146147
vertex_stride,
147148
&vertex_locks,
148149
) else {
149-
// Couldn't simplify the group enough, retry its meshlets later
150-
retry_queue.extend_from_slice(&group_meshlets);
150+
// Couldn't simplify the group enough
151151
continue;
152152
};
153153

@@ -187,12 +187,8 @@ impl MeshletMesh {
187187
);
188188
}
189189

190-
// Set simplification queue to the list of newly created (and retrying) meshlets
191-
simplification_queue.clear();
192-
simplification_queue.extend(next_lod_start..meshlets.len());
193-
if !simplification_queue.is_empty() {
194-
simplification_queue.append(&mut retry_queue);
195-
}
190+
// Set simplification queue to the list of newly created meshlets
191+
simplification_queue = next_lod_start..meshlets.len();
196192
}
197193

198194
// Copy vertex attributes per meshlet and compress
@@ -252,50 +248,45 @@ fn compute_meshlets(indices: &[u32], vertices: &VertexDataAdapter) -> Meshlets {
252248
}
253249

254250
fn find_connected_meshlets(
255-
simplification_queue: &[usize],
251+
simplification_queue: Range<usize>,
256252
meshlets: &Meshlets,
257253
position_only_vertex_remap: &[u32],
258254
position_only_vertex_count: usize,
259255
) -> Vec<Vec<(usize, usize)>> {
260256
// For each vertex, build a list of all meshlets that use it
261257
let mut vertices_to_meshlets = vec![Vec::new(); position_only_vertex_count];
262-
for (meshlet_queue_id, meshlet_id) in simplification_queue.iter().enumerate() {
263-
let meshlet = meshlets.get(*meshlet_id);
258+
for meshlet_id in simplification_queue.clone() {
259+
let meshlet = meshlets.get(meshlet_id);
264260
for index in meshlet.triangles {
265261
let vertex_id = position_only_vertex_remap[meshlet.vertices[*index as usize] as usize];
266262
let vertex_to_meshlets = &mut vertices_to_meshlets[vertex_id as usize];
267263
// Meshlets are added in order, so we can just check the last element to deduplicate,
268264
// in the case of two triangles sharing the same vertex within a single meshlet
269-
if vertex_to_meshlets.last() != Some(&meshlet_queue_id) {
270-
vertex_to_meshlets.push(meshlet_queue_id);
265+
if vertex_to_meshlets.last() != Some(&meshlet_id) {
266+
vertex_to_meshlets.push(meshlet_id);
271267
}
272268
}
273269
}
274270

275271
// For each meshlet pair, count how many vertices they share
276272
let mut meshlet_pair_to_shared_vertex_count = <HashMap<_, _>>::default();
277273
for vertex_meshlet_ids in vertices_to_meshlets {
278-
for (meshlet_queue_id1, meshlet_queue_id2) in
279-
vertex_meshlet_ids.into_iter().tuple_combinations()
280-
{
274+
for (meshlet_id1, meshlet_id2) in vertex_meshlet_ids.into_iter().tuple_combinations() {
281275
let count = meshlet_pair_to_shared_vertex_count
282-
.entry((
283-
meshlet_queue_id1.min(meshlet_queue_id2),
284-
meshlet_queue_id1.max(meshlet_queue_id2),
285-
))
276+
.entry((meshlet_id1.min(meshlet_id2), meshlet_id1.max(meshlet_id2)))
286277
.or_insert(0);
287278
*count += 1;
288279
}
289280
}
290281

291282
// For each meshlet, gather all other meshlets that share at least one vertex along with their shared vertex count
292283
let mut connected_meshlets_per_meshlet = vec![Vec::new(); simplification_queue.len()];
293-
for ((meshlet_queue_id1, meshlet_queue_id2), shared_count) in
294-
meshlet_pair_to_shared_vertex_count
295-
{
284+
for ((meshlet_id1, meshlet_id2), shared_vertex_count) in meshlet_pair_to_shared_vertex_count {
296285
// We record both id1->id2 and id2->id1 as adjacency is symmetrical
297-
connected_meshlets_per_meshlet[meshlet_queue_id1].push((meshlet_queue_id2, shared_count));
298-
connected_meshlets_per_meshlet[meshlet_queue_id2].push((meshlet_queue_id1, shared_count));
286+
connected_meshlets_per_meshlet[meshlet_id1 - simplification_queue.start]
287+
.push((meshlet_id2, shared_vertex_count));
288+
connected_meshlets_per_meshlet[meshlet_id2 - simplification_queue.start]
289+
.push((meshlet_id1, shared_vertex_count));
299290
}
300291

301292
// The order of meshlets depends on hash traversal order; to produce deterministic results, sort them
@@ -309,15 +300,15 @@ fn find_connected_meshlets(
309300
// METIS manual: https://github.com/KarypisLab/METIS/blob/e0f1b88b8efcb24ffa0ec55eabb78fbe61e58ae7/manual/manual.pdf
310301
fn group_meshlets(
311302
connected_meshlets_per_meshlet: &[Vec<(usize, usize)>],
312-
simplification_queue: &[usize],
303+
simplification_queue: Range<usize>,
313304
) -> Vec<SmallVec<[usize; TARGET_MESHLETS_PER_GROUP]>> {
314305
let mut xadj = Vec::with_capacity(simplification_queue.len() + 1);
315306
let mut adjncy = Vec::new();
316307
let mut adjwgt = Vec::new();
317308
for connected_meshlets in connected_meshlets_per_meshlet {
318309
xadj.push(adjncy.len() as i32);
319-
for (connected_meshlet_queue_id, shared_vertex_count) in connected_meshlets {
320-
adjncy.push(*connected_meshlet_queue_id as i32);
310+
for (connected_meshlet_id, shared_vertex_count) in connected_meshlets {
311+
adjncy.push((connected_meshlet_id - simplification_queue.start) as i32);
321312
adjwgt.push(*shared_vertex_count as i32);
322313
// TODO: Additional weight based on meshlet spatial proximity
323314
}
@@ -336,8 +327,8 @@ fn group_meshlets(
336327
.unwrap();
337328

338329
let mut groups = vec![SmallVec::new(); partition_count];
339-
for (meshlet_queue_id, meshlet_group) in group_per_meshlet.into_iter().enumerate() {
340-
groups[meshlet_group as usize].push(simplification_queue[meshlet_queue_id]);
330+
for (i, meshlet_group) in group_per_meshlet.into_iter().enumerate() {
331+
groups[meshlet_group as usize].push(i + simplification_queue.start);
341332
}
342333
groups
343334
}

0 commit comments

Comments
 (0)