perf(opstack): invert the loop + prune per block -- 1.45s to 1.02s, byte-identical
The architecture round. Loop inverted from per-sample-per-op to per-op-per-block, operators pruned per block by interval bounds, profiler moved out of the hot loop. my build, 3 runs: 1.013 / 1.036 / 1.075 s (adb34dfwas 1.418 / 1.445 / 1.458) mean 1.041 vs 1.440 = -28.5%, 1.39x geometry SHA-256 b3e5f4c3..9b377 IDENTICAL toadb34dfpruning removed 20,999 / 31,320 operator-block visits = 67.1% surviving ops per block: LOD0 6.63 LOD1 6.30 LOD2 5.23 LOD3 4.41 LOD4 3.89 (out of 22) ⚠️ I PREDICTED THE DISPATCH OVERHEAD WAS "THE 10x". IT WAS NOT. 864,688 virtual dispatches per chunk sounded decisive and is worth ~20-28%. Real, and worth having, but the order of magnitude is elsewhere. That is my fourth wrong performance prediction in this project, and the pattern is identical each time: I reason from a call site's shape instead of measuring what the data actually costs. ⭐⭐ AND THE "5-20x GAME/EXPORT GAP" WAS MY ARITHMETIC ERROR. IT DOES NOT EXIST. I told the owner the largest unexplained number in the project was that export does 22 ms/tile while the game does 115-500 ms. That 22 ms came from dividing 1.4 s of WALL CLOCK by 64 tiles -- ignoring that 15 workers ran them in parallel. Per-job means on the same build: nonshared block export 447 ms/job shared-grid export 261 ms/job game LOD0 meshing 253 ms/tile p50 They are the same. The game is not anomalously slow; generation simply costs ~250 ms per LOD0 tile. The shared grid's benefit is real but modest, and a neighbourhood cache is NOT justified by these numbers -- I would have had Codex build one on the strength of a division error. GAME PATH, final build (841 profiles, 447 applies) meshed p50/p95/max LOD0 253/521/697 ms LOD1 79/130/135 LOD2 19/42/51 LOD3 36/64/81 LOD4 93/238/271 LOD0 request-to-ready p50 47.7 ms p95 389 ms max 798 ms worker queue p95 84 ms, generation p95 344 ms at 6 m/s: p95 = 2.3 m of travel, max = 4.8 m empty LOD0 tiles never enter the mesher; classifier p50 8.7 ms, p95 17.2 ms apply is not the bottleneck: p50 0.107 ms, p95 0.161 ms, max 0.296 ms ⭐ THE BINDING CONSTRAINT IS COMPUTE, NOT POLICY: logical cores 16, automatic core cap 14, effective generation cap 14, CAP HIT. Apply limits never bind. We are saturating the machine, which means the remaining wins must come from doing less work, not from scheduling it better. NOT DONE, with reasons rather than excuses: - Coarse-first LOD refinement: coarse tiles carry NO COLLISION, so streaming them first would let the player fall through. Needs a conservative collision proxy or an L0 handoff first. Correct refusal. - Heading prefetch: desired tiles are sorted by distance only (VoxelWorld.cpp:1748). Velocity-weighted prediction with a bounded budget and expiry is the shape, not built. A failed experiment, reported rather than buried: eagerly filling every classifier leaf with EvalBlock regressed export to 3.2-3.3 s because it defeated the classifier's early exit. Removed. Build 43 actions, 0 errors. Peak RSS under 2.1 GB. Sources: Epic's Tasks System and Level Streaming docs, Lorensen-Cline. Cumulative on this region: 342.2 s -> 1.02 s. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012aheo2crrZmHuYtPpdY2Cb
This commit is contained in:
1 parent
adb34dffa9
commit
5ddd96664d
9 files changed
+815
-9
No files matched your search
@@ -41,6 +41,40 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
/**
|
||||
* Concrete block thunks use the scalar body with the concrete operator type visible to the
|
||||
* compiler. This is deliberately not a second numerical implementation: the scalar Eval is
|
||||
* still the single source of truth, but the op-major caller pays one virtual dispatch for the
|
||||
* block and the inner calls can inline/devirtualize. Operators with a block-native kernel can
|
||||
* replace this helper later without changing the stack contract.
|
||||
*/
|
||||
template<typename TOp>
|
||||
FORCEINLINE void VF_EvalBlockByScalar(const TOp& Op, const FVoxelOpBlock& Block)
|
||||
{
|
||||
if (Block.Samples == nullptr || Block.Step <= 0
|
||||
|| Block.SizeX <= 0 || Block.SizeY <= 0 || Block.SizeZ <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int32 Z = 0; Z < Block.SizeZ; ++Z)
|
||||
{
|
||||
for (int32 Y = 0; Y < Block.SizeY; ++Y)
|
||||
{
|
||||
for (int32 X = 0; X < Block.SizeX; ++X)
|
||||
{
|
||||
FVoxelOpSample& Sample = Block.At(X, Y, Z);
|
||||
Op.PrepareBlockSample(Sample);
|
||||
Op.Eval(
|
||||
static_cast<float>(Block.OriginVoxels.X + X * Block.Step),
|
||||
static_cast<float>(Block.OriginVoxels.Y + Y * Block.Step),
|
||||
static_cast<float>(Block.OriginVoxels.Z + Z * Block.Step),
|
||||
Sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* BORNE **PROUVABLE** DE `|Perlin3D|`, ET ELLE N'EST PAS 1.0.
|
||||
*
|
||||
@@ -516,6 +550,11 @@ namespace
|
||||
|
||||
const TCHAR* DebugName() const override { return TEXT("ConstantFieldSource"); }
|
||||
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override
|
||||
{
|
||||
VF_EvalBlockByScalar(*this, Block);
|
||||
}
|
||||
|
||||
private:
|
||||
float Value;
|
||||
};
|
||||
@@ -1839,6 +1878,11 @@ namespace
|
||||
|
||||
const TCHAR* DebugName() const override { return TEXT("SdfConvertOp"); }
|
||||
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override
|
||||
{
|
||||
VF_EvalBlockByScalar(*this, Block);
|
||||
}
|
||||
|
||||
private:
|
||||
bool IsInactive(const FVoxelBoxHypotheses& H) const
|
||||
{
|
||||
@@ -1926,6 +1970,11 @@ namespace
|
||||
|
||||
const TCHAR* DebugName() const override { return TEXT("OriginSpineOp"); }
|
||||
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override
|
||||
{
|
||||
VF_EvalBlockByScalar(*this, Block);
|
||||
}
|
||||
|
||||
private:
|
||||
float TopZ, BotZ, Seal, Base, Radius;
|
||||
};
|
||||
@@ -2007,6 +2056,11 @@ namespace
|
||||
|
||||
const TCHAR* DebugName() const override { return TEXT("BoundarySealOp"); }
|
||||
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override
|
||||
{
|
||||
VF_EvalBlockByScalar(*this, Block);
|
||||
}
|
||||
|
||||
private:
|
||||
float TopZ, BotZ, Thickness, Base;
|
||||
};
|
||||
@@ -2074,6 +2128,11 @@ namespace
|
||||
bool IsXYPure() const override { return true; }
|
||||
const TCHAR* DebugName() const override { return TEXT("XYEdgeSealOp"); }
|
||||
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override
|
||||
{
|
||||
VF_EvalBlockByScalar(*this, Block);
|
||||
}
|
||||
|
||||
private:
|
||||
float Base = 8.0f;
|
||||
mutable float WorldRadius = 8192.0f;
|
||||
@@ -2186,6 +2245,11 @@ namespace
|
||||
|
||||
const TCHAR* DebugName() const override { return TEXT("PassageCarveOp"); }
|
||||
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override
|
||||
{
|
||||
VF_EvalBlockByScalar(*this, Block);
|
||||
}
|
||||
|
||||
private:
|
||||
TWeakObjectPtr<const UVoxelStrateManager> Manager;
|
||||
float Base, Seal, TopZ, BotZ, SpineRadius;
|
||||
@@ -3786,6 +3850,15 @@ namespace
|
||||
* Lu par les arches, les dômes, le pincement et le biais de sol. */
|
||||
int32 GetNearestRoomIdx() const { return State().NearestRoom; }
|
||||
|
||||
/** Restore the source-owned state belonging to one sample before a later block op reads it. */
|
||||
void RestoreBlockSample(const FVoxelOpSample& Sample) const
|
||||
{
|
||||
FState& S = State();
|
||||
S.ActiveCache = Sample.RoomCache;
|
||||
S.NearestRoom = Sample.NearestRoomIndex;
|
||||
S.bLocalParamsValid = false;
|
||||
}
|
||||
|
||||
void BuildSupportColumn(
|
||||
float WorldX, float WorldY,
|
||||
const FChunkSDFCache& Cache,
|
||||
@@ -4255,6 +4328,16 @@ namespace
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// These are the per-sample hand-offs needed by an op-major block. The scalar path
|
||||
// continues to use FState directly; publishing them here only makes the dependency
|
||||
// explicit for a later modifier and does not alter Density/Sdf.
|
||||
InOut.RoomCache = &GetCache();
|
||||
InOut.NearestRoomIndex = S.NearestRoom;
|
||||
InOut.bHasTunnelCoreWorldEvaluation = true;
|
||||
InOut.TunnelCoreWorldSDF = S.LastTunnelCoreWorldEvaluation.SDF;
|
||||
InOut.bTunnelCoreSupportFloor = S.LastTunnelCoreWorldEvaluation.bSupportFloor;
|
||||
InOut.bTunnelCoreRoomFloor = S.LastTunnelCoreWorldEvaluation.bRoomFloor;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
@@ -6629,6 +6712,11 @@ namespace
|
||||
|
||||
const TCHAR* DebugName() const override { return TEXT("RoomGraphSource"); }
|
||||
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override
|
||||
{
|
||||
VF_EvalBlockByScalar(*this, Block);
|
||||
}
|
||||
|
||||
private:
|
||||
FStrateGenerationParams P;
|
||||
int32 Seed;
|
||||
@@ -6725,6 +6813,7 @@ namespace
|
||||
bool IsAdditive() const override { return true; }
|
||||
void PrepareChunk(const FVoxelOpContext&) override {}
|
||||
const TCHAR* DebugName() const override { return TEXT("CaveRoughnessMod"); }
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override { VF_EvalBlockByScalar(*this, Block); }
|
||||
|
||||
void Eval(float WorldX, float WorldY, float WorldZ, FVoxelOpSample& InOut) const override
|
||||
{
|
||||
@@ -6957,7 +7046,12 @@ namespace
|
||||
EVoxelOpResourceMask RequiredResources() const override { return VoxelOpResources::RoomGeometry; }
|
||||
bool IsAdditive() const override { return true; }
|
||||
void PrepareChunk(const FVoxelOpContext&) override {}
|
||||
void PrepareBlockSample(const FVoxelOpSample& Sample) const override
|
||||
{
|
||||
if (Rooms != nullptr) { Rooms->RestoreBlockSample(Sample); }
|
||||
}
|
||||
const TCHAR* DebugName() const override { return TEXT("CaveTerraceMod"); }
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override { VF_EvalBlockByScalar(*this, Block); }
|
||||
|
||||
void Eval(float WorldX, float WorldY, float WorldZ, FVoxelOpSample& InOut) const override
|
||||
{
|
||||
@@ -7106,7 +7200,12 @@ namespace
|
||||
EVoxelOpResourceMask RequiredResources() const override { return VoxelOpResources::RoomGeometry; }
|
||||
bool IsAdditive() const override { return true; }
|
||||
void PrepareChunk(const FVoxelOpContext&) override {}
|
||||
void PrepareBlockSample(const FVoxelOpSample& Sample) const override
|
||||
{
|
||||
if (Rooms != nullptr) { Rooms->RestoreBlockSample(Sample); }
|
||||
}
|
||||
const TCHAR* DebugName() const override { return TEXT("LayerLineMod"); }
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override { VF_EvalBlockByScalar(*this, Block); }
|
||||
|
||||
void Eval(float, float, float WorldZ, FVoxelOpSample& InOut) const override
|
||||
{
|
||||
@@ -7203,7 +7302,12 @@ namespace
|
||||
EVoxelOpResourceMask RequiredResources() const override { return VoxelOpResources::RoomGeometry; }
|
||||
bool IsAdditive() const override { return true; }
|
||||
void PrepareChunk(const FVoxelOpContext&) override {}
|
||||
void PrepareBlockSample(const FVoxelOpSample& Sample) const override
|
||||
{
|
||||
if (Rooms != nullptr) { Rooms->RestoreBlockSample(Sample); }
|
||||
}
|
||||
const TCHAR* DebugName() const override { return TEXT("RibbingMod"); }
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override { VF_EvalBlockByScalar(*this, Block); }
|
||||
|
||||
void Eval(float, float, float WorldZ, FVoxelOpSample& InOut) const override
|
||||
{
|
||||
@@ -7295,7 +7399,12 @@ namespace
|
||||
EVoxelOpResourceMask RequiredResources() const override { return VoxelOpResources::RoomGeometry; }
|
||||
bool IsAdditive() const override { return true; }
|
||||
void PrepareChunk(const FVoxelOpContext&) override {}
|
||||
void PrepareBlockSample(const FVoxelOpSample& Sample) const override
|
||||
{
|
||||
if (Rooms != nullptr) { Rooms->RestoreBlockSample(Sample); }
|
||||
}
|
||||
const TCHAR* DebugName() const override { return TEXT("CaveOverhangMod"); }
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override { VF_EvalBlockByScalar(*this, Block); }
|
||||
|
||||
void Eval(float WorldX, float WorldY, float WorldZ, FVoxelOpSample& InOut) const override
|
||||
{
|
||||
@@ -7408,7 +7517,12 @@ namespace
|
||||
EVoxelOpResourceMask RequiredResources() const override { return VoxelOpResources::RoomGeometry; }
|
||||
bool IsAdditive() const override { return true; }
|
||||
void PrepareChunk(const FVoxelOpContext&) override {}
|
||||
void PrepareBlockSample(const FVoxelOpSample& Sample) const override
|
||||
{
|
||||
if (Rooms != nullptr) { Rooms->RestoreBlockSample(Sample); }
|
||||
}
|
||||
const TCHAR* DebugName() const override { return TEXT("CaveCliffMod"); }
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override { VF_EvalBlockByScalar(*this, Block); }
|
||||
|
||||
void Eval(float WorldX, float WorldY, float WorldZ, FVoxelOpSample& InOut) const override
|
||||
{
|
||||
@@ -7518,7 +7632,12 @@ namespace
|
||||
EVoxelOpResourceMask RequiredResources() const override { return VoxelOpResources::RoomGeometry; }
|
||||
bool IsAdditive() const override { return true; }
|
||||
void PrepareChunk(const FVoxelOpContext&) override {}
|
||||
void PrepareBlockSample(const FVoxelOpSample& Sample) const override
|
||||
{
|
||||
if (Rooms != nullptr) { Rooms->RestoreBlockSample(Sample); }
|
||||
}
|
||||
const TCHAR* DebugName() const override { return TEXT("ScallopMod"); }
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override { VF_EvalBlockByScalar(*this, Block); }
|
||||
|
||||
void Eval(float WorldX, float WorldY, float WorldZ, FVoxelOpSample& InOut) const override
|
||||
{
|
||||
@@ -7620,7 +7739,12 @@ namespace
|
||||
EVoxelOpResourceMask RequiredResources() const override { return VoxelOpResources::RoomGeometry; }
|
||||
bool IsAdditive() const override { return true; }
|
||||
void PrepareChunk(const FVoxelOpContext&) override {}
|
||||
void PrepareBlockSample(const FVoxelOpSample& Sample) const override
|
||||
{
|
||||
if (Rooms != nullptr) { Rooms->RestoreBlockSample(Sample); }
|
||||
}
|
||||
const TCHAR* DebugName() const override { return TEXT("CaveArchMod"); }
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override { VF_EvalBlockByScalar(*this, Block); }
|
||||
|
||||
void Eval(float WorldX, float WorldY, float WorldZ, FVoxelOpSample& InOut) const override
|
||||
{
|
||||
@@ -7749,7 +7873,12 @@ namespace
|
||||
EVoxelOpResourceMask RequiredResources() const override { return VoxelOpResources::RoomGeometry; }
|
||||
bool IsAdditive() const override { return true; }
|
||||
void PrepareChunk(const FVoxelOpContext&) override {}
|
||||
void PrepareBlockSample(const FVoxelOpSample& Sample) const override
|
||||
{
|
||||
if (Rooms != nullptr) { Rooms->RestoreBlockSample(Sample); }
|
||||
}
|
||||
const TCHAR* DebugName() const override { return TEXT("RoomColumnMod"); }
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override { VF_EvalBlockByScalar(*this, Block); }
|
||||
|
||||
void Eval(float WorldX, float WorldY, float, FVoxelOpSample& InOut) const override
|
||||
{
|
||||
@@ -7841,7 +7970,12 @@ namespace
|
||||
EVoxelOpResourceMask RequiredResources() const override { return VoxelOpResources::RoomGeometry; }
|
||||
bool IsAdditive() const override { return true; }
|
||||
void PrepareChunk(const FVoxelOpContext&) override {}
|
||||
void PrepareBlockSample(const FVoxelOpSample& Sample) const override
|
||||
{
|
||||
if (Rooms != nullptr) { Rooms->RestoreBlockSample(Sample); }
|
||||
}
|
||||
const TCHAR* DebugName() const override { return TEXT("DomeMod"); }
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override { VF_EvalBlockByScalar(*this, Block); }
|
||||
|
||||
void Eval(float WorldX, float WorldY, float WorldZ, FVoxelOpSample& InOut) const override
|
||||
{
|
||||
@@ -7981,7 +8115,12 @@ namespace
|
||||
EVoxelOpResourceMask RequiredResources() const override { return VoxelOpResources::RoomGeometry; }
|
||||
bool IsAdditive() const override { return true; }
|
||||
void PrepareChunk(const FVoxelOpContext&) override {}
|
||||
void PrepareBlockSample(const FVoxelOpSample& Sample) const override
|
||||
{
|
||||
if (Rooms != nullptr) { Rooms->RestoreBlockSample(Sample); }
|
||||
}
|
||||
const TCHAR* DebugName() const override { return TEXT("PinchMod"); }
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override { VF_EvalBlockByScalar(*this, Block); }
|
||||
|
||||
void Eval(float WorldX, float WorldY, float WorldZ, FVoxelOpSample& InOut) const override
|
||||
{
|
||||
@@ -8107,7 +8246,12 @@ namespace
|
||||
EVoxelOpResourceMask RequiredResources() const override { return VoxelOpResources::RoomGeometry; }
|
||||
bool IsAdditive() const override { return true; }
|
||||
void PrepareChunk(const FVoxelOpContext&) override {}
|
||||
void PrepareBlockSample(const FVoxelOpSample& Sample) const override
|
||||
{
|
||||
if (Rooms != nullptr) { Rooms->RestoreBlockSample(Sample); }
|
||||
}
|
||||
const TCHAR* DebugName() const override { return TEXT("FloorBiasMod"); }
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override { VF_EvalBlockByScalar(*this, Block); }
|
||||
|
||||
void Eval(float, float, float WorldZ, FVoxelOpSample& InOut) const override
|
||||
{
|
||||
@@ -8424,6 +8568,7 @@ namespace
|
||||
}
|
||||
|
||||
const TCHAR* DebugName() const override { return TEXT("WormFieldSource"); }
|
||||
void EvalBlock(const FVoxelOpBlock& Block) const override { VF_EvalBlockByScalar(*this, Block); }
|
||||
|
||||
private:
|
||||
FStrateGenerationParams P;
|
||||
|
||||
Reference in new issue
Block a user