Fix reference counting for SplatAccumulator during updates (#200)

This commit is contained in:
Noeri Huisman
2025-10-24 18:27:40 +02:00
committed by GitHub
parent 5d5493e8a4
commit 8f90fe0ca6
3 changed files with 24 additions and 10 deletions
+1 -1
View File
@@ -464,7 +464,7 @@ export class PackedSplats {
let maxSplats = 0;
const mapping = splatCounts.map((numSplats) => {
const base = maxSplats;
// Generation happens in horizonal row chunks, so round up to full width
// Generation happens in horizontal row chunks, so round up to full width
const rounded = Math.ceil(numSplats / SPLAT_TEX_WIDTH) * SPLAT_TEX_WIDTH;
maxSplats += rounded;
return { base, count: numSplats };
+2 -1
View File
@@ -314,6 +314,7 @@ export class SparkRenderer extends THREE.Mesh {
this.splatEncoding = options.splatEncoding ?? { ...DEFAULT_SPLAT_ENCODING };
this.active = new SplatAccumulator();
this.active.refCount = 1;
this.accumulatorCount = 1;
this.freeAccumulators = [];
// Start with the minimum of 2 total accumulators
@@ -765,7 +766,7 @@ export class SparkRenderer extends THREE.Mesh {
// minimum co-orientation (dot product of quaternions)
const originChanged = !withinCoorientDist({
matrix1: originToWorld,
matrix2: this.active.toWorld,
matrix2: accumulator.toWorld,
maxDistance: 0.00001,
minCoorient: 0.99999,
});
+21 -8
View File
@@ -479,9 +479,15 @@ export class SparkViewpoint {
// Splat mapping has not changed, so reuse the existing sorted
// geometry to show updates faster. We will still fire off
// a re-sort if necessary. First release old accumulator.
accumulator.refCount += 1;
this.spark.releaseAccumulator(this.display.accumulator);
this.display.accumulator = accumulator;
this.display.viewToWorld.copy(this.viewToWorld);
displayed = true;
if (this.spark.viewpoint === this) {
this.spark.prepareViewpoint(this);
}
}
}
@@ -509,15 +515,12 @@ export class SparkViewpoint {
}
if (accumulator) {
// Hold a reference to the accumulator so it isn't released
// Hold a reference to the accumulator for sorting
accumulator.refCount += 1;
}
if (
accumulator &&
this.pending?.accumulator &&
this.pending.accumulator !== this.display?.accumulator
) {
if (this.pending?.accumulator) {
// Release the reference of the pending accumulator
this.spark.releaseAccumulator(this.pending.accumulator);
}
this.pending = { accumulator, viewToWorld: this.viewToWorld, displayed };
@@ -533,9 +536,10 @@ export class SparkViewpoint {
}
const { viewToWorld, displayed } = this.pending;
let accumulator = this.pending.accumulator ?? this.display?.accumulator;
let accumulator = this.pending.accumulator;
if (!accumulator) {
accumulator = this.spark.active;
// Hold a reference to the accumulator while sorting
accumulator = this.display?.accumulator ?? this.spark.active;
accumulator.refCount += 1;
}
this.pending = null;
@@ -546,6 +550,10 @@ export class SparkViewpoint {
this.sorting = { viewToWorld };
await this.sortUpdate({ accumulator, viewToWorld, displayed });
this.sorting = null;
// Release the reference to the accumulator
this.spark.releaseAccumulator(accumulator);
// Continue in loop with any queued sort
}
}
@@ -668,6 +676,8 @@ export class SparkViewpoint {
displayed?: boolean;
}) {
if (!this.display) {
// Hold a reference to the accumulator while part of display
accumulator.refCount += 1;
this.display = {
accumulator,
viewToWorld,
@@ -675,6 +685,9 @@ export class SparkViewpoint {
};
} else {
if (!displayed && accumulator !== this.display.accumulator) {
// Hold a reference to the new accumulator being displayed
accumulator.refCount += 1;
// Release the reference to the previously displayed accumulator
this.spark.releaseAccumulator(this.display.accumulator);
this.display.accumulator = accumulator;
}