perf(apply): stutter is NOT the game thread -- and the flat floor cannot be relaxed

Two things the owner reported from playing 412a7ad. One is answered, one is a null
result that Codex flagged itself rather than dressing up.

THE FLATTENED TUNNEL FLOORS -- capability-safe, and worth almost nothing
He has now flagged these twice: every tunnel carries a smooth flat strip running in
and out through otherwise craggy rock. The idea was to make the floor CONDITIONAL --
assert it only where the natural rock fails walkability, leave the rock alone
elsewhere. Cheaper and better looking, in theory.

The floor is now skipped only when the exact no-floor field passes the same
player-fit validator at foot offsets 0, -1, +1. Unknown or failed keeps the slab.

  natural-floor skips accepted   1,539 of 1,529,241 tests   = 0.10%
  player-fit cells        20,153 -> 20,153
  reachable cells         10,483 -> 10,483
  arrival -> departure    connected, both
  dihedral p50/p90        2.5429 / 33.8499 deg, IDENTICAL
  mesh time (their batch) 1.757135 -> 1.757140 s

Capability preserved exactly. Visual complaint NOT solved, and no speed gained.

⭐ The useful part is what it PROVED by trying to go further. Every broader policy
lost walkable space:
    analytic-only        fit -217, reachable -195
    tightened analytic   fit  -76, reachable  -76
    exact +/-4 foot      fit  -16, reachable  -16
⇒ The floor cannot be relaxed without changing the walkability contract or adding a
route-aware global proof. That is a real constraint, now measured rather than assumed.

Codex's own words, and it was right to lead with them: "the conservative floor change
is capability-safe, but it does not visibly solve the flattened-strip complaint."

THE STUTTER -- measured, and it is not where we thought
Game-thread apply, meshed tiles, under -nullrhi:

  total apply            p50 0.107 ms   p95 0.153 ms   max 0.273 ms
    stream upload/RMC    p50 0.040      p95 0.088      max 0.124
    component creation   p50 0.019      p95 0.021      max 0.035
    registration         p50 0.010      p95 0.011      max 0.020
    collision config     p50 0.005      p95 0.007      max 0.019

A quarter of a millisecond at worst. The game-thread drain is NOT the hitch.
⇒ Remaining visible stutter is most likely render-thread/RHI work or asynchronous
collision cooking behind RealtimeMeshComponent, which is off-limits for edits.

Added anyway as a cheap safety valve: MaxMeshApplyMilliseconds, default 2 ms of drain
budget per frame. Over 729 apply frames: drain p50/p95/max 0.111/0.182/0.313 ms,
budget hits 0, at most 2 visible applies in a frame. It costs nothing today and caps
a future burst.

Request-to-ready, now timed after game-thread application:
  all     p50 57.1 ms   p95 432.9 ms   max 919.4 ms   -> 2.60 m at 6 m/s
  meshed  p50 134.1 ms  p95 457.4 ms   max 919.4 ms

⚠️ My own verification: 1.197 / 1.131 / 1.118 s vs 1.088-1.102 s on 412a7ad. Mean
+4.7% -- below the 17% noise floor, but slower in all three runs, and the validator
runs 1.5M times to accept 1,539 skips. Geometry moved by 4 triangles (153,740 ->
153,744), which is allowed. If the next round cannot make that validator earn its
place, it should come out.

Build 0 errors. Peak RSS 1.67 GB export / 1.90 GB game. Nothing outside
Plugins/VoxelForge; RealtimeMeshComponent untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aheo2crrZmHuYtPpdY2Cb
This commit is contained in:
Fr0zkaandClaude Opus 5 committed 2026-09-10 14:46:29 +02:00
1 parent 412a7ad219
commit 383ec86c37
11 files changed
+508 -43

No files matched your search

@@ -3591,8 +3591,10 @@ namespace
{
public:
FRoomGraphSource(const FStrateGenerationParams& InP, int32 InSeed,
const UVoxelStrateManager* InManager)
const UVoxelStrateManager* InManager,
const UVoxelGenerator* InGenerator = nullptr)
: P(InP), Seed(InSeed), SeedU((uint32)InSeed), Manager(InManager)
, Generator(InGenerator)
, ManagerLifetimeId(InManager ? InManager->GetCacheLifetimeId() : 0)
, ParamsFingerprint(FCrc::MemCrc32(&InP, sizeof(InP)))
{}
@@ -3791,6 +3793,37 @@ namespace
return P.RoomDensity > 0.0f && P.RoomSpacing > 0.0f;
}
void BuildSupportColumn(
float WorldX, float WorldY,
const FChunkSDFCache& Cache,
FTunnelSupportFloorColumn& OutColumn) const
{
if (Generator == nullptr)
{
VoxelCaveMorphology::BuildTunnelSupportFloorColumn(
WorldX, WorldY, Cache, OutColumn);
return;
}
// This is a synchronous, non-owning view of the exact field with only the graph
// support slab disabled. BuildTunnelSupportFloorColumn consumes it immediately and
// retains only the proven interval decision in the worker-local column cache.
const auto SampleWithoutTunnelSupportFloor =
[this](float X, float Y, float Z) -> float
{
return Generator->GetDensityWithParams(
X, Y, Z, P, ParamsFingerprint, LayoutVersion,
/*bApplyLegacyStructuralPosts=*/true,
/*bApplyTunnelSupportFloor=*/false);
};
FTunnelSupportFloorDensitySampler NaturalSampler =
SampleWithoutTunnelSupportFloor;
VoxelCaveMorphology::BuildTunnelSupportFloorColumn(
WorldX, WorldY, Cache, OutColumn, &NaturalSampler,
P.StrateTopWorldZ, P.StrateBottomWorldZ,
P.BoundarySealThickness);
}
const FTunnelSupportFloorColumn* GetSupportColumn(const FVector& Position) const
{
FState& S = State();
@@ -3809,7 +3842,7 @@ namespace
IX, IY, &Cache, S.SupportColumns.Clock, bNewColumn);
if (bNewColumn)
{
VoxelCaveMorphology::BuildTunnelSupportFloorColumn(
BuildSupportColumn(
static_cast<float>(Position.X),
static_cast<float>(Position.Y),
Cache,
@@ -3818,7 +3851,7 @@ namespace
return Column;
}
VoxelCaveMorphology::BuildTunnelSupportFloorColumn(
BuildSupportColumn(
static_cast<float>(Position.X), static_cast<float>(Position.Y),
GetCache(), S.FractionalSupportColumn);
return &S.FractionalSupportColumn;
@@ -6633,6 +6666,7 @@ namespace
int32 Seed;
uint32 SeedU;
TWeakObjectPtr<const UVoxelStrateManager> Manager;
const UVoxelGenerator* Generator = nullptr;
uint64 ManagerLifetimeId = 0;
uint32 ParamsFingerprint;
uint32 LayoutVersion = 0;
@@ -9408,7 +9442,8 @@ namespace VoxelDensityOps
void BuildTunnelNetworkStack(FVoxelOpStack& OutStack, const FStrateGenerationParams& P,
int32 Seed, float SpineRadius, const UVoxelStrateManager* StrateManager,
bool bAppendStructuralPosts)
bool bAppendStructuralPosts,
const UVoxelGenerator* Generator)
{
// ⚠️ ÉTAPES A + B + C1 — LA PILE EST COMPLÈTE POUR CET ARCHÉTYPE.
// Portés : échelle verticale, roc de base, warp, graphe de salles (+ pits + cheminées),
@@ -9452,7 +9487,8 @@ namespace VoxelDensityOps
// La source de salles est retenue par pointeur non possédant : les terrasses re-interrogent
// son cache SDF en Z±1. Même motif que `FShaftFieldSource` → `FShaftLedgeMod`.
TUniquePtr<FRoomGraphSource> RoomSource = MakeUnique<FRoomGraphSource>(P, Seed, StrateManager);
TUniquePtr<FRoomGraphSource> RoomSource = MakeUnique<FRoomGraphSource>(
P, Seed, StrateManager, Generator);
const FRoomGraphSource* RoomPtr = RoomSource.Get();
OutStack.Add(MakeConstantRockSource(P.BaseDensity));