refactor(A.5 T9): _surfaceCache -> ConcurrentDictionary for off-thread mesh build
Widens LandblockMesh.Build's surfaceCache parameter from Dictionary to IDictionary so any IDictionary implementation compiles at call sites. Switches GameWindow._surfaceCache from Dictionary to ConcurrentDictionary so T11's streaming worker can call Build off the render thread without a lock. The TryGetValue+assign lookup inside Build is not atomic, but BuildSurface is deterministic (same palCode -> same SurfaceInfo), making last-write-wins under concurrent access benign. Comment added at the pattern site. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a0741bd13a
commit
4be392b361
2 changed files with 9 additions and 3 deletions
|
|
@ -111,7 +111,9 @@ public sealed class GameWindow : IDisposable
|
||||||
// LandblockMesh.Build without re-deriving these each time.
|
// LandblockMesh.Build without re-deriving these each time.
|
||||||
private float[]? _heightTable;
|
private float[]? _heightTable;
|
||||||
private AcDream.Core.Terrain.TerrainBlendingContext? _blendCtx;
|
private AcDream.Core.Terrain.TerrainBlendingContext? _blendCtx;
|
||||||
private Dictionary<uint, AcDream.Core.Terrain.SurfaceInfo>? _surfaceCache;
|
// Was: Dictionary<uint, SurfaceInfo>. ConcurrentDictionary so the off-thread
|
||||||
|
// mesh builder (A.5 T11+) can call LandblockMesh.Build without a lock.
|
||||||
|
private System.Collections.Concurrent.ConcurrentDictionary<uint, AcDream.Core.Terrain.SurfaceInfo>? _surfaceCache;
|
||||||
|
|
||||||
// Phase A.1 Task 8: worker thread pre-builds EnvCell room-mesh sub-meshes
|
// Phase A.1 Task 8: worker thread pre-builds EnvCell room-mesh sub-meshes
|
||||||
// (CPU only) and stores them here. ApplyLoadedTerrain (render thread) drains
|
// (CPU only) and stores them here. ApplyLoadedTerrain (render thread) drains
|
||||||
|
|
@ -1465,7 +1467,7 @@ public sealed class GameWindow : IDisposable
|
||||||
RoadAlphaRCodes: terrainAtlas.RoadAlphaRCodes);
|
RoadAlphaRCodes: terrainAtlas.RoadAlphaRCodes);
|
||||||
|
|
||||||
_heightTable = heightTable;
|
_heightTable = heightTable;
|
||||||
_surfaceCache = new Dictionary<uint, AcDream.Core.Terrain.SurfaceInfo>();
|
_surfaceCache = new System.Collections.Concurrent.ConcurrentDictionary<uint, AcDream.Core.Terrain.SurfaceInfo>();
|
||||||
|
|
||||||
// (Bindless detection moved above — must precede TerrainAtlas.Build /
|
// (Bindless detection moved above — must precede TerrainAtlas.Build /
|
||||||
// TerrainModernRenderer ctor so they can consume BindlessSupport.)
|
// TerrainModernRenderer ctor so they can consume BindlessSupport.)
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ public static class LandblockMesh
|
||||||
uint landblockY,
|
uint landblockY,
|
||||||
float[] heightTable,
|
float[] heightTable,
|
||||||
TerrainBlendingContext ctx,
|
TerrainBlendingContext ctx,
|
||||||
Dictionary<uint, SurfaceInfo> surfaceCache)
|
System.Collections.Generic.IDictionary<uint, SurfaceInfo> surfaceCache)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(block);
|
ArgumentNullException.ThrowIfNull(block);
|
||||||
ArgumentNullException.ThrowIfNull(heightTable);
|
ArgumentNullException.ThrowIfNull(heightTable);
|
||||||
|
|
@ -105,6 +105,10 @@ public static class LandblockMesh
|
||||||
uint palCode = TerrainBlending.GetPalCode(
|
uint palCode = TerrainBlending.GetPalCode(
|
||||||
rBL, rBR, rTR, rTL, ttBL, ttBR, ttTR, ttTL);
|
rBL, rBR, rTR, rTL, ttBL, ttBR, ttTR, ttTL);
|
||||||
|
|
||||||
|
// Lookup-or-build pattern. Not atomic under concurrent access
|
||||||
|
// (TryGetValue then assign), but BuildSurface is deterministic —
|
||||||
|
// two workers building the same palCode produce equal SurfaceInfo,
|
||||||
|
// last-write-wins is benign.
|
||||||
if (!surfaceCache.TryGetValue(palCode, out var surf))
|
if (!surfaceCache.TryGetValue(palCode, out var surf))
|
||||||
{
|
{
|
||||||
surf = TerrainBlending.BuildSurface(palCode, ctx);
|
surf = TerrainBlending.BuildSurface(palCode, ctx);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue