Skip to content

Commit 06c9f89

Browse files
Fix Bvh::optimize_incremental non-determinism (#403)
* Fix Bvh::optimize_incremental being non-deterministic when restored from a serialized snapshot, due to significant state being stored in BvhWorkspace which cannot be serialized (#402) * Fix typo in BvhIncrementalOptimizationState description (#403) * chore: add comment for the new optimization field * cargo fmt --------- Co-authored-by: Sébastien Crozet <sebcrozet@dimforge.com>
1 parent 72f842d commit 06c9f89

2 files changed

Lines changed: 23 additions & 6 deletions

File tree

src/partitioning/bvh/bvh_optimize.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,15 +240,16 @@ impl Bvh {
240240
}
241241

242242
workspace.rebuild_leaves.clear();
243-
workspace.rebuild_frame_index = workspace.rebuild_frame_index.overflowing_add(1).0;
244-
let config = self.optimization_config(workspace.rebuild_frame_index);
243+
self.optimization.rebuild_frame_index =
244+
self.optimization.rebuild_frame_index.overflowing_add(1).0;
245+
let config = self.optimization_config(self.optimization.rebuild_frame_index);
245246

246247
/*
247248
* Subtree optimizations.
248249
*/
249250
// let t0 = core::time::Instant::now();
250251
let num_leaves = self.nodes[0].leaf_count();
251-
let mut start_index = workspace.rebuild_start_index;
252+
let mut start_index = self.optimization.rebuild_start_index;
252253

253254
// println!("Max candidate leaf count = {}", max_candidate_leaf_count);
254255
self.find_optimization_roots(
@@ -266,7 +267,7 @@ impl Bvh {
266267
// to reach the target subtree count.
267268
}
268269

269-
workspace.rebuild_start_index = start_index;
270+
self.optimization.rebuild_start_index = start_index;
270271

271272
// println!(
272273
// "Num refinement candidates: {}, list: {:?}",
@@ -522,6 +523,19 @@ impl Bvh {
522523
}
523524
}
524525

526+
/// The optimization state used by `Bvh::optimize_incremental`.
527+
/// This allows each call to `optimize_incremental` to continue from where the last one left off.
528+
#[derive(Clone, Debug, Default)]
529+
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
530+
#[cfg_attr(
531+
feature = "rkyv",
532+
derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)
533+
)]
534+
pub(super) struct BvhIncrementalOptimizationState {
535+
pub(super) rebuild_frame_index: u32,
536+
pub(super) rebuild_start_index: u32,
537+
}
538+
525539
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
526540
enum RootOptimizationMode {
527541
PriorityQueue,

src/partitioning/bvh/bvh_tree.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::bvh_optimize::BvhIncrementalOptimizationState;
12
use super::BvhOptimizationHeapEntry;
23
use crate::bounding_volume::{Aabb, BoundingVolume};
34
use crate::math::{Real, Vector};
@@ -136,8 +137,6 @@ pub enum BvhBuildStrategy {
136137
pub struct BvhWorkspace {
137138
pub(super) refit_tmp: BvhNodeVec,
138139
pub(super) rebuild_leaves: Vec<BvhNode>,
139-
pub(super) rebuild_frame_index: u32,
140-
pub(super) rebuild_start_index: u32,
141140
pub(super) optimization_roots: Vec<u32>,
142141
pub(super) queue: BinaryHeap<BvhOptimizationHeapEntry>,
143142
pub(super) dequeue: VecDeque<u32>,
@@ -1752,6 +1751,9 @@ pub struct Bvh {
17521751
// We don’t store this in `Self::nodes` since it’s only useful for node removal.
17531752
pub(super) parents: Vec<BvhNodeIndex>,
17541753
pub(super) leaf_node_indices: VecMap<BvhNodeIndex>,
1754+
// NOTE: this cannot be in the workspace as we need this to survive serialization/deserialization
1755+
// to maintain determinism.
1756+
pub(super) optimization: BvhIncrementalOptimizationState,
17551757
}
17561758

17571759
impl Bvh {
@@ -2186,6 +2188,7 @@ impl Bvh {
21862188
nodes,
21872189
parents,
21882190
leaf_node_indices,
2191+
optimization: _,
21892192
} = self;
21902193
nodes.capacity() * size_of::<BvhNodeWide>()
21912194
+ parents.capacity() * size_of::<BvhNodeIndex>()

0 commit comments

Comments
 (0)