chore(N.5b): TEMPORARY perf benchmark toggle for legacy↔modern terrain

Adds an ACDREAM_LEGACY_TERRAIN=1 env var that routes Draw through the
legacy TerrainChunkRenderer instead of the new TerrainModernRenderer.
Both renderers are constructed and fed AddLandblock/RemoveLandblock so
they stay in sync; only one is drawn per frame. The [TERRAIN-DIAG]
log line is labeled /modern or /legacy so the user can tell which
numbers they're capturing.

Removed in Task 9 along with TerrainChunkRenderer.cs, terrain.vert,
and terrain.frag.

Usage:
  \$env:ACDREAM_LEGACY_TERRAIN = "1"   # legacy mode
  \$env:ACDREAM_LEGACY_TERRAIN = \$null # modern mode (default)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-09 09:36:13 +02:00
parent 75913c1c97
commit 336ad34444

View file

@ -19,6 +19,12 @@ public sealed class GameWindow : IDisposable
private GL? _gl;
private IInputContext? _input;
private TerrainModernRenderer? _terrain;
// Phase N.5b benchmark toggle (TEMPORARY — removed in Task 9 along with TerrainChunkRenderer):
// when ACDREAM_LEGACY_TERRAIN=1, route Draw through the legacy renderer
// for direct perf comparison. Both renderers are constructed and fed
// AddLandblock/RemoveLandblock; only one is drawn per frame.
private TerrainChunkRenderer? _terrainLegacy;
private bool _useLegacyTerrain;
private Shader? _shader;
/// <summary>Phase N.5b: terrain_modern.vert/.frag program. Owned by
/// <see cref="_terrain"/> at draw time but allocated + disposed here. Lives
@ -1445,6 +1451,10 @@ public sealed class GameWindow : IDisposable
_terrain = new TerrainModernRenderer(_gl, _bindlessSupport, _terrainModernShader!, terrainAtlas);
// Phase N.5b benchmark toggle (TEMPORARY — see field declaration).
_useLegacyTerrain = Environment.GetEnvironmentVariable("ACDREAM_LEGACY_TERRAIN") == "1";
_terrainLegacy = new TerrainChunkRenderer(_gl, _shader!, terrainAtlas);
int centerX = (int)((centerLandblockId >> 24) & 0xFFu);
int centerY = (int)((centerLandblockId >> 16) & 0xFFu);
@ -1602,6 +1612,7 @@ public sealed class GameWindow : IDisposable
_lightingSink.UnregisterOwner(ent.Id);
}
_terrain?.RemoveLandblock(id);
_terrainLegacy?.RemoveLandblock(id); // Phase N.5b benchmark toggle (TEMPORARY).
_physicsEngine.RemoveLandblock(id);
_cellVisibility.RemoveLandblock((id >> 16) & 0xFFFFu);
});
@ -5122,6 +5133,7 @@ public sealed class GameWindow : IDisposable
var meshData = AcDream.Core.Terrain.LandblockMesh.Build(
lb.Heightmap, lbXu, lbYu, _heightTable, _blendCtx, _surfaceCache);
_terrain.AddLandblock(lb.LandblockId, meshData, origin);
_terrainLegacy?.AddLandblock(lb.LandblockId, meshData, origin); // Phase N.5b benchmark toggle (TEMPORARY).
// Step 4: drain pending LoadedCells from the worker thread.
while (_pendingCells.TryTake(out var cell))
@ -6346,6 +6358,10 @@ public sealed class GameWindow : IDisposable
// (gated on ACDREAM_WB_DIAG=1, same env var as [WB-DIAG]). Stopwatch
// is cheap; only the periodic Console.WriteLine is gated.
_terrainCpuStopwatch.Restart();
// Phase N.5b benchmark toggle (TEMPORARY): pick renderer per ACDREAM_LEGACY_TERRAIN.
if (_useLegacyTerrain)
_terrainLegacy?.Draw(camera, frustum, neverCullLandblockId: playerLb);
else
_terrain?.Draw(camera, frustum, neverCullLandblockId: playerLb);
_terrainCpuStopwatch.Stop();
_terrainCpuSamples[_terrainCpuSampleCursor] = (long)(_terrainCpuStopwatch.Elapsed.TotalMicroseconds);
@ -8765,7 +8781,7 @@ public sealed class GameWindow : IDisposable
long cpuMedUs = TerrainDiagMedianMicros(_terrainCpuSamples);
long cpuP95Us = TerrainDiagPercentile95Micros(_terrainCpuSamples);
Console.WriteLine(
$"[TERRAIN-DIAG] cpu_ms={cpuMedUs / 1000.0:F2}/{cpuP95Us / 1000.0:F2} " +
$"[TERRAIN-DIAG{(_useLegacyTerrain ? "/legacy" : "/modern")}] cpu_ms={cpuMedUs / 1000.0:F2}/{cpuP95Us / 1000.0:F2} " +
$"draws={_terrain?.VisibleSlots ?? 0}/frame " +
$"visible={_terrain?.VisibleSlots ?? 0} " +
$"loaded={_terrain?.LoadedSlots ?? 0} " +
@ -8813,6 +8829,7 @@ public sealed class GameWindow : IDisposable
_meshShader?.Dispose();
_terrain?.Dispose();
_terrainLegacy?.Dispose(); // Phase N.5b benchmark toggle (TEMPORARY).
_shader?.Dispose();
_terrainModernShader?.Dispose();
_sceneLightingUbo?.Dispose();