refactor: store-owned diff snapshot and drop dead ChunkJob.ExistingChunk
TryGetDiff now returns an independent copy so callers can safely retain the reference; removes the defensive copy from ChunkStreamer.DispatchLoad. ChunkJob.ExistingChunk was never populated (DispatchRemesh uses closures instead), so the field is removed along with its misleading record-level comment.
This commit is contained in:
@@ -10,7 +10,9 @@ public sealed class InMemoryChunkModificationStore : IChunkModificationStore
|
|||||||
{
|
{
|
||||||
if (this._diffs.TryGetValue(chunkPos, out Dictionary<int, ushort>? d))
|
if (this._diffs.TryGetValue(chunkPos, out Dictionary<int, ushort>? d))
|
||||||
{
|
{
|
||||||
diff = d;
|
// Returned snapshot: callers may safely retain and enumerate even
|
||||||
|
// after concurrent RecordEdit on the same chunk.
|
||||||
|
diff = new Dictionary<int, ushort>(d);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
diff = null;
|
diff = null;
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ using VoxelEngine.World.Chunk;
|
|||||||
|
|
||||||
namespace VoxelEngine.World.Streaming;
|
namespace VoxelEngine.World.Streaming;
|
||||||
|
|
||||||
// Job dispatched to an IJobExecutor. For a fresh load, ExistingChunk is null
|
// Job dispatched to an IJobExecutor for a fresh chunk load. The worker
|
||||||
// and the worker generates + applies diff + meshes. For a remesh-only job,
|
// generates the chunk, applies any modification diff, and meshes the result.
|
||||||
// ExistingChunk holds the chunk and the worker only meshes (no generation).
|
// Remesh-only jobs are dispatched separately by DispatchRemesh and capture
|
||||||
|
// their state via closures, so they do not use this record.
|
||||||
internal sealed record ChunkJob(
|
internal sealed record ChunkJob(
|
||||||
Vector3i Pos,
|
Vector3i Pos,
|
||||||
Chunk.Chunk? ExistingChunk,
|
|
||||||
NeighborSnapshots Neighbors,
|
NeighborSnapshots Neighbors,
|
||||||
IReadOnlyDictionary<int, ushort>? Diff);
|
IReadOnlyDictionary<int, ushort>? Diff);
|
||||||
|
|
||||||
|
|||||||
@@ -299,15 +299,9 @@ public sealed class ChunkStreamer : IDisposable
|
|||||||
private void DispatchLoad(Vector3i pos)
|
private void DispatchLoad(Vector3i pos)
|
||||||
{
|
{
|
||||||
NeighborSnapshots neighbors = this.SnapshotNeighbors(pos);
|
NeighborSnapshots neighbors = this.SnapshotNeighbors(pos);
|
||||||
IReadOnlyDictionary<int, ushort>? diff = null;
|
this._world.ModificationStore.TryGetDiff(pos, out IReadOnlyDictionary<int, ushort>? diff);
|
||||||
if (this._world.ModificationStore.TryGetDiff(pos, out var d) && d != null)
|
|
||||||
{
|
|
||||||
// Copy: TryGetDiff returns the live internal dictionary, which the
|
|
||||||
// main thread may mutate via World.SetBlock while the worker iterates.
|
|
||||||
diff = new Dictionary<int, ushort>(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
var job = new ChunkJob(pos, ExistingChunk: null, neighbors, diff);
|
var job = new ChunkJob(pos, neighbors, diff);
|
||||||
this._inFlight++;
|
this._inFlight++;
|
||||||
|
|
||||||
IChunkMesher mesher = this._mesher;
|
IChunkMesher mesher = this._mesher;
|
||||||
|
|||||||
Reference in New Issue
Block a user