wip(assembler): round L12 -- region pages keep LOD1 block proofs: 24 m crossing 5x faster
Analytic region pages now retain the immutable shared manifest, so LOD1 page tiles get the L9 uniform-block proofs (71.7 -> 5.6 ms per tile). Reviewer W12 no-hash: 24 m crossing 0.898 -> 0.166 s; Luna: 1 km 5.89 -> 1.25 s. Spawn unchanged; all L1/FloatingIslands hashes and the 24 m crossing hash unchanged (W1/W12). KNOWN BUG (pre-existing, measured here): the same tile key yields different density from the base shape (manifest field) than from a region page (legacy field), sometimes different mesh too, so output depends on streaming history. To be fixed in L13. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CSFYgsdW8ejZSyiMf4qRSX
This commit is contained in:
1 parent
b1cfaf53b8
commit
32b8670833
6 files changed
+292
-23
No files matched your search
@@ -42,6 +42,7 @@ namespace
|
||||
bool ScreenSpaceGate=false;
|
||||
bool AuditUniformBlockProofs=false;
|
||||
bool ProfileLodWork=false;
|
||||
bool AuditBasePageEquivalence=false;
|
||||
bool RegionCrossing=false;
|
||||
bool AuditTileShapeReadiness=false;
|
||||
int DiagnosticSlowShapeCompileMs=0;
|
||||
@@ -120,6 +121,7 @@ namespace
|
||||
" --screen-space-gate (measure display error and historical negative controls)\n"
|
||||
" --audit-uniform-block-proofs (fill and check every interval-certified block)\n"
|
||||
" --profile-lod-work (report per-LOD density sample counts)\n"
|
||||
" --audit-base-page-equivalence (hash one tile through both shape routes)\n"
|
||||
" --audit-tile-shape-readiness (run a deliberately mis-marked tile against the native-only guard)\n"
|
||||
" --diagnostic-slow-shape-compile-ms=N (diagnostic overlap control; default 0)\n"
|
||||
" --render-distance-chunks=N (0 disables the extra far ring)\n"
|
||||
@@ -139,6 +141,7 @@ namespace
|
||||
else if(arg=="--screen-space-gate")options.ScreenSpaceGate=true;
|
||||
else if(arg=="--audit-uniform-block-proofs")options.AuditUniformBlockProofs=true;
|
||||
else if(arg=="--profile-lod-work")options.ProfileLodWork=true;
|
||||
else if(arg=="--audit-base-page-equivalence")options.AuditBasePageEquivalence=true;
|
||||
else if(arg=="--region-crossing")options.RegionCrossing=true;
|
||||
else if(arg=="--audit-tile-shape-readiness")options.AuditTileShapeReadiness=true;
|
||||
else if(arg=="--auto-surface-camera")options.AutoSurfaceCamera=true;
|
||||
@@ -370,5 +373,5 @@ int main(int argc,char** argv)
|
||||
options.CameraPitchDegrees,options.ScreenSpaceGate,options.UseSharedColumnCache,
|
||||
cameraStepVoxels,options.AuditUniformBlockProofs,options.ProfileLodWork,
|
||||
options.RegionCrossing,options.AuditTileShapeReadiness,
|
||||
options.DiagnosticSlowShapeCompileMs);
|
||||
options.DiagnosticSlowShapeCompileMs,options.AuditBasePageEquivalence);
|
||||
}
|
||||
@@ -144,7 +144,8 @@ namespace StandaloneStreamBenchmark
|
||||
bool bUseSharedColumnCache=true,FVector CameraStepVoxels=FVector::ZeroVector,
|
||||
bool bAuditUniformBlockProofs=false,bool bReportLodWorkProfile=false,
|
||||
bool bRegionCrossing=false,
|
||||
bool bAuditTileShapeReadiness=false,int DiagnosticSlowShapeCompileMs=0)
|
||||
bool bAuditTileShapeReadiness=false,int DiagnosticSlowShapeCompileMs=0,
|
||||
bool bAuditBasePageEquivalence=false)
|
||||
{
|
||||
using Clock=std::chrono::steady_clock;
|
||||
FStandaloneOwnerWorld& World=*OwnerWorld;
|
||||
@@ -304,7 +305,7 @@ namespace StandaloneStreamBenchmark
|
||||
bSkipUvAndColors,bSkipMaterialGroups,bSkipUV,bSkipColors,&Shape,bProfileColumnOverlap,
|
||||
FarHorizonLOD8InteriorStepVoxels,bUseSharedColumnCache);
|
||||
Streamer.SetUniformBlockProofAuditEnabled(bAuditUniformBlockProofs);
|
||||
if(bScreenSpaceGate)Streamer.SetMesherStageProfilingEnabled(true);
|
||||
if(bScreenSpaceGate||bReportLodWorkProfile)Streamer.SetMesherStageProfilingEnabled(true);
|
||||
const auto StreamStart=Clock::now();
|
||||
const FStandaloneStreamingUpdate EarlyUpdate=Streamer.StartWithDesired(ShapeFreeDesired);
|
||||
if(EarlyUpdate.DesiredTiles!=static_cast<int32>(ShapeFreeDesired.Tiles.size()))
|
||||
@@ -371,6 +372,106 @@ namespace StandaloneStreamBenchmark
|
||||
return 9;
|
||||
}
|
||||
}
|
||||
if(bAuditBasePageEquivalence)
|
||||
{
|
||||
std::vector<VoxelForgeCore::TileKey> AuditKeys;
|
||||
AuditKeys.reserve(48);
|
||||
const auto AddAuditCandidates=[&](int32 PreferredLOD)
|
||||
{
|
||||
const std::size_t ExistingCount=AuditKeys.size();
|
||||
for(const FVoxelTileKey& Tile:Desired.Tiles)
|
||||
{
|
||||
if(Tile.Level!=PreferredLOD)continue;
|
||||
const VoxelForgeCore::TileKey Key{{Tile.Coord.X,Tile.Coord.Y,Tile.Coord.Z},
|
||||
Tile.Level};
|
||||
if(Shape.isTileShapeFree(Key)||Shape.needsTileRegion(Key))continue;
|
||||
if(std::find(AuditKeys.begin(),AuditKeys.end(),Key)==AuditKeys.end())
|
||||
AuditKeys.push_back(Key);
|
||||
if(AuditKeys.size()>=48||AuditKeys.size()-ExistingCount>=4)return;
|
||||
}
|
||||
};
|
||||
for(int32 PreferredLOD:{1,0,2,3,4,5,6,7,8})
|
||||
{
|
||||
AddAuditCandidates(PreferredLOD);
|
||||
if(AuditKeys.size()>=48)break;
|
||||
}
|
||||
if(AuditKeys.empty())
|
||||
{
|
||||
std::printf("[BasePageTileEquivalence] status=UNAVAILABLE reason=no_tile_reachable_through_both_routes\n");
|
||||
Streamer.Stop();
|
||||
return 9;
|
||||
}
|
||||
VoxelForgeCore::TileGenerationOptions HashOptions;
|
||||
HashOptions.hashDensity=true;
|
||||
HashOptions.profileMesherStages=true;
|
||||
bool bFoundEquivalentTile=false;
|
||||
std::size_t CandidatesTried=0;
|
||||
VoxelForgeCore::TileKey EquivalentKey{};
|
||||
for(const VoxelForgeCore::TileKey& AuditKey:AuditKeys)
|
||||
{
|
||||
++CandidatesTried;
|
||||
std::string BaseError,PageError,CompileError;
|
||||
const auto BaseGenerationStart=Clock::now();
|
||||
const auto BaseTile=Shape.generateTile(AuditKey,HashOptions,BaseError);
|
||||
const double BaseGenerationSeconds=std::chrono::duration<double>(
|
||||
Clock::now()-BaseGenerationStart).count();
|
||||
if(!BaseTile)
|
||||
{
|
||||
std::printf("[BasePageTileEquivalenceCandidate] key=(%d,%d,%d,lod%d) base=FAIL reason=%s\n",
|
||||
AuditKey.coordinate.x,AuditKey.coordinate.y,AuditKey.coordinate.z,
|
||||
AuditKey.lod,BaseError.c_str());
|
||||
continue;
|
||||
}
|
||||
const std::array<VoxelForgeCore::TileKey,1> AuditTiles={AuditKey};
|
||||
VoxelForgeCore::TileRegionCompileStats PageBuildStats;
|
||||
std::size_t PageTileCount=0;
|
||||
const auto PageCompileStart=Clock::now();
|
||||
const bool bPageBuilt=Shape.compileTileRegion(AuditTiles,
|
||||
static_cast<std::uint32_t>(std::clamp(WorkerCount,1,16)),Scheduler,
|
||||
CompileError,&PageTileCount,&PageBuildStats,true,true);
|
||||
const double PageCompileSeconds=std::chrono::duration<double>(
|
||||
Clock::now()-PageCompileStart).count();
|
||||
const auto PageGenerationStart=Clock::now();
|
||||
const auto PageTile=bPageBuilt?Shape.generateTile(AuditKey,HashOptions,PageError)
|
||||
:std::optional<VoxelForgeCore::TileMesh>{};
|
||||
const double PageGenerationSeconds=std::chrono::duration<double>(
|
||||
Clock::now()-PageGenerationStart).count();
|
||||
const bool bDensitySame=PageTile&&BaseTile->densityHash==PageTile->densityHash;
|
||||
const bool bMeshSame=PageTile&&BaseTile->meshHash==PageTile->meshHash;
|
||||
const bool bPayloadSame=PageTile&&BaseTile->payloadHash==PageTile->payloadHash;
|
||||
const bool bTopologySame=PageTile&&BaseTile->topologyHash==PageTile->topologyHash;
|
||||
const bool bActualPage=PageTile&&PageTile->diagnostics.analyticRegionPageRoute;
|
||||
const int32 Matches=static_cast<int32>(bDensitySame)+static_cast<int32>(bMeshSame)
|
||||
+static_cast<int32>(bPayloadSame)+static_cast<int32>(bTopologySame);
|
||||
const bool bSame=bActualPage&&Matches==4;
|
||||
std::printf("[BasePageTileEquivalenceCandidate] key=(%d,%d,%d,lod%d) page_built=%d page_route_verified=%d page_keys=%zu page_nodes=%llu base_route=base-shape page_route=analytic-page base_generation_ms=%.3f page_compile_ms=%.3f page_generation_ms=%.3f density=%s mesh=%s payload=%s topology=%s base_density=0x%016llx page_density=0x%016llx status=%s error=%s\n",
|
||||
AuditKey.coordinate.x,AuditKey.coordinate.y,AuditKey.coordinate.z,AuditKey.lod,
|
||||
bPageBuilt?1:0,bActualPage?1:0,PageTileCount,
|
||||
static_cast<unsigned long long>(PageBuildStats.latticeNodes),
|
||||
BaseGenerationSeconds*1000.0,PageCompileSeconds*1000.0,
|
||||
PageGenerationSeconds*1000.0,
|
||||
bDensitySame?"same":"DIFF",bMeshSame?"same":"DIFF",
|
||||
bPayloadSame?"same":"DIFF",bTopologySame?"same":"DIFF",
|
||||
static_cast<unsigned long long>(BaseTile->densityHash),
|
||||
static_cast<unsigned long long>(PageTile?PageTile->densityHash:0),
|
||||
bSame?"PASS":"DIFF",bPageBuilt?PageError.c_str():CompileError.c_str());
|
||||
if(bSame)
|
||||
{
|
||||
bFoundEquivalentTile=true;
|
||||
EquivalentKey=AuditKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::printf("[BasePageTileEquivalence] candidates=%zu tried=%zu matching_key=(%d,%d,%d,lod%d) status=%s\n",
|
||||
AuditKeys.size(),CandidatesTried,EquivalentKey.coordinate.x,
|
||||
EquivalentKey.coordinate.y,EquivalentKey.coordinate.z,EquivalentKey.lod,
|
||||
bFoundEquivalentTile?"PASS":"FAIL");
|
||||
if(!bFoundEquivalentTile)
|
||||
{
|
||||
Streamer.Stop();
|
||||
return 9;
|
||||
}
|
||||
}
|
||||
const FStandaloneStreamingUpdate Update=Streamer.UpdateDesiredWithSet(Desired,{},0);
|
||||
if(Update.DesiredTiles!=static_cast<int32>(Desired.Tiles.size()))
|
||||
{
|
||||
@@ -431,6 +532,7 @@ namespace StandaloneStreamBenchmark
|
||||
std::array<bool,9> ColumnCaptureCompleteByLOD{};
|
||||
ColumnCaptureCompleteByLOD.fill(true);
|
||||
std::array<double,9> WorkerSecondsByLOD{};
|
||||
std::array<double,9> BaseRouteWorkerSecondsByLOD{},PageRouteWorkerSecondsByLOD{};
|
||||
std::array<double,9> ColumnEvalMsByLOD{},MarchingExclusiveMsByLOD{};
|
||||
std::array<double,9> GroundRefineExclusiveMsByLOD{},CapRefineExclusiveMsByLOD{};
|
||||
std::array<double,9> MeshAssemblyMsByLOD{};
|
||||
@@ -438,6 +540,7 @@ namespace StandaloneStreamBenchmark
|
||||
std::array<std::uint64_t,9> DensitySamplesByLOD{};
|
||||
std::array<std::uint64_t,9> SkirtTrianglesByLOD{};
|
||||
std::array<std::uint64_t,9> TileCountByLOD{};
|
||||
std::array<std::uint64_t,9> BaseRouteTilesByLOD{},PageRouteTilesByLOD{};
|
||||
for(const FVoxelTileKey& Tile:Desired.Tiles)
|
||||
if(Tile.Level>=0&&Tile.Level<static_cast<int32>(ExpectedTilesByLOD.size()))
|
||||
++ExpectedTilesByLOD[static_cast<std::size_t>(Tile.Level)];
|
||||
@@ -487,6 +590,19 @@ namespace StandaloneStreamBenchmark
|
||||
const std::size_t LOD=static_cast<std::size_t>(Tile.Key.Level);
|
||||
++TileCountByLOD[LOD];
|
||||
WorkerSecondsByLOD[LOD]+=Tile.WorkerSeconds;
|
||||
if(bReportLodWorkProfile)
|
||||
{
|
||||
if(Tile.CoreDiagnostics.analyticRegionPageRoute)
|
||||
{
|
||||
++PageRouteTilesByLOD[LOD];
|
||||
PageRouteWorkerSecondsByLOD[LOD]+=Tile.WorkerSeconds;
|
||||
}
|
||||
else
|
||||
{
|
||||
++BaseRouteTilesByLOD[LOD];
|
||||
BaseRouteWorkerSecondsByLOD[LOD]+=Tile.WorkerSeconds;
|
||||
}
|
||||
}
|
||||
ColumnEvalMsByLOD[LOD]+=Tile.CoreDiagnostics.columnEvaluationExclusiveMilliseconds;
|
||||
MarchingExclusiveMsByLOD[LOD]+=Tile.CoreDiagnostics.marchingCubesExclusiveMilliseconds;
|
||||
GroundRefineExclusiveMsByLOD[LOD]+=Tile.CoreDiagnostics.groundRefinementExclusiveMilliseconds;
|
||||
@@ -636,6 +752,16 @@ namespace StandaloneStreamBenchmark
|
||||
const auto MovingUpdate=Streamer.UpdateDesiredWithSet(MovedDesired,Desired.Tiles,1);
|
||||
std::array<std::uint64_t,9> MovingTilesByLOD{};
|
||||
std::array<double,9> MovingWorkerSecondsByLOD{};
|
||||
std::array<std::uint64_t,9> MovingSamplesByLOD{},MovingNativeFloatCallsByLOD{},
|
||||
MovingNativeLatticeCallsByLOD{},MovingNativeOnlyTilesByLOD{},
|
||||
MovingAnalyticPageTilesByLOD{},MovingNativeSurfaceTilesByLOD{};
|
||||
std::array<std::uint64_t,9> MovingBaseRouteTilesByLOD{};
|
||||
std::array<double,9> MovingBaseRouteWorkerSecondsByLOD{},
|
||||
MovingPageRouteWorkerSecondsByLOD{};
|
||||
std::array<double,9> MovingColumnComputeMsByLOD{},MovingClassificationMsByLOD{},
|
||||
MovingMcExclusiveMsByLOD{},MovingMcDensityGridMsByLOD{},
|
||||
MovingMcCellClassMsByLOD{},MovingMcGradientMsByLOD{},
|
||||
MovingMcInterpolationMsByLOD{},MovingMcDedupMsByLOD{},MovingMcOtherMsByLOD{};
|
||||
std::vector<FHashedTile> MovingDensityRows,MovingMeshRows,
|
||||
MovingPayloadRows,MovingTopologyRows;
|
||||
int32 MovingFinished=0;
|
||||
@@ -652,6 +778,32 @@ namespace StandaloneStreamBenchmark
|
||||
const std::size_t LOD=static_cast<std::size_t>(Tile.Key.Level);
|
||||
++MovingTilesByLOD[LOD];
|
||||
MovingWorkerSecondsByLOD[LOD]+=Tile.WorkerSeconds;
|
||||
if(bReportLodWorkProfile)
|
||||
{
|
||||
const auto& D=Tile.CoreDiagnostics;
|
||||
MovingSamplesByLOD[LOD]+=Tile.DensitySamples;
|
||||
MovingNativeFloatCallsByLOD[LOD]+=D.floatFieldCalls;
|
||||
MovingNativeLatticeCallsByLOD[LOD]+=D.latticeFieldCalls;
|
||||
MovingNativeOnlyTilesByLOD[LOD]+=D.nativeOnlyRoute?1u:0u;
|
||||
MovingAnalyticPageTilesByLOD[LOD]+=D.analyticRegionPageRoute?1u:0u;
|
||||
MovingNativeSurfaceTilesByLOD[LOD]+=D.nativeSurfaceTile?1u:0u;
|
||||
if(D.analyticRegionPageRoute)
|
||||
MovingPageRouteWorkerSecondsByLOD[LOD]+=Tile.WorkerSeconds;
|
||||
else
|
||||
{
|
||||
++MovingBaseRouteTilesByLOD[LOD];
|
||||
MovingBaseRouteWorkerSecondsByLOD[LOD]+=Tile.WorkerSeconds;
|
||||
}
|
||||
MovingColumnComputeMsByLOD[LOD]+=D.columnEvaluationExclusiveMilliseconds;
|
||||
MovingClassificationMsByLOD[LOD]+=D.classificationExclusiveMilliseconds;
|
||||
MovingMcExclusiveMsByLOD[LOD]+=D.marchingCubesExclusiveMilliseconds;
|
||||
MovingMcDensityGridMsByLOD[LOD]+=D.marchingCubesDensityGridMilliseconds;
|
||||
MovingMcCellClassMsByLOD[LOD]+=D.marchingCubesCellClassificationMilliseconds;
|
||||
MovingMcGradientMsByLOD[LOD]+=D.marchingCubesGradientNormalsMilliseconds;
|
||||
MovingMcInterpolationMsByLOD[LOD]+=D.marchingCubesEdgeInterpolationMilliseconds;
|
||||
MovingMcDedupMsByLOD[LOD]+=D.marchingCubesVertexDedupStreamMilliseconds;
|
||||
MovingMcOtherMsByLOD[LOD]+=D.marchingCubesOtherMilliseconds;
|
||||
}
|
||||
}
|
||||
if(bHashDensity)
|
||||
{
|
||||
@@ -693,9 +845,32 @@ namespace StandaloneStreamBenchmark
|
||||
?"PASS":"FAIL");
|
||||
for(std::size_t LOD=0;LOD<MovingTilesByLOD.size();++LOD)
|
||||
if(MovingTilesByLOD[LOD]!=0)
|
||||
{
|
||||
std::printf("[MovingCameraStepLOD] lod=%zu tiles=%llu worker_sum_s=%.6f\n",
|
||||
LOD,static_cast<unsigned long long>(MovingTilesByLOD[LOD]),
|
||||
MovingWorkerSecondsByLOD[LOD]);
|
||||
if(bReportLodWorkProfile)
|
||||
std::printf("[MovingCameraStepLODProfile] lod=%zu density_samples=%llu samples_per_tile=%.1f native_float_calls=%llu native_lattice_calls=%llu native_surface_tiles=%llu native_only_tiles=%llu analytic_page_tiles=%llu base_route_tiles=%llu base_route_avg_ms=%.3f page_route_avg_ms=%.3f column_compute_ms=%.3f classification_ms=%.3f mc_exclusive_ms=%.3f mc_density_grid_ms=%.3f mc_cell_class_ms=%.3f mc_gradient_ms=%.3f mc_interpolation_ms=%.3f mc_dedup_ms=%.3f mc_other_ms=%.3f\n",
|
||||
LOD,static_cast<unsigned long long>(MovingSamplesByLOD[LOD]),
|
||||
static_cast<double>(MovingSamplesByLOD[LOD])/MovingTilesByLOD[LOD],
|
||||
static_cast<unsigned long long>(MovingNativeFloatCallsByLOD[LOD]),
|
||||
static_cast<unsigned long long>(MovingNativeLatticeCallsByLOD[LOD]),
|
||||
static_cast<unsigned long long>(MovingNativeSurfaceTilesByLOD[LOD]),
|
||||
static_cast<unsigned long long>(MovingNativeOnlyTilesByLOD[LOD]),
|
||||
static_cast<unsigned long long>(MovingAnalyticPageTilesByLOD[LOD]),
|
||||
static_cast<unsigned long long>(MovingBaseRouteTilesByLOD[LOD]),
|
||||
MovingBaseRouteTilesByLOD[LOD]
|
||||
?MovingBaseRouteWorkerSecondsByLOD[LOD]*1000.0
|
||||
/MovingBaseRouteTilesByLOD[LOD]:0.0,
|
||||
MovingAnalyticPageTilesByLOD[LOD]
|
||||
?MovingPageRouteWorkerSecondsByLOD[LOD]*1000.0
|
||||
/MovingAnalyticPageTilesByLOD[LOD]:0.0,
|
||||
MovingColumnComputeMsByLOD[LOD],MovingClassificationMsByLOD[LOD],
|
||||
MovingMcExclusiveMsByLOD[LOD],MovingMcDensityGridMsByLOD[LOD],
|
||||
MovingMcCellClassMsByLOD[LOD],MovingMcGradientMsByLOD[LOD],
|
||||
MovingMcInterpolationMsByLOD[LOD],MovingMcDedupMsByLOD[LOD],
|
||||
MovingMcOtherMsByLOD[LOD]);
|
||||
}
|
||||
}
|
||||
Streamer.Stop();
|
||||
bool bScreenSpaceGatePassing=true;
|
||||
@@ -809,6 +984,13 @@ namespace StandaloneStreamBenchmark
|
||||
?static_cast<double>(DensitySamplesByLOD[LOD])/TileCountByLOD[LOD]:0.0;
|
||||
std::printf("[WorldAssemblerLODSamples] lod=%zu samples=%llu samples_per_tile=%.1f\n",
|
||||
LOD,static_cast<unsigned long long>(DensitySamplesByLOD[LOD]),SamplesPerTile);
|
||||
std::printf("[WorldAssemblerLODRouteProfile] lod=%zu base_shape_tiles=%llu base_shape_avg_ms=%.3f analytic_page_tiles=%llu analytic_page_avg_ms=%.3f\n",
|
||||
LOD,static_cast<unsigned long long>(BaseRouteTilesByLOD[LOD]),
|
||||
BaseRouteTilesByLOD[LOD]
|
||||
?BaseRouteWorkerSecondsByLOD[LOD]*1000.0/BaseRouteTilesByLOD[LOD]:0.0,
|
||||
static_cast<unsigned long long>(PageRouteTilesByLOD[LOD]),
|
||||
PageRouteTilesByLOD[LOD]
|
||||
?PageRouteWorkerSecondsByLOD[LOD]*1000.0/PageRouteTilesByLOD[LOD]:0.0);
|
||||
}
|
||||
}
|
||||
const double NeighborhoodSeconds=std::chrono::duration<double>(NeighborhoodReady-ColdStart).count();
|
||||
|
||||
Reference in new issue
Block a user