fix(A.5): strip far-tier entities in worker (Bug A — far tier optimization)
Phase A.5's two-tier streaming spec promised that far-tier landblocks ship terrain ONLY — no entities, no scenery, no interior cells. T13/T16 wired the controller side (RecenterTo emits ToLoadFar/ToLoadNear/ToPromote; controller passes JobKind to the worker), but the worker's HandleJob never branched on Kind: every load called BuildLandblockForStreaming which runs the full hydration + scenery generation + interior cell path. Result: at default radii (N₁=4 / N₂=12), 540 far-tier LBs each loaded their full entity layer (~132 entities/LB → ~71K entities total) into GpuWorldState. The dispatcher then walked all ~54K entities per frame (post-frustum-cull), driving the entity dispatcher cpu_us from ~3.6ms median (T24 baseline) to ~18-21ms (post-T22.5 horizon-test). User- observed: 40 FPS / 25ms frame time at horizon-safe settings; system crash at full High preset. Minimum-diff fix: in LandblockStreamer.HandleJob, after _loadLandblock returns, strip Entities to empty for LoadFar before posting Loaded. Worker still does wasted hydration CPU (off the render thread, harmless). Render-side dispatcher walk drops from ~54K to ~10K entities/frame. Math: post-fix entity dispatcher should drop to ~3-4ms median at N₁=4 / N₂=12 (matches T24's 3.6ms at radius=5 single-tier, since N₁=4 has 33% fewer near entities than N₁=5). Future optimization (N.6 / A.6): plumb JobKind through BuildLandblockForStreaming so the worker also skips the wasted CPU. Out of A.5 scope. Bug B (T17 WalkEntities allocation) is a smaller perf hit — defer if post-Bug-A FPS is acceptable. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
28d2c6018e
commit
9217fd93cd
1 changed files with 21 additions and 5 deletions
|
|
@ -177,11 +177,19 @@ public sealed class LandblockStreamer : IDisposable
|
||||||
switch (job)
|
switch (job)
|
||||||
{
|
{
|
||||||
case LandblockStreamJob.Load load:
|
case LandblockStreamJob.Load load:
|
||||||
// TODO(A.5 T16): route by load.Kind. LoadFar will skip
|
// A.5 T26 follow-up (Bug A): far-tier LBs must NOT contribute
|
||||||
// LandBlockInfo + scenery generation; PromoteToNear will skip
|
// entities to GpuWorldState — that defeats the whole purpose of
|
||||||
// mesh build (terrain already on GPU). Today every Kind takes
|
// the two-tier split. The factory still builds the full entity
|
||||||
// the full-load path via _loadLandblock, which matches today's
|
// layer (LandblockLoader + scenery generation + interior cells)
|
||||||
// single-tier semantics.
|
// regardless of Kind because it doesn't know about JobKind today.
|
||||||
|
// We strip Entities here for far-tier results so the render-
|
||||||
|
// thread dispatcher walks only near-tier (~10K) entities, not
|
||||||
|
// all (~71K) entities at radius=12.
|
||||||
|
//
|
||||||
|
// Wasted worker-thread CPU is acceptable (it's off the render
|
||||||
|
// thread). A future optimization (TODO N.6 or A.6) plumbs Kind
|
||||||
|
// through BuildLandblockForStreaming so the dat read + scenery
|
||||||
|
// generation are skipped entirely for far-tier.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var lb = _loadLandblock(load.LandblockId);
|
var lb = _loadLandblock(load.LandblockId);
|
||||||
|
|
@ -200,6 +208,14 @@ public sealed class LandblockStreamer : IDisposable
|
||||||
}
|
}
|
||||||
var tier = load.Kind == LandblockStreamJobKind.LoadFar
|
var tier = load.Kind == LandblockStreamJobKind.LoadFar
|
||||||
? LandblockStreamTier.Far : LandblockStreamTier.Near;
|
? LandblockStreamTier.Far : LandblockStreamTier.Near;
|
||||||
|
if (tier == LandblockStreamTier.Far && lb.Entities.Count > 0)
|
||||||
|
{
|
||||||
|
// Strip entities — far-tier ships terrain only.
|
||||||
|
lb = new LoadedLandblock(
|
||||||
|
lb.LandblockId,
|
||||||
|
lb.Heightmap,
|
||||||
|
System.Array.Empty<AcDream.Core.World.WorldEntity>());
|
||||||
|
}
|
||||||
_outbox.Writer.TryWrite(new LandblockStreamResult.Loaded(
|
_outbox.Writer.TryWrite(new LandblockStreamResult.Loaded(
|
||||||
load.LandblockId, tier, lb, mesh));
|
load.LandblockId, tier, lb, mesh));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue