standalone: cheap chunk crossings -- exact-tile slab compile, nearest tiles first (~1.2 s -> 121 ms peak)
- Core compiles exact-tile analytic slabs for entering tiles; a Z-column sampler reuses the coherent
noise context along each tile column; the viewer keeps residents and prioritises nearby tiles.
- 30-crossing straight flight: nearest tile ready 15.8 ms median / 27.6 ms max; full crossing wall
121 ms peak; worker CPU per crossing 545 ms median, 834 ms max.
- W1/W8 hashes equal; routes 5642/5642; look, passage, stair, thin-sheet, coarse-panel and far
audits pass; bad-shell control fails; path-hash audit kept.
Cold whole view, measured by me interleaved (busy machine): 1.242 s vs 1.255 s for 3b37d57, parity.
Still open from the owner (LOD0): fins along a strata seam, choppy stair facets.
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
3b37d5702e
commit
08ceed200d
7 files changed
+614
-86
No files matched your search
@@ -442,7 +442,17 @@ namespace
|
||||
uint64 Samples=0;
|
||||
double WorkerSeconds=0.0;
|
||||
double CorePageSeconds=0.0;
|
||||
double CorePageWorkerSeconds=0.0;
|
||||
uint64 PageCoveredTiles=0;
|
||||
uint64 PageRegions=0;
|
||||
uint64 PageLatticeNodes=0;
|
||||
FVoxelTileKey NearestNewTile{};
|
||||
double NearestReadySeconds=-1.0;
|
||||
bool bHasNearestNewTile=false;
|
||||
uint64 TilesByLevel[MaxLevels+1]{};
|
||||
uint64 SamplesByLevel[MaxLevels+1]{};
|
||||
double WorkerSecondsByLevel[MaxLevels+1]{};
|
||||
double WallSeconds=0.0;
|
||||
std::chrono::steady_clock::time_point StartTime{};
|
||||
bool bReported=false;
|
||||
};
|
||||
@@ -559,11 +569,16 @@ namespace
|
||||
bool bCompareEvaluators=false;
|
||||
bool bParityOnly=false;
|
||||
bool bDensityHash=false;
|
||||
bool bTestOneChunkCrossing=false;
|
||||
bool bCrossingMoveStarted=false;
|
||||
bool bCrossingMoveFinished=false;
|
||||
bool bCrossingClosePosted=false;
|
||||
std::chrono::steady_clock::time_point CrossingMoveStopTime{};
|
||||
int32 FlightTargetCrossings=0;
|
||||
int32 FlightObservedCrossings=0;
|
||||
uint64 FlightStartCrossingIndex=0;
|
||||
float FlightSpeedMps=16.0f;
|
||||
bool bFlightStarted=false;
|
||||
bool bFlightFinished=false;
|
||||
bool bFlightClosePosted=false;
|
||||
bool bFlightCrossingsValid=true;
|
||||
V3 FlightStartPosition{};
|
||||
std::chrono::steady_clock::time_point FlightStartTime{};
|
||||
bool bCaptureAfterClipmap=false;
|
||||
bool bQuitAfterClipmap=false;
|
||||
bool bPrintedClipOverride=false;
|
||||
@@ -1198,6 +1213,14 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
}
|
||||
if(NewDesired.CenterChunk==BuildTargetChunk)return;
|
||||
const FIntVector Previous=BuildTargetChunk;
|
||||
const FIntVector CenterDelta(NewDesired.CenterChunk.X-Previous.X,
|
||||
NewDesired.CenterChunk.Y-Previous.Y,NewDesired.CenterChunk.Z-Previous.Z);
|
||||
if(FlightTargetCrossings>0&&bFlightStarted&&!bFlightFinished)
|
||||
{
|
||||
++FlightObservedCrossings;
|
||||
if(CenterDelta.X!=0||CenterDelta.Y!=1||CenterDelta.Z!=0)
|
||||
bFlightCrossingsValid=false;
|
||||
}
|
||||
std::unordered_set<FVoxelTileKey,FStandaloneTileKeyHash> NewSet;
|
||||
NewSet.reserve(NewDesired.Tiles.size()*2+1);
|
||||
for(const FVoxelTileKey& Key:NewDesired.Tiles)NewSet.insert(Key);
|
||||
@@ -1206,6 +1229,17 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
const auto CrossingStart=std::chrono::steady_clock::now();
|
||||
double PageCompileSeconds=0.0;
|
||||
uint64 PageCoveredTiles=0;
|
||||
VoxelForgeCore::TileRegionCompileStats PageStats;
|
||||
const uint64 NextCrossing=CrossingIndex+1;
|
||||
FCrossingWork& NextWork=CrossingWork[NextCrossing];
|
||||
NextWork.StartTime=CrossingStart;
|
||||
for(const FVoxelTileKey& Key:NewDesired.Tiles)
|
||||
if(NewSet.contains(Key)&&!ResidentTiles.contains(Key))
|
||||
{
|
||||
NextWork.NearestNewTile=Key;
|
||||
NextWork.bHasNearestNewTile=true;
|
||||
break;
|
||||
}
|
||||
if(bShapeWorld&&ShapeWorld)
|
||||
{
|
||||
std::vector<VoxelForgeCore::TileKey> NewCoreTiles;
|
||||
@@ -1216,8 +1250,8 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
std::string PageError;
|
||||
size_t CompiledPageCount=0;
|
||||
if(!ShapeWorld->compileTileRegion(NewCoreTiles,
|
||||
static_cast<uint32>(std::min(4,WorkerCount)),CoreScheduler,PageError,
|
||||
&CompiledPageCount))
|
||||
static_cast<uint32>(std::clamp(WorkerCount,1,8)),CoreScheduler,PageError,
|
||||
&CompiledPageCount,&PageStats,true))
|
||||
{
|
||||
std::fprintf(stderr,"[ShapeRegionPage] compile failed at center=(%d,%d,%d): %s\n",
|
||||
NewDesired.CenterChunk.X,NewDesired.CenterChunk.Y,NewDesired.CenterChunk.Z,
|
||||
@@ -1233,11 +1267,13 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
for(const FVoxelTileKey& Key:Leavers)DeferredLeaverTiles.insert(Key);
|
||||
const double PageSeconds=std::chrono::duration<double>(
|
||||
std::chrono::steady_clock::now()-CrossingStart).count();
|
||||
PageCompileSeconds=PageSeconds;
|
||||
std::printf("[ShapeRegionPage] center=(%d,%d,%d) requested_tiles=%zu page_covered_tiles=%llu worker_limit=%d seconds=%.4f retained_resident=%zu deferred_leavers=%zu\n",
|
||||
PageCompileSeconds=PageStats.wallSeconds;
|
||||
std::printf("[ShapeRegionPage] region_mode=analytic-lod-slab center=(%d,%d,%d) requested_tiles=%zu page_covered_tiles=%llu regions=%zu lattice_nodes=%llu worker_limit=%d shape=%.4fs intervals_signs=%.4fs detail=%.4fs core_worker_sum=%.4fs seconds=%.4f retained_resident=%zu deferred_leavers=%zu\n",
|
||||
NewDesired.CenterChunk.X,NewDesired.CenterChunk.Y,NewDesired.CenterChunk.Z,
|
||||
NewCoreTiles.size(),static_cast<unsigned long long>(PageCoveredTiles),
|
||||
std::min(4,WorkerCount),PageSeconds,
|
||||
PageStats.regionsBuilt,static_cast<unsigned long long>(PageStats.latticeNodes),
|
||||
std::clamp(WorkerCount,1,8),PageStats.shapeSeconds,PageStats.intervalSeconds,
|
||||
PageStats.surfaceSeconds,PageStats.workerSeconds,PageSeconds,
|
||||
ResidentTiles.size()-std::min(ResidentTiles.size(),Leavers.size()),Leavers.size());
|
||||
}
|
||||
else
|
||||
@@ -1260,8 +1296,9 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
}
|
||||
FCrossingWork& Work=CrossingWork[CrossingIndex];
|
||||
Work.SubmittedJobs=Update.NewJobs;Work.PendingJobs=Update.NewJobs;
|
||||
Work.StartTime=CrossingStart;
|
||||
Work.PageCoveredTiles=PageCoveredTiles;Work.CorePageSeconds=PageCompileSeconds;
|
||||
Work.CorePageWorkerSeconds=PageStats.workerSeconds;
|
||||
Work.PageRegions=PageStats.regionsBuilt;Work.PageLatticeNodes=PageStats.latticeNodes;
|
||||
BuildTargetChunk=Update.CenterChunk;bGenerationRunning=true;
|
||||
std::printf("[ChunkCrossing] id=%llu center=(%d,%d,%d) delta=(%d,%d,%d) desired=%d retained=%d new_jobs=%d deferred_resident=%zu cancelled_queued=%d full_detail=%d\n",
|
||||
static_cast<unsigned long long>(CrossingIndex),Update.CenterChunk.X,Update.CenterChunk.Y,Update.CenterChunk.Z,
|
||||
@@ -1416,9 +1453,11 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
Work.bReported=true;
|
||||
const double AverageMs=Work.FinishedJobs>0
|
||||
?Work.WorkerSeconds*1000.0/static_cast<double>(Work.FinishedJobs):0.0;
|
||||
const double WallSeconds=Work.StartTime.time_since_epoch().count()!=0
|
||||
Work.WallSeconds=Work.StartTime.time_since_epoch().count()!=0
|
||||
?std::chrono::duration<double>(std::chrono::steady_clock::now()-Work.StartTime).count():0.0;
|
||||
std::printf("[ChunkCrossingWork] id=%llu submitted=%llu finished=%llu generated=%llu cancelled_queued=%llu stale=%llu samples=%.2fM page_covered_tiles=%llu core_page=%.4fs worker_sum=%.3fs wall=%.3fs avg=%.3fms\n",
|
||||
const double NearestReadyMs=Work.NearestReadySeconds>=0.0
|
||||
?Work.NearestReadySeconds*1000.0:-1.0;
|
||||
std::printf("[ChunkCrossingWork] id=%llu submitted=%llu finished=%llu generated=%llu cancelled_queued=%llu stale=%llu samples=%.2fM page_covered_tiles=%llu page_regions=%llu page_nodes=%llu core_page=%.4fs core_page_worker=%.4fs nearest_ready=%.3fms nearest_tile=(%d,%d,%d,lod%d) worker_sum=%.3fs wall=%.3fs avg=%.3fms\n",
|
||||
static_cast<unsigned long long>(Pair.first),
|
||||
static_cast<unsigned long long>(Work.SubmittedJobs),
|
||||
static_cast<unsigned long long>(Work.FinishedJobs),
|
||||
@@ -1426,8 +1465,22 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
static_cast<unsigned long long>(Work.CancelledQueuedJobs),
|
||||
static_cast<unsigned long long>(Work.StaleResults),
|
||||
static_cast<double>(Work.Samples)/1.0e6,
|
||||
static_cast<unsigned long long>(Work.PageCoveredTiles),Work.CorePageSeconds,
|
||||
Work.WorkerSeconds,WallSeconds,AverageMs);
|
||||
static_cast<unsigned long long>(Work.PageCoveredTiles),
|
||||
static_cast<unsigned long long>(Work.PageRegions),
|
||||
static_cast<unsigned long long>(Work.PageLatticeNodes),
|
||||
Work.CorePageSeconds,Work.CorePageWorkerSeconds,NearestReadyMs,
|
||||
Work.NearestNewTile.Coord.X,Work.NearestNewTile.Coord.Y,
|
||||
Work.NearestNewTile.Coord.Z,Work.NearestNewTile.Level,
|
||||
Work.WorkerSeconds,Work.WallSeconds,AverageMs);
|
||||
for(int32 Level=0;Level<=MaxLevels;++Level)
|
||||
if(Work.TilesByLevel[Level]>0)
|
||||
std::printf("[ChunkCrossingLevel] id=%llu lod=%d tiles=%llu samples=%.3fM worker_sum=%.4fs avg=%.3fms\n",
|
||||
static_cast<unsigned long long>(Pair.first),Level,
|
||||
static_cast<unsigned long long>(Work.TilesByLevel[Level]),
|
||||
static_cast<double>(Work.SamplesByLevel[Level])/1.0e6,
|
||||
Work.WorkerSecondsByLevel[Level],
|
||||
Work.WorkerSecondsByLevel[Level]*1000.0/
|
||||
static_cast<double>(Work.TilesByLevel[Level]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1442,6 +1495,16 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
FCrossingWork& Crossing=CrossingWork[Tile.RequestedCrossing];
|
||||
if(Crossing.PendingJobs>0)--Crossing.PendingJobs;
|
||||
++Crossing.FinishedJobs;Crossing.Samples+=Tile.DensitySamples;Crossing.WorkerSeconds+=Tile.WorkerSeconds;
|
||||
if(Level>=0&&Level<=MaxLevels)
|
||||
{
|
||||
++Crossing.TilesByLevel[Level];
|
||||
Crossing.SamplesByLevel[Level]+=Tile.DensitySamples;
|
||||
Crossing.WorkerSecondsByLevel[Level]+=Tile.WorkerSeconds;
|
||||
}
|
||||
if(Crossing.bHasNearestNewTile&&Tile.Key==Crossing.NearestNewTile
|
||||
&&Crossing.NearestReadySeconds<0.0)
|
||||
Crossing.NearestReadySeconds=std::chrono::duration<double>(
|
||||
Tile.CompletedAt-Crossing.StartTime).count();
|
||||
if(!Streamer->IsDesired(Tile.Key)||ResidentTiles.contains(Tile.Key))
|
||||
{++Crossing.StaleResults;continue;}
|
||||
++Crossing.Tiles;
|
||||
@@ -1475,14 +1538,56 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
}
|
||||
}
|
||||
if(bShapePipelineActive)TryCompleteShapePipeline();
|
||||
if(bTestOneChunkCrossing&&bCrossingMoveFinished&&!bCrossingClosePosted
|
||||
&&DirtyBatchSet.empty())
|
||||
if(FlightTargetCrossings>0&&bFlightFinished&&!bFlightClosePosted
|
||||
&&DirtyBatchSet.empty()&&DeferredLeaverTiles.empty())
|
||||
{
|
||||
const auto Crossing=CrossingWork.find(1);
|
||||
if(Crossing!=CrossingWork.end()&&Crossing->second.bReported)
|
||||
bool bAllFlightWorkReported=true;
|
||||
bool bCrossingLatencyUnderTarget=true;
|
||||
double MaxCrossingWallSeconds=0.0,MaxWorkerCpuSeconds=0.0;
|
||||
std::vector<double> NearestReadyMilliseconds;
|
||||
for(uint64 Crossing=FlightStartCrossingIndex+1;
|
||||
Crossing<=CrossingIndex;++Crossing)
|
||||
{
|
||||
bCrossingClosePosted=true;
|
||||
std::printf("[CrossingTestComplete] crossing work and its bounded uploads drained; closing this test viewer.\n");
|
||||
const auto It=CrossingWork.find(Crossing);
|
||||
if(It==CrossingWork.end()||!It->second.bReported)
|
||||
{bAllFlightWorkReported=false;continue;}
|
||||
const FCrossingWork& Work=It->second;
|
||||
MaxCrossingWallSeconds=std::max(MaxCrossingWallSeconds,Work.WallSeconds);
|
||||
MaxWorkerCpuSeconds=std::max(MaxWorkerCpuSeconds,Work.WorkerSeconds);
|
||||
if(Work.WallSeconds>=0.200)bCrossingLatencyUnderTarget=false;
|
||||
if(Work.NearestReadySeconds>=0.0)
|
||||
NearestReadyMilliseconds.push_back(Work.NearestReadySeconds*1000.0);
|
||||
}
|
||||
if(bAllFlightWorkReported)
|
||||
{
|
||||
bFlightClosePosted=true;
|
||||
const double Elapsed=std::chrono::duration<double>(
|
||||
std::chrono::steady_clock::now()-FlightStartTime).count();
|
||||
const uint64 CacheHits=Streamer?Streamer->GetCacheHits():0;
|
||||
std::size_t DesiredResidentCount=0;
|
||||
for(const FVoxelTileKey& Key:DesiredTiles)
|
||||
if(ResidentTiles.contains(Key))++DesiredResidentCount;
|
||||
std::sort(NearestReadyMilliseconds.begin(),NearestReadyMilliseconds.end());
|
||||
const auto Percentile=[&](std::size_t Percent)
|
||||
{
|
||||
if(NearestReadyMilliseconds.empty())return -1.0;
|
||||
const std::size_t Index=(NearestReadyMilliseconds.size()-1)*Percent/100;
|
||||
return NearestReadyMilliseconds[Index];
|
||||
};
|
||||
const double NearestMaximum=NearestReadyMilliseconds.empty()?-1.0:
|
||||
NearestReadyMilliseconds.back();
|
||||
const std::size_t MissingDesired=DesiredTiles.size()-DesiredResidentCount;
|
||||
const bool bPass=FlightObservedCrossings==FlightTargetCrossings
|
||||
&&bFlightCrossingsValid&&CacheHits==0&&bCrossingLatencyUnderTarget
|
||||
&&MissingDesired==0&&DeferredLeaverTiles.empty()&&DirtyBatchSet.empty();
|
||||
std::printf("[FlightBenchmarkComplete] crossings=%d/%d speed=%.2fm/s elapsed=%.3fs cache_hits=%llu crossing_deltas=%s nearest_ready_p50=%.3fms nearest_ready_p95=%.3fms nearest_ready_max=%.3fms max_crossing_wall=%.3fs max_worker_cpu_sum=%.3fs resident=%zu/%zu missing_tiles=%zu deferred_leavers=%zu uploads_drained=%s status=%s\n",
|
||||
FlightObservedCrossings,FlightTargetCrossings,FlightSpeedMps,Elapsed,
|
||||
static_cast<unsigned long long>(CacheHits),
|
||||
bFlightCrossingsValid?"unit-+Y":"invalid",
|
||||
Percentile(50),Percentile(95),NearestMaximum,MaxCrossingWallSeconds,
|
||||
MaxWorkerCpuSeconds,DesiredResidentCount,DesiredTiles.size(),MissingDesired,
|
||||
DeferredLeaverTiles.size(),DirtyBatchSet.empty()?"yes":"no",
|
||||
bPass?"PASS":"FAIL");
|
||||
std::fflush(stdout);
|
||||
PostMessageA(Window,WM_CLOSE,0,0);
|
||||
}
|
||||
@@ -1547,20 +1652,27 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
{
|
||||
PumpGeneration();
|
||||
const auto Now=std::chrono::steady_clock::now();
|
||||
if(bTestOneChunkCrossing&&bFullDetailReported&&!bCrossingMoveStarted&&!bCrossingMoveFinished)
|
||||
if(FlightTargetCrossings>0&&bFullDetailReported&&!bFlightStarted)
|
||||
{
|
||||
bCrossingMoveStarted=true;
|
||||
CrossingMoveStopTime=Now+std::chrono::milliseconds(350);
|
||||
Keys[VK_SHIFT]=true;Keys['W']=true;
|
||||
std::printf("[CrossingTestMove] moving forward for 350 ms after full detail.\n");
|
||||
bFlightStarted=true;FlightStartTime=Now;FlightStartPosition=Position;
|
||||
FlightStartCrossingIndex=CrossingIndex;FlightObservedCrossings=0;
|
||||
bFlightCrossingsValid=true;
|
||||
std::printf("[FlightBenchmarkStart] crossings=%d speed=%.2fm/s direction=+Y start=(%.2f,%.2f,%.2f)m cache_mode=none\n",
|
||||
FlightTargetCrossings,FlightSpeedMps,Position.X,Position.Y,Position.Z);
|
||||
std::fflush(stdout);
|
||||
}
|
||||
if(bCrossingMoveStarted&&Now>=CrossingMoveStopTime)
|
||||
if(FlightTargetCrossings>0&&bFlightStarted&&!bFlightFinished)
|
||||
{
|
||||
Keys[VK_SHIFT]=false;Keys['W']=false;
|
||||
bCrossingMoveStarted=false;bCrossingMoveFinished=true;
|
||||
std::printf("[CrossingTestMove] movement stopped; waiting for crossing work and uploads.\n");
|
||||
std::fflush(stdout);
|
||||
const double Elapsed=std::chrono::duration<double>(Now-FlightStartTime).count();
|
||||
Position=V3(FlightStartPosition.X,FlightStartPosition.Y+
|
||||
static_cast<float>(FlightSpeedMps*Elapsed),FlightStartPosition.Z);
|
||||
if(FlightObservedCrossings>=FlightTargetCrossings)
|
||||
{
|
||||
bFlightFinished=true;
|
||||
std::printf("[FlightBenchmarkMove] movement stopped after %d center-chunk crossings; waiting for new nearest tiles, meshes and uploads.\n",
|
||||
FlightObservedCrossings);
|
||||
std::fflush(stdout);
|
||||
}
|
||||
}
|
||||
const float Dt=std::clamp(std::chrono::duration<float>(Now-PreviousFrame).count(),0.0f,0.1f);
|
||||
PreviousFrame=Now;FrameMs=Dt*1000.0;
|
||||
@@ -2807,7 +2919,7 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
const std::array<VoxelForgeCore::TileKey,1> pageTiles={target};
|
||||
std::size_t pageTilesA=0;
|
||||
if(!base.compileTileRegion(pageTiles,static_cast<uint32>(std::clamp(workers,1,8)),
|
||||
scheduler,error,&pageTilesA))
|
||||
scheduler,error,&pageTilesA,nullptr,false))
|
||||
{std::fprintf(stderr,"[TilePathHashAudit] path-A page compile failed: %s\n",error.c_str());return 11;}
|
||||
auto pathA=base.generateTile(target,options,error);
|
||||
if(!pathA){std::fprintf(stderr,"[TilePathHashAudit] path-A generation failed: %s\n",error.c_str());return 11;}
|
||||
@@ -2839,7 +2951,63 @@ float3 Lit=Rock*(Ambient+0.88*Diffuse)+float3(0.50,0.69,0.82)*Head*0.75;
|
||||
static_cast<unsigned long long>(pathB->payloadHash),
|
||||
static_cast<unsigned long long>(pathA->topologyHash),
|
||||
static_cast<unsigned long long>(pathB->topologyHash),pass?"PASS":"FAIL");
|
||||
return pass?0:12;
|
||||
|
||||
VoxelForgeCore::World analyticForward(snapshot),analyticReverse(snapshot);
|
||||
VoxelForgeCore::ShapeBuildRequest forwardRequest,reverseRequest;
|
||||
const FVector reverseCamera((target.coordinate.x+TargetChunkOffset+0.5)*CHUNK_SIZE,
|
||||
camera.Y,camera.Z);
|
||||
const auto reverseTiles=base.desiredTiles(
|
||||
{reverseCamera.X,reverseCamera.Y,reverseCamera.Z});
|
||||
if(!MakeRegionBuildRequest(baseTiles,config,workers,detail,roundTunnels,
|
||||
enhancedWalls,forwardRequest,error)
|
||||
||!analyticForward.compile(forwardRequest,scheduler,error)
|
||||
||reverseTiles.empty()
|
||||
||!MakeRegionBuildRequest(reverseTiles,config,workers,detail,roundTunnels,
|
||||
enhancedWalls,reverseRequest,error)
|
||||
||!analyticReverse.compile(reverseRequest,scheduler,error))
|
||||
{std::fprintf(stderr,"[TilePathHashDirections] setup failed: %s\n",error.c_str());return 11;}
|
||||
std::size_t analyticForwardCovered=0,analyticReverseCovered=0;
|
||||
VoxelForgeCore::TileRegionCompileStats forwardStats,reverseStats;
|
||||
if(!analyticForward.compileTileRegion(pageTiles,static_cast<uint32>(std::clamp(workers,1,8)),
|
||||
scheduler,error,&analyticForwardCovered,&forwardStats,true)
|
||||
||!analyticReverse.compileTileRegion(pageTiles,static_cast<uint32>(std::clamp(workers,1,8)),
|
||||
scheduler,error,&analyticReverseCovered,&reverseStats,true))
|
||||
{std::fprintf(stderr,"[TilePathHashDirections] region compile failed: %s\n",error.c_str());return 11;}
|
||||
auto analyticPathForward=analyticForward.generateTile(target,options,error);
|
||||
auto analyticPathReverse=analyticReverse.generateTile(target,options,error);
|
||||
if(!analyticPathForward||!analyticPathReverse)
|
||||
{std::fprintf(stderr,"[TilePathHashDirections] tile generation failed: %s\n",error.c_str());return 11;}
|
||||
const bool analyticDirectionsSame=Same(*analyticPathForward,*analyticPathReverse);
|
||||
const bool packedAnalyticRenderSame=pathA->meshHash==analyticPathForward->meshHash
|
||||
&&pathA->payloadHash==analyticPathForward->payloadHash
|
||||
&&pathA->topologyHash==analyticPathForward->topologyHash;
|
||||
const bool packedAnalyticDensitySame=pathA->densityHash==analyticPathForward->densityHash;
|
||||
std::printf("[TilePathHashDirections] tile=(%d,%d,%d) lod=%d approach_deltas=(-%d,+%d) regions=(%zu,%zu) density=(0x%016llx,0x%016llx) mesh=(0x%016llx,0x%016llx) payload=(0x%016llx,0x%016llx) topology=(0x%016llx,0x%016llx) status=%s\n",
|
||||
target.coordinate.x,target.coordinate.y,target.coordinate.z,target.lod,
|
||||
TargetChunkOffset,TargetChunkOffset,analyticForwardCovered,analyticReverseCovered,
|
||||
static_cast<unsigned long long>(analyticPathForward->densityHash),
|
||||
static_cast<unsigned long long>(analyticPathReverse->densityHash),
|
||||
static_cast<unsigned long long>(analyticPathForward->meshHash),
|
||||
static_cast<unsigned long long>(analyticPathReverse->meshHash),
|
||||
static_cast<unsigned long long>(analyticPathForward->payloadHash),
|
||||
static_cast<unsigned long long>(analyticPathReverse->payloadHash),
|
||||
static_cast<unsigned long long>(analyticPathForward->topologyHash),
|
||||
static_cast<unsigned long long>(analyticPathReverse->topologyHash),
|
||||
analyticDirectionsSame&&analyticForwardCovered==1&&analyticReverseCovered==1?"PASS":"FAIL");
|
||||
std::printf("[TilePathPackedAnalyticParity] tile=(%d,%d,%d) density=(0x%016llx,0x%016llx) density_representation=%s mesh=(0x%016llx,0x%016llx) payload=(0x%016llx,0x%016llx) topology=(0x%016llx,0x%016llx) status=%s\n",
|
||||
target.coordinate.x,target.coordinate.y,target.coordinate.z,
|
||||
static_cast<unsigned long long>(pathA->densityHash),
|
||||
static_cast<unsigned long long>(analyticPathForward->densityHash),
|
||||
packedAnalyticDensitySame?"same":"different",
|
||||
static_cast<unsigned long long>(pathA->meshHash),
|
||||
static_cast<unsigned long long>(analyticPathForward->meshHash),
|
||||
static_cast<unsigned long long>(pathA->payloadHash),
|
||||
static_cast<unsigned long long>(analyticPathForward->payloadHash),
|
||||
static_cast<unsigned long long>(pathA->topologyHash),
|
||||
static_cast<unsigned long long>(analyticPathForward->topologyHash),
|
||||
packedAnalyticRenderSame?"PASS":"FAIL");
|
||||
return pass&&analyticDirectionsSame&&analyticForwardCovered==1
|
||||
&&analyticReverseCovered==1&&packedAnalyticRenderSame?0:12;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2928,7 +3096,21 @@ int main(int Argc,char** Argv)
|
||||
else if(Arg.starts_with("--max-clip-level="))
|
||||
MaxClipLevelOverride=std::clamp(
|
||||
std::atoi(std::string(Arg.substr(17)).c_str()),0,8);
|
||||
else if(Arg=="--test-one-chunk-crossing")App.bTestOneChunkCrossing=true;
|
||||
else if(Arg=="--test-one-chunk-crossing")
|
||||
{
|
||||
App.FlightTargetCrossings=1;
|
||||
App.bShapeWorld=true;
|
||||
}
|
||||
else if(Arg.starts_with("--test-flight-crossings="))
|
||||
{
|
||||
App.FlightTargetCrossings=std::max(1,std::atoi(
|
||||
std::string(Arg.substr(std::string_view("--test-flight-crossings=").size())).c_str()));
|
||||
App.bShapeWorld=true;
|
||||
}
|
||||
else if(Arg.starts_with("--flight-speed-mps="))
|
||||
App.FlightSpeedMps=std::clamp(std::strtof(
|
||||
std::string(Arg.substr(std::string_view("--flight-speed-mps=").size())).c_str(),nullptr),
|
||||
1.0f,256.0f);
|
||||
else if(Arg=="--capture-after-clipmap")App.bCaptureAfterClipmap=true;
|
||||
else if(Arg=="--quit-after-clipmap")App.bQuitAfterClipmap=true;
|
||||
else if(Arg.starts_with("--workers="))
|
||||
|
||||
@@ -1040,9 +1040,49 @@ FVoxelMeshData UVoxelMarchingCubesMesher::GenerateMesh(FIntVector OriginVoxels,
|
||||
const int64 TileExtentVoxels = static_cast<int64>(Step) * CellsPerAxis;
|
||||
const bool bUseVerticalCacheTraversal = TileExtentVoxels > CHUNK_SIZE * 16;
|
||||
const FStandaloneShapeWorld* ActiveShapeWorld=ShapeWorldContext;
|
||||
const bool bUseShapeWorldZBatch=ActiveShapeWorld!=nullptr
|
||||
&&ActiveShapeWorld->IsAnalyticOnly()
|
||||
&&!bUseSharedDensityGrid&&!bCapturePreEditGrid;
|
||||
const bool bUseShapeWorldXBatch=ActiveShapeWorld!=nullptr
|
||||
&&!bUseSharedDensityGrid&&!bCapturePreEditGrid;
|
||||
if (bUseVerticalCacheTraversal)
|
||||
if(bUseShapeWorldZBatch&&!bUseVerticalCacheTraversal)
|
||||
{
|
||||
for(const std::vector<int32>& YGroup:YGroups)
|
||||
for(const std::vector<int32>& XGroup:XGroups)
|
||||
for(const int32 gy:YGroup)
|
||||
for(const int32 gx:XGroup)
|
||||
{
|
||||
if(ShouldAbortWork())
|
||||
{
|
||||
if(bUseOperatorBlock){Generator->EndDensityBlock();}
|
||||
return FVoxelMeshData();
|
||||
}
|
||||
const int32 BatchCount=GzHi-GzLo+1;
|
||||
const int32 SampleX=OriginVoxels.X+gx*Step;
|
||||
const int32 SampleY=OriginVoxels.Y+gy*Step;
|
||||
float Densities[CHUNK_SIZE+3]{};
|
||||
ActiveShapeWorld->DensityAtLatticeZRun(SampleX,SampleY,
|
||||
OriginVoxels.Z+GzLo*Step,Step,BatchCount,Densities);
|
||||
for(int32 Lane=0;Lane<BatchCount;++Lane)
|
||||
{
|
||||
const int32 LocalGz=GzLo+Lane;
|
||||
const int32 LocalIndex=
|
||||
((LocalGz+1)*MDim+(gy+1))*MDim+(gx+1);
|
||||
DensityGrid[LocalIndex]=Densities[Lane];
|
||||
}
|
||||
const int32 ReachBlockX=FMath::Clamp(gx,0,CellsPerAxis-1)
|
||||
/VoxelGenLOD::TileReachBlockCells;
|
||||
const int32 ReachBlockY=FMath::Clamp(gy,0,CellsPerAxis-1)
|
||||
/VoxelGenLOD::TileReachBlockCells;
|
||||
const int32 ReachBlockZ=FMath::Clamp(GzHi,0,CellsPerAxis-1)
|
||||
/VoxelGenLOD::TileReachBlockCells;
|
||||
VoxelGenLOD::TileReachBlockIndex=
|
||||
((ReachBlockZ*ReachBlocksPerAxis)+ReachBlockY)
|
||||
*ReachBlocksPerAxis+ReachBlockX;
|
||||
if(OutDensitySampleCount)*OutDensitySampleCount+=BatchCount;
|
||||
}
|
||||
}
|
||||
else if (bUseVerticalCacheTraversal)
|
||||
{
|
||||
for (const std::vector<int32>& YGroup : YGroups)
|
||||
for (const std::vector<int32>& XGroup : XGroups)
|
||||
|
||||
Reference in new issue
Block a user