standalone: cheap far-survival repairs -- whole view 1.80 -> 1.40 s, payload 277 -> 111 MiB

- Far repairs are source-aware (only where the sampled mesh lost a shell) and redundant radius probes
  trimmed; ~175k two-triangle repair panels remain (+18 MiB over the no-shell 92.6 MiB).
- Pipelined start builds the shape world once; the 27-tile neighbourhood is ready ~0.73 s from
  process start; pipelined whole view is no slower than direct.
- Far audit passes, bad-shell control still fails (16 missing / 16 holes); look audits pass; routes
  5642/5642; 60 W1/W8 + direct/pipeline hash fields equal; six fixed captures pixel-identical.
Verified by me head to head (8 workers, cold, BelowNormal 0xFF00, quiet machine, two runs each):
1.40 s vs 1.80 s for the previous default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-05 01:56:41 +02:00
1 parent a40b0454b3
commit d4fa89204d
4 files changed
+837 -303

No files matched your search

+69 -136
View File
@@ -674,7 +674,9 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
std::printf("Standalone max clip level override applied after world reload: max_level=%d.\n",
MaxClipLevelOverride);
}
if(bShapeWorld&&!BuildShapeWorldForCamera(Error,false,true))return false;
// Compile one world field before streaming. The streamer already prioritizes the
// player's neighborhood, so a second near-only field would only duplicate work.
if(bShapeWorld&&!BuildShapeWorldForCamera(Error,true,false))return false;
LoadMeshCache();
return true;
}
@@ -1889,111 +1891,64 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
}
if(FineMin.X==INT32_MAX||ClipMin.X==INT32_MAX)
{std::fprintf(stderr,"[StreamPipeline] no desired detail or clipmap tiles.\n");return 7;}
const FIntVector CenterChunk=Desired.CenterChunk;
std::vector<FVoxelTileKey> Neighborhood;
FIntVector NearMin(INT32_MAX,INT32_MAX,INT32_MAX),NearMax(INT32_MIN,INT32_MIN,INT32_MIN);
std::unordered_set<FVoxelTileKey,FStandaloneTileKeyHash> Neighborhood;
Neighborhood.reserve(32);
for(const FVoxelTileKey& Tile:Desired.Tiles)
{
if(Tile.Level!=0||std::abs(Tile.Coord.X-CenterChunk.X)>1
||std::abs(Tile.Coord.Y-CenterChunk.Y)>1||std::abs(Tile.Coord.Z-CenterChunk.Z)>1)continue;
Neighborhood.push_back(Tile);const FIntVector Origin=Tile.OriginVoxels();const int32 Extent=Tile.ExtentVoxels();
NearMin.X=std::min(NearMin.X,Origin.X);NearMin.Y=std::min(NearMin.Y,Origin.Y);NearMin.Z=std::min(NearMin.Z,Origin.Z);
NearMax.X=std::max(NearMax.X,Origin.X+Extent);NearMax.Y=std::max(NearMax.Y,Origin.Y+Extent);NearMax.Z=std::max(NearMax.Z,Origin.Z+Extent);
}
if(Neighborhood.empty())
{std::fprintf(stderr,"[StreamPipeline] the player neighborhood is absent from the desired set.\n");return 7;}
constexpr int32 NearBuildPad=64;
NearMin.X-=NearBuildPad;NearMin.Y-=NearBuildPad;NearMin.Z-=NearBuildPad;
NearMax.X+=NearBuildPad;NearMax.Y+=NearBuildPad;NearMax.Z+=NearBuildPad;
const int32 NearWorkers=WorkerCount>=8?2:1;
const int32 FullBuildWorkers=WorkerCount>=8?6:1;
auto NearShape=std::make_unique<FStandaloneShapeWorld>();
if(Tile.Level==0&&std::abs(Tile.Coord.X-CenterChunk.X)<=1
&&std::abs(Tile.Coord.Y-CenterChunk.Y)<=1&&std::abs(Tile.Coord.Z-CenterChunk.Z)<=1)
Neighborhood.insert(Tile);
if(Neighborhood.size()!=27)
{std::fprintf(stderr,"[StreamPipeline] expected 27 player-neighborhood tiles, found %zu.\n",Neighborhood.size());return 7;}
FStandaloneShapeWorld Shape;
std::string BuildError;
const auto NearBuildStart=Clock::now();
if(!NearShape->Build(World,NearMin,NearMax,ClipMin,ClipMax,NearWorkers,
DetailVariant,false,BuildError))
{std::fprintf(stderr,"[StreamPipeline] near shape build failed: %s\n",BuildError.c_str());return 2;}
const double NearShapeSeconds=std::chrono::duration<double>(Clock::now()-NearBuildStart).count();
FStandaloneShapeWorldAccess::SetActive(NearShape.get());
FStandaloneStreamingGenerator NearStreamer(World,NearWorkers,bHashDensity,nullptr,MaxLevel,
const bool bIncludeFarWorld=MaxLevel<0||MaxLevel>=World.FullResClipLevels;
const auto ShapeBuildStart=Clock::now();
if(!Shape.Build(World,FineMin,FineMax,ClipMin,ClipMax,WorkerCount,
DetailVariant,bIncludeFarWorld,BuildError))
{std::fprintf(stderr,"[StreamPipeline] full shape build failed: %s\n",BuildError.c_str());return 2;}
const auto ShapeReady=Clock::now();
const double ShapeSeconds=std::chrono::duration<double>(ShapeReady-ShapeBuildStart).count();
FStandaloneShapeWorldAccess::SetActive(&Shape);
FStandaloneStreamingGenerator Streamer(World,WorkerCount,bHashDensity,nullptr,MaxLevel,
bSkipUvAndColors,bSkipMaterialGroups,bSkipUV,bSkipColors);
NearStreamer.SetDesiredTileFilter(Neighborhood);
const auto NearStreamStart=Clock::now();
const FStandaloneStreamingUpdate NearUpdate=NearStreamer.Start(CameraPositionVoxels);
if(NearUpdate.DesiredTiles!=static_cast<int32>(Neighborhood.size()))
{NearStreamer.Stop();FStandaloneShapeWorldAccess::SetActive(nullptr);
std::fprintf(stderr,"[StreamPipeline] expected %zu player tiles but queued %d.\n",Neighborhood.size(),NearUpdate.DesiredTiles);return 7;}
FStandaloneShapeWorld FullShape;
bool bFullBuildOk=false;std::string FullBuildError;
const auto FullBuildStart=Clock::now();
std::thread FullBuildThread([&]
{bFullBuildOk=FullShape.Build(World,FineMin,FineMax,ClipMin,ClipMax,FullBuildWorkers,
DetailVariant,true,FullBuildError);});
struct FPipelineTileHashes {uint64 Density=0,Mesh=0,Payload=0,Topology=0;};
std::unordered_map<FVoxelTileKey,FPipelineTileHashes,FStandaloneTileKeyHash> NearHashByKey;
NearHashByKey.reserve(Neighborhood.size()*2+1);
std::vector<FHashedTile> DensityRows,MeshRows,PayloadRows,TopologyRows;
std::vector<FStandaloneCpuTile> NearTiles;NearTiles.reserve(Neighborhood.size());
std::chrono::steady_clock::time_point NeighborhoodReady{};
int32 NearFinished=0;
while(NearFinished<NearUpdate.DesiredTiles)
const auto StreamStart=Clock::now();
const FStandaloneStreamingUpdate Update=Streamer.Start(CameraPositionVoxels);
if(Update.DesiredTiles!=static_cast<int32>(Desired.Tiles.size()))
{
std::vector<FStandaloneCpuTile> Ready=NearStreamer.TakeReady();
if(Ready.empty()){std::this_thread::sleep_for(std::chrono::milliseconds(1));continue;}
for(FStandaloneCpuTile& Tile:Ready)
{
++NearFinished;
if(bHashDensity)
{
if(Tile.bHasDensityHash)DensityRows.push_back({Tile.Key,Tile.DensityHash});
if(Tile.bHasMeshHash)MeshRows.push_back({Tile.Key,Tile.MeshHash});
if(Tile.bHasPayloadHash)PayloadRows.push_back({Tile.Key,Tile.PayloadHash});
if(Tile.bHasTopologyHash)TopologyRows.push_back({Tile.Key,Tile.TopologyHash});
NearHashByKey[Tile.Key]={Tile.DensityHash,Tile.MeshHash,Tile.PayloadHash,Tile.TopologyHash};
}
NeighborhoodReady=std::max(NeighborhoodReady,Tile.CompletedAt);
NearTiles.push_back(std::move(Tile));
}
Streamer.Stop();FStandaloneShapeWorldAccess::SetActive(nullptr);
std::fprintf(stderr,"[StreamPipeline] expected %zu tiles but queued %d.\n",
Desired.Tiles.size(),Update.DesiredTiles);return 7;
}
NearStreamer.Stop();
const double NearStreamSeconds=std::chrono::duration<double>(NeighborhoodReady-NearStreamStart).count();
FStandaloneShapeWorldAccess::SetActive(nullptr);
// Release the small shape before the large build finishes allocating its packed field.
NearTiles.clear();NearTiles.shrink_to_fit();NearShape.reset();
FullBuildThread.join();
const double FullShapeSeconds=std::chrono::duration<double>(Clock::now()-FullBuildStart).count();
if(!bFullBuildOk)
{std::fprintf(stderr,"[StreamPipeline] full shape build failed: %s\n",FullBuildError.c_str());return 2;}
FStandaloneShapeWorldAccess::SetActive(&FullShape);
std::unordered_set<FVoxelTileKey,FStandaloneTileKeyHash> NearSet;
NearSet.reserve(Neighborhood.size()*2+1);for(const FVoxelTileKey& Key:Neighborhood)NearSet.insert(Key);
std::vector<FVoxelTileKey> Remaining;Remaining.reserve(Desired.Tiles.size()-Neighborhood.size());
std::vector<FHashedTile> DensityRows,MeshRows,PayloadRows,TopologyRows;
int32 Finished=0,NeighborhoodFinished=0,FullDetailFinished=0;
int32 FullDetailExpected=0;
for(const FVoxelTileKey& Tile:Desired.Tiles)
{
if(Tile.Level<World.FullResClipLevels)++FullDetailExpected;
if(!NearSet.contains(Tile))Remaining.push_back(Tile);
}
FStandaloneStreamingGenerator FullStreamer(World,WorkerCount,bHashDensity,nullptr,MaxLevel,
bSkipUvAndColors,bSkipMaterialGroups,bSkipUV,bSkipColors);
FullStreamer.SetDesiredTileFilter(Remaining);
const auto FillStart=Clock::now();
const FStandaloneStreamingUpdate FillUpdate=FullStreamer.Start(CameraPositionVoxels);
int32 Finished=0,FullDetailFinished=static_cast<int32>(Neighborhood.size());
const int32 FullDetailRemaining=std::max(0,FullDetailExpected-FullDetailFinished);
std::chrono::steady_clock::time_point FullDetailReady=NeighborhoodReady,WholeViewReady{};
bool bFullDetailReported=false;
while(Finished<FillUpdate.DesiredTiles)
Clock::time_point NeighborhoodReady{},FullDetailReady{},WholeViewReady{};
bool bNeighborhoodReported=false,bFullDetailReported=false;
while(Finished<Update.DesiredTiles)
{
std::vector<FStandaloneCpuTile> Ready=FullStreamer.TakeReady();
std::vector<FStandaloneCpuTile> Ready=Streamer.TakeReady();
if(Ready.empty()){std::this_thread::sleep_for(std::chrono::milliseconds(1));continue;}
for(const FStandaloneCpuTile& Tile:Ready)
{
++Finished;WholeViewReady=std::max(WholeViewReady,Tile.CompletedAt);
++Finished;
WholeViewReady=std::max(WholeViewReady,Tile.CompletedAt);
if(Neighborhood.contains(Tile.Key))
{
++NeighborhoodFinished;
NeighborhoodReady=std::max(NeighborhoodReady,Tile.CompletedAt);
}
if(Tile.Key.Level<World.FullResClipLevels)
{++FullDetailFinished;FullDetailReady=std::max(FullDetailReady,Tile.CompletedAt);}
{
++FullDetailFinished;
FullDetailReady=std::max(FullDetailReady,Tile.CompletedAt);
}
if(bHashDensity)
{
if(Tile.bHasDensityHash)DensityRows.push_back({Tile.Key,Tile.DensityHash});
@@ -2002,7 +1957,13 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
if(Tile.bHasTopologyHash)TopologyRows.push_back({Tile.Key,Tile.TopologyHash});
}
}
if(!bFullDetailReported&&FullDetailRemaining>0&&FullDetailFinished>=FullDetailExpected)
if(!bNeighborhoodReported&&NeighborhoodFinished==static_cast<int32>(Neighborhood.size()))
{
std::printf("[PipelineMilestone] neighborhood_ready=%.3fs generated=%d/27\n",
std::chrono::duration<double>(NeighborhoodReady-ColdStart).count(),NeighborhoodFinished);
bNeighborhoodReported=true;
}
if(!bFullDetailReported&&FullDetailFinished==FullDetailExpected)
{
std::printf("[PipelineMilestone] full_detail_ready=%.3fs generated=%d/%d\n",
std::chrono::duration<double>(FullDetailReady-ColdStart).count(),
@@ -2010,51 +1971,24 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
bFullDetailReported=true;
}
}
FullStreamer.Stop();
const double WholeViewSeconds=std::chrono::duration<double>(WholeViewReady-ColdStart).count();
Streamer.Stop();
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();
bool bNearParityPassing=true;
if(bHashDensity)
{
FStandaloneStreamingGenerator NearVerifier(World,NearWorkers,true,nullptr,MaxLevel,
bSkipUvAndColors,bSkipMaterialGroups,bSkipUV,bSkipColors);
NearVerifier.SetDesiredTileFilter(Neighborhood);
const FStandaloneStreamingUpdate VerifyUpdate=NearVerifier.Start(CameraPositionVoxels);
int32 VerifiedTiles=0,NearHashMismatches=0;
while(VerifiedTiles<VerifyUpdate.DesiredTiles)
{
std::vector<FStandaloneCpuTile> Ready=NearVerifier.TakeReady();
if(Ready.empty()){std::this_thread::sleep_for(std::chrono::milliseconds(1));continue;}
for(const FStandaloneCpuTile& Tile:Ready)
{
++VerifiedTiles;
const auto It=NearHashByKey.find(Tile.Key);
if(It==NearHashByKey.end()||!Tile.bHasDensityHash||!Tile.bHasMeshHash
||!Tile.bHasPayloadHash||!Tile.bHasTopologyHash
||It->second.Density!=Tile.DensityHash||It->second.Mesh!=Tile.MeshHash
||It->second.Payload!=Tile.PayloadHash||It->second.Topology!=Tile.TopologyHash)
{
++NearHashMismatches;
if(NearHashMismatches<=4)
std::fprintf(stderr,"[PipelineNeighborhoodHashMismatch] key=(%d,%d,%d,lod%d)\n",
Tile.Key.Coord.X,Tile.Key.Coord.Y,Tile.Key.Coord.Z,Tile.Key.Level);
}
}
}
NearVerifier.Stop();
bNearParityPassing=VerifiedTiles==static_cast<int32>(Neighborhood.size())
&&NearHashMismatches==0;
std::printf("[PipelineNeighborhoodParity] tiles=%d/%zu hash_fields=%d mismatched_tiles=%d status=%s\n",
VerifiedTiles,Neighborhood.size(),VerifiedTiles*4,NearHashMismatches,
bNearParityPassing?"PASS":"FAIL");
}
std::printf("[StreamPipeline] workers=%d near_mesh_workers=%d full_shape_workers=%d near_shape=%.3fs near_mesh=%.3fs full_shape=%.3fs neighborhood_ready=%.3fs full_detail_ready=%.3fs whole_view_ready=%.3fs neighborhood_tiles=%zu/%zu full_detail_tiles=%d/%d whole_tiles=%d/%zu cache_hits=0 full_payload=1\n",
WorkerCount,NearWorkers,FullBuildWorkers,NearShapeSeconds,NearStreamSeconds,FullShapeSeconds,
NeighborhoodSeconds,FullDetailSeconds,WholeViewSeconds,Neighborhood.size(),Neighborhood.size(),
FullDetailFinished,FullDetailExpected,static_cast<int32>(Desired.Tiles.size()),Desired.Tiles.size());
const double WholeViewSeconds=std::chrono::duration<double>(WholeViewReady-ColdStart).count();
const double StreamSeconds=std::chrono::duration<double>(WholeViewReady-StreamStart).count();
std::printf("[StreamPipeline] workers=%d shape=%.3fs neighborhood_mesh=%.3fs neighborhood_ready=%.3fs full_detail_ready=%.3fs whole_view_ready=%.3fs neighborhood_tiles=%d/27 full_detail_tiles=%d/%d whole_tiles=%d/%zu stream_wall=%.3fs cache_hits=0 full_payload=1\n",
WorkerCount,ShapeSeconds,NeighborhoodMeshSeconds,NeighborhoodSeconds,
FullDetailSeconds,WholeViewSeconds,NeighborhoodFinished,
FullDetailFinished,FullDetailExpected,Finished,Desired.Tiles.size(),StreamSeconds);
bool bHashesPassing=true;
if(bHashDensity)
{
bHashesPassing=DensityRows.size()==Desired.Tiles.size()
&&MeshRows.size()==Desired.Tiles.size()
&&PayloadRows.size()==Desired.Tiles.size()
&&TopologyRows.size()==Desired.Tiles.size();
std::vector<FHashedTile> FullDensity,FullMesh,FullPayload,FullTopology;
for(const FHashedTile& Row:DensityRows)if(Row.Key.Level<World.FullResClipLevels)FullDensity.push_back(Row);
for(const FHashedTile& Row:MeshRows)if(Row.Key.Level<World.FullResClipLevels)FullMesh.push_back(Row);
@@ -2072,10 +2006,9 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
static_cast<unsigned long long>(HashTileRows(TopologyRows)));
}
FStandaloneShapeWorldAccess::SetActive(nullptr);
return FullDetailFinished==FullDetailExpected&&Finished==FillUpdate.DesiredTiles
&&bNearParityPassing?0:6;
return NeighborhoodFinished==static_cast<int32>(Neighborhood.size())
&&FullDetailFinished==FullDetailExpected&&Finished==Update.DesiredTiles&&bHashesPassing?0:6;
}
int RunStreamingBenchmark(FStandaloneOwnerWorld& World,const FVector& CameraPositionVoxels,
int32 WorkerCount,int32 MaxLevel,bool bRoundTunnels,
bool bEnhancedWalls,const FStandaloneMeshCache* Cache,