wip(assembler): round S10 -- LOD8 horizon sampled at MC spacing: LOD8 worker time 18.8 s -> 4.3 s
Planar far horizon samples the LOD8 interior at the MC cell spacing, keeping 128-voxel boundary strips; far recipe v3. LOD8 p95 59.8 -> 13.9 ms, spawn worker-seconds ~41 -> 26.9, full set 7.8 -> 7.1 s, ring 0.49 s, LOD0 1.43 s, 40 m/s ring 75/75. S3/S4 2 cm agreement, 100% cap coverage, W1/W8/W12 and W1/W8/W16 determinism pass. Report: Standalone/Research/WorldAssemblerM3/Round14. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
e7586a1256
commit
b90d63d0f7
14 files changed
+616
-86
No files matched your search
@@ -1720,6 +1720,7 @@ namespace
|
||||
bool Keys[256]{};
|
||||
int32 Seed=0;
|
||||
int32 WorkerCount=8;
|
||||
int32 FarHorizonLOD8InteriorStepVoxels=0;
|
||||
int32 ClipRadius=3;
|
||||
int32 MaxClipLevelOverride=-1;
|
||||
int32 CaptureTileLimit=0;
|
||||
@@ -2903,7 +2904,8 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
Streamer=std::make_unique<FStandaloneStreamingGenerator>(*World,StreamWorkers,false,
|
||||
(!bShapeWorld&&MeshCache.IsLoaded())?&MeshCache:nullptr,
|
||||
bFarShapeStagePending?World->FullResClipLevels-1:-1,
|
||||
false,false,false,false,ShapeWorld.get());
|
||||
false,false,false,false,ShapeWorld.get(),false,
|
||||
FarHorizonLOD8InteriorStepVoxels);
|
||||
if(bGpuFarTimelineEnabled)
|
||||
Streamer->EnableColdTimelineTrace(ColdProcessStart,&ColdTimelineFrameOrdinal);
|
||||
if(bGpuFarEnabled&&ShapeWorld&&ShapeWorld->hasFarWorld())
|
||||
@@ -6974,7 +6976,8 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
const FVector& CameraPositionVoxels,int32 WorkerCount,int32 MaxLevel,
|
||||
VoxelForgeCore::DetailVariant DetailVariant,const VoxelForgeCore::JobScheduler& Scheduler,
|
||||
bool bHashDensity,bool bSkipUvAndColors,bool bSkipMaterialGroups,bool bSkipUV,bool bSkipColors,
|
||||
std::chrono::steady_clock::time_point ColdStart)
|
||||
std::chrono::steady_clock::time_point ColdStart,bool bProfileFarColumnOverlap,
|
||||
int32 FarHorizonLOD8InteriorStepVoxels)
|
||||
{
|
||||
using Clock=std::chrono::steady_clock;
|
||||
FStandaloneOwnerWorld& World=*OwnerWorld;
|
||||
@@ -7042,7 +7045,8 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
const auto ShapeReady=Clock::now();
|
||||
const double ShapeSeconds=std::chrono::duration<double>(ShapeReady-ShapeBuildStart).count();
|
||||
FStandaloneStreamingGenerator Streamer(World,WorkerCount,bHashDensity,nullptr,MaxLevel,
|
||||
bSkipUvAndColors,bSkipMaterialGroups,bSkipUV,bSkipColors,&Shape);
|
||||
bSkipUvAndColors,bSkipMaterialGroups,bSkipUV,bSkipColors,&Shape,bProfileFarColumnOverlap,
|
||||
FarHorizonLOD8InteriorStepVoxels);
|
||||
const auto StreamStart=Clock::now();
|
||||
const FStandaloneStreamingUpdate Update=Streamer.StartWithDesired(Desired);
|
||||
if(Update.DesiredTiles!=static_cast<int32>(Desired.Tiles.size()))
|
||||
@@ -7055,6 +7059,43 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
std::vector<FHashedTile> DensityRows,MeshRows,PayloadRows,TopologyRows;
|
||||
int32 Finished=0,NeighborhoodFinished=0,FullDetailFinished=0;
|
||||
int32 FullDetailExpected=0;
|
||||
struct FColumnXY
|
||||
{
|
||||
std::int64_t X=0,Y=0;
|
||||
bool operator==(const FColumnXY&)const=default;
|
||||
};
|
||||
struct FColumnXYHash
|
||||
{
|
||||
std::size_t operator()(const FColumnXY& Value)const noexcept
|
||||
{
|
||||
const std::size_t X=std::hash<std::int64_t>{}(Value.X);
|
||||
const std::size_t Y=std::hash<std::int64_t>{}(Value.Y);
|
||||
return X^(Y+static_cast<std::size_t>(0x9E3779B9u)+(X<<6)+(X>>2));
|
||||
}
|
||||
};
|
||||
struct FFirstColumnUse
|
||||
{
|
||||
FVoxelTileKey Tile;
|
||||
std::uint64_t WorkerHash=0;
|
||||
};
|
||||
std::unordered_map<FColumnXY,FFirstColumnUse,FColumnXYHash> LOD8ColumnFirstUse;
|
||||
std::uint64_t LOD8ColumnDuplicateEvents=0,LOD8NeighbourDuplicateEvents=0;
|
||||
std::uint64_t LOD8CrossWorkerNeighbourDuplicateEvents=0;
|
||||
std::size_t LOD8ColumnCaptureTiles=0;
|
||||
bool bLOD8ColumnCaptureComplete=true;
|
||||
std::array<double,9> WorkerSecondsByLOD{};
|
||||
std::array<double,9> ColumnEvalMsByLOD{},MarchingExclusiveMsByLOD{};
|
||||
std::array<double,9> GroundRefineExclusiveMsByLOD{},CapRefineExclusiveMsByLOD{};
|
||||
std::array<double,9> MeshAssemblyMsByLOD{};
|
||||
std::array<std::uint64_t,9> TileCountByLOD{};
|
||||
const auto AreLOD8Neighbours=[](const FVoxelTileKey& A,const FVoxelTileKey& B)
|
||||
{
|
||||
if(A.Level!=8||B.Level!=8)return false;
|
||||
const std::int64_t DX=std::abs(static_cast<std::int64_t>(A.Coord.X)-B.Coord.X);
|
||||
const std::int64_t DY=std::abs(static_cast<std::int64_t>(A.Coord.Y)-B.Coord.Y);
|
||||
const std::int64_t DZ=std::abs(static_cast<std::int64_t>(A.Coord.Z)-B.Coord.Z);
|
||||
return std::max({DX,DY,DZ})<=1&&(DX+DY+DZ)>0;
|
||||
};
|
||||
uint64 NativeSolidBoxes=0,NativeAirBoxes=0,NativeMixedBoxes=0,NativeUnknownBoxes=0;
|
||||
uint64 NativeFieldCalls=0,NativeColumnHits=0,NativeColumnMisses=0,NativeMeshingSkips=0;
|
||||
double NativeClassificationMilliseconds=0.0,NativeColumnComputeMilliseconds=0.0;
|
||||
@@ -7070,6 +7111,41 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
for(const FStandaloneCpuTile& Tile:Ready)
|
||||
{
|
||||
++Finished;
|
||||
if(Tile.Key.Level>=0&&Tile.Key.Level<static_cast<int32>(TileCountByLOD.size()))
|
||||
{
|
||||
const std::size_t LOD=static_cast<std::size_t>(Tile.Key.Level);
|
||||
++TileCountByLOD[LOD];
|
||||
WorkerSecondsByLOD[LOD]+=Tile.WorkerSeconds;
|
||||
ColumnEvalMsByLOD[LOD]+=Tile.CoreDiagnostics.columnEvaluationExclusiveMilliseconds;
|
||||
MarchingExclusiveMsByLOD[LOD]+=Tile.CoreDiagnostics.marchingCubesExclusiveMilliseconds;
|
||||
GroundRefineExclusiveMsByLOD[LOD]+=Tile.CoreDiagnostics.groundRefinementExclusiveMilliseconds;
|
||||
CapRefineExclusiveMsByLOD[LOD]+=Tile.CoreDiagnostics.capRefinementExclusiveMilliseconds;
|
||||
MeshAssemblyMsByLOD[LOD]+=Tile.CoreDiagnostics.meshAssemblyMilliseconds;
|
||||
}
|
||||
if(bProfileFarColumnOverlap&&Tile.Key.Level==8)
|
||||
{
|
||||
++LOD8ColumnCaptureTiles;
|
||||
bLOD8ColumnCaptureComplete=bLOD8ColumnCaptureComplete
|
||||
&&Tile.CoreDiagnostics.columnCoordinateCaptureComplete;
|
||||
std::vector<std::array<std::int64_t,2>> Coordinates=
|
||||
Tile.CoreDiagnostics.evaluatedColumnCoordinates;
|
||||
std::sort(Coordinates.begin(),Coordinates.end());
|
||||
Coordinates.erase(std::unique(Coordinates.begin(),Coordinates.end()),Coordinates.end());
|
||||
for(const auto& Coordinate:Coordinates)
|
||||
{
|
||||
const FColumnXY XY{Coordinate[0],Coordinate[1]};
|
||||
const auto [First,Inserted]=LOD8ColumnFirstUse.try_emplace(XY,
|
||||
FFirstColumnUse{Tile.Key,Tile.CoreDiagnostics.columnEvaluationWorkerHash});
|
||||
if(Inserted)continue;
|
||||
++LOD8ColumnDuplicateEvents;
|
||||
if(AreLOD8Neighbours(First->second.Tile,Tile.Key))
|
||||
{
|
||||
++LOD8NeighbourDuplicateEvents;
|
||||
if(First->second.WorkerHash!=Tile.CoreDiagnostics.columnEvaluationWorkerHash)
|
||||
++LOD8CrossWorkerNeighbourDuplicateEvents;
|
||||
}
|
||||
}
|
||||
}
|
||||
WholeViewReady=std::max(WholeViewReady,Tile.CompletedAt);
|
||||
if(Neighborhood.contains(Tile.Key))
|
||||
{
|
||||
@@ -7115,6 +7191,22 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
}
|
||||
}
|
||||
Streamer.Stop();
|
||||
if(bProfileFarColumnOverlap)
|
||||
{
|
||||
std::printf("[WorldAssemblerLOD8ColumnOverlap] tiles=%zu unique_xy_columns=%zu repeated_tile_evaluations=%llu neighbouring_duplicate_evaluations=%llu cross_worker_neighbouring_duplicates=%llu capture_complete=%d\n",
|
||||
LOD8ColumnCaptureTiles,LOD8ColumnFirstUse.size(),
|
||||
static_cast<unsigned long long>(LOD8ColumnDuplicateEvents),
|
||||
static_cast<unsigned long long>(LOD8NeighbourDuplicateEvents),
|
||||
static_cast<unsigned long long>(LOD8CrossWorkerNeighbourDuplicateEvents),
|
||||
bLOD8ColumnCaptureComplete?1:0);
|
||||
}
|
||||
for(std::size_t LOD=0;LOD<TileCountByLOD.size();++LOD)
|
||||
{
|
||||
std::printf("[WorldAssemblerLODWorker] lod=%zu tiles=%llu worker_sum_s=%.6f column_eval_exclusive_ms=%.3f mc_exclusive_ms=%.3f ground_refine_exclusive_ms=%.3f cap_refine_exclusive_ms=%.3f mesh_assembly_ms=%.3f\n",
|
||||
LOD,static_cast<unsigned long long>(TileCountByLOD[LOD]),WorkerSecondsByLOD[LOD],
|
||||
ColumnEvalMsByLOD[LOD],MarchingExclusiveMsByLOD[LOD],
|
||||
GroundRefineExclusiveMsByLOD[LOD],CapRefineExclusiveMsByLOD[LOD],MeshAssemblyMsByLOD[LOD]);
|
||||
}
|
||||
const double NeighborhoodSeconds=std::chrono::duration<double>(NeighborhoodReady-ColdStart).count();
|
||||
const double NeighborhoodMeshSeconds=std::chrono::duration<double>(NeighborhoodReady-ShapeReady).count();
|
||||
const double FullDetailSeconds=std::chrono::duration<double>(FullDetailReady-ColdStart).count();
|
||||
@@ -7160,7 +7252,8 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
static_cast<unsigned long long>(HashTileRows(TopologyRows)));
|
||||
}
|
||||
return NeighborhoodFinished==static_cast<int32>(Neighborhood.size())
|
||||
&&FullDetailFinished==FullDetailExpected&&Finished==Update.DesiredTiles&&bHashesPassing?0:6;
|
||||
&&FullDetailFinished==FullDetailExpected&&Finished==Update.DesiredTiles&&bHashesPassing
|
||||
&&(!bProfileFarColumnOverlap||(bLOD8ColumnCaptureComplete&&LOD8ColumnCaptureTiles>0))?0:6;
|
||||
}
|
||||
int RunStreamingBenchmark(FStandaloneOwnerWorld& World,VoxelForgeCore::World* CoreWorld,
|
||||
const FVector& CameraPositionVoxels,
|
||||
@@ -9508,6 +9601,7 @@ int main(int Argc,char** Argv)
|
||||
std::string WorldAssemblyManifestOutputPath;
|
||||
bool bStreamBenchmark=false;
|
||||
bool bStreamPipeline=false;
|
||||
bool bProfileFarColumnOverlap=false;
|
||||
bool bCoarseFirstStreamOrder=false;
|
||||
bool bProfileDetailBand=false;
|
||||
bool bPassageDetailAuditOnly=false;
|
||||
@@ -9530,6 +9624,9 @@ int main(int Argc,char** Argv)
|
||||
{
|
||||
const std::string_view Arg=Argv[I];
|
||||
if(Arg.starts_with("--capture="))App.CapturePath=std::string(Arg.substr(10));
|
||||
else if(Arg.starts_with("--far-horizon-lod8-step="))
|
||||
App.FarHorizonLOD8InteriorStepVoxels=std::max(0,std::atoi(
|
||||
std::string(Arg.substr(std::string_view("--far-horizon-lod8-step=").size())).c_str()));
|
||||
else if(Arg.starts_with("--capture-flight-sequence-prefix="))
|
||||
App.FlightCaptureSequencePrefix=std::string(
|
||||
Arg.substr(std::string_view("--capture-flight-sequence-prefix=").size()));
|
||||
@@ -9642,6 +9739,8 @@ int main(int Argc,char** Argv)
|
||||
else if(Arg=="--coarse-first-stream-order")bCoarseFirstStreamOrder=true;
|
||||
else if(Arg=="--stream-pipeline")
|
||||
{bStreamPipeline=true;bStreamBenchmark=true;App.bShapeWorld=true;App.bForceGenerate=true;}
|
||||
else if(Arg=="--profile-far-column-overlap")
|
||||
{bProfileFarColumnOverlap=true;bStreamPipeline=true;bStreamBenchmark=true;App.bShapeWorld=true;App.bForceGenerate=true;}
|
||||
else if(Arg=="--edit-benchmark")
|
||||
{bEditBenchmark=true;bStreamBenchmark=true;App.bShapeWorld=true;}
|
||||
else if(Arg=="--stream-hash")bStreamHash=true;
|
||||
@@ -9858,7 +9957,8 @@ int main(int Argc,char** Argv)
|
||||
FVector(App.Position.X*4.0,App.Position.Y*4.0,App.Position.Z*4.0),
|
||||
App.WorkerCount,StreamBenchmarkMaxLevel,App.ShapeDetailVariant,App.CoreScheduler,
|
||||
bStreamHash||!BakeMeshCachePath.empty(),bSkipUvAndColors,bSkipMaterialGroups,
|
||||
bSkipUV,bSkipColors,ColdProcessStart);
|
||||
bSkipUV,bSkipColors,ColdProcessStart,bProfileFarColumnOverlap,
|
||||
App.FarHorizonLOD8InteriorStepVoxels);
|
||||
if(bEditBenchmark)
|
||||
return RunEditTransactionBenchmark(*App.World,*App.ShapeWorld,
|
||||
FVector(App.Position.X*4.0,App.Position.Y*4.0,App.Position.Z*4.0),App.WorkerCount);
|
||||
|
||||
Reference in new issue
Block a user