wip(assembler): round S5 -- streaming gates + trace; coarse-first order kept opt-in (no win)

Walkable/enclosed/refined gates defined; JSONL trace joins request, worker start,
build/apply and discards. Coarse-first + dynamic near reserve behind
voxel.StreamingCoarseFirst / voxel.StreamingDynamicNearReserve (default 0 =
S4 order): matched runs showed no walkability or full-view win and slower
LOD0/1 refinement. Instruments settled: 3.1 s standalone reproduced (16.7 s was
another generation route); black early captures were clear-only frames.
Hashes equal S4; Core-off, M2, SurfaceWorld/FloatingIslands BuildHost pass.

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-19 04:42:41 +02:00
1 parent 9d3c50ca95
commit c0596c5f24
32 files changed
+1049 -65

No files matched your search

+79 -7
View File
@@ -9,6 +9,7 @@
#include <atomic>
#include <bit>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstring>
#include <deque>
@@ -409,6 +410,11 @@ namespace StandaloneWorldMesher
class FStandaloneStreamingGenerator
{
public:
static void SetCoarseFirstSchedulingEnabled(bool bEnabled)
{bCoarseFirstSchedulingEnabled.store(bEnabled,std::memory_order_relaxed);}
static bool IsCoarseFirstSchedulingEnabled()
{return bCoarseFirstSchedulingEnabled.load(std::memory_order_relaxed);}
explicit FStandaloneStreamingGenerator(FStandaloneOwnerWorld& InWorld,int32 InWorkerCount=8,
bool bInHashDensity=false,
const FStandaloneMeshCache* InMeshCache=nullptr,
@@ -448,6 +454,7 @@ public:
bStop=false;
}
for(int32 I=0;I<WorkerCount;++I)Workers.emplace_back([this](){WorkerLoop();});
bHasLastCameraPosition=false;TravelDirection=FVector::ZeroVector;
return UpdateDesired(CameraPositionVoxels,ResidentKeys,CrossingIndex);
}
@@ -461,6 +468,7 @@ public:
bStop=false;
}
for(int32 I=0;I<WorkerCount;++I)Workers.emplace_back([this](){WorkerLoop();});
bHasLastCameraPosition=false;TravelDirection=FVector::ZeroVector;
return UpdateDesiredSet(InitialDesired,ResidentKeys,CrossingIndex);
}
@@ -507,6 +515,23 @@ public:
const FVector& CameraPositionVoxels,const std::vector<FVoxelTileKey>& ResidentKeys,
uint64 CrossingIndex=0)
{
if(bHasLastCameraPosition)
{
const FVector Delta=CameraPositionVoxels-LastCameraPositionVoxels;
const double LengthSquared=static_cast<double>(Delta.X)*Delta.X
+static_cast<double>(Delta.Y)*Delta.Y;
if(LengthSquared>1.0e-12)
{
const double InverseLength=1.0/std::sqrt(LengthSquared);
TravelDirection=FVector(static_cast<float>(Delta.X*InverseLength),
static_cast<float>(Delta.Y*InverseLength),0.0f);
}
else TravelDirection=FVector::ZeroVector;
}
else
TravelDirection=FVector::ZeroVector;
LastCameraPositionVoxels=CameraPositionVoxels;
bHasLastCameraPosition=true;
FStandaloneDesiredTileSet NewDesired=StandaloneWorldMesher::BuildDesiredSet(*World,CameraPositionVoxels);
if(CoreWorld)
{
@@ -652,17 +677,60 @@ private:
Stats.CancelledByCrossing.reserve(CancelledByCrossing.size());
for(const auto& Pair:CancelledByCrossing)Stats.CancelledByCrossing.push_back(Pair);
std::vector<VoxelForgeCore::TileKey> Unordered;Unordered.reserve(NewDesired.Tiles.size());
for(const FVoxelTileKey& Key:NewDesired.Tiles)
Unordered.push_back({{Key.Coord.X,Key.Coord.Y,Key.Coord.Z},Key.Level});
const auto Prioritized=VoxelForgeCore::World::prioritizeTiles(Unordered,
{NewDesired.CenterChunk.X,NewDesired.CenterChunk.Y,NewDesired.CenterChunk.Z});
std::vector<FVoxelTileKey> Prioritized=NewDesired.Tiles;
if(IsCoarseFirstSchedulingEnabled())
{
// The local walkable ring leads, the coarse enclosure follows, then target-detail work.
// L'anneau praticable local passe d'abord, puis l'enveloppe grossiere, puis le detail cible.
const int32 FirstCoarseLevel=FMath::Max(2,World->FullResClipLevels);
auto Tier=[&](const FVoxelTileKey& Key)
{
if(Key.Level==0&&std::abs(Key.Coord.X-NewDesired.CenterChunk.X)<=1
&&std::abs(Key.Coord.Y-NewDesired.CenterChunk.Y)<=1
&&std::abs(Key.Coord.Z-NewDesired.CenterChunk.Z)<=1)return 0;
return Key.Level>=FirstCoarseLevel?1:2;
};
auto IsAhead=[&](const FVoxelTileKey& Key)
{
if(TravelDirection.X*TravelDirection.X+TravelDirection.Y*TravelDirection.Y<=1.0e-12f)
return false;
const double Scale=static_cast<double>(1<<Key.Level);
const double OffsetX=(static_cast<double>(Key.Coord.X)+0.5)*Scale-NewDesired.CenterChunk.X;
const double OffsetY=(static_cast<double>(Key.Coord.Y)+0.5)*Scale-NewDesired.CenterChunk.Y;
return OffsetX*TravelDirection.X+OffsetY*TravelDirection.Y>0.0;
};
std::sort(Prioritized.begin(),Prioritized.end(),[&](const FVoxelTileKey& A,const FVoxelTileKey& B)
{
const int32 TierA=Tier(A),TierB=Tier(B);
if(TierA!=TierB)return TierA<TierB;
if(TierA==1&&A.Level!=B.Level)return A.Level>B.Level;
const bool bAheadA=IsAhead(A),bAheadB=IsAhead(B);
if(bAheadA!=bAheadB)return bAheadA;
const double DA=StandaloneWorldMesher::TileDistanceSquaredChunks(A,NewDesired.CenterChunk);
const double DB=StandaloneWorldMesher::TileDistanceSquaredChunks(B,NewDesired.CenterChunk);
if(DA!=DB)return DA<DB;
if(A.Level!=B.Level)return A.Level<B.Level;
if(A.Coord.Z!=B.Coord.Z)return A.Coord.Z<B.Coord.Z;
if(A.Coord.Y!=B.Coord.Y)return A.Coord.Y<B.Coord.Y;
return A.Coord.X<B.Coord.X;
});
}
else
{
std::vector<VoxelForgeCore::TileKey> Unordered;Unordered.reserve(NewDesired.Tiles.size());
for(const FVoxelTileKey& Key:NewDesired.Tiles)
Unordered.push_back({{Key.Coord.X,Key.Coord.Y,Key.Coord.Z},Key.Level});
const auto CorePrioritized=VoxelForgeCore::World::prioritizeTiles(Unordered,
{NewDesired.CenterChunk.X,NewDesired.CenterChunk.Y,NewDesired.CenterChunk.Z});
Prioritized.clear();Prioritized.reserve(CorePrioritized.size());
for(const auto& Key:CorePrioritized)
Prioritized.emplace_back(FIntVector(Key.coordinate.x,Key.coordinate.y,Key.coordinate.z),Key.lod);
}
std::unordered_map<FVoxelTileKey,size_t,FStandaloneTileKeyHash> PriorityRanks;
PriorityRanks.reserve(Prioritized.size()*2+1);
for(size_t Rank=0;Rank<Prioritized.size();++Rank)
{
const auto& Key=Prioritized[Rank];
PriorityRanks.emplace(FVoxelTileKey(FIntVector(Key.coordinate.x,Key.coordinate.y,Key.coordinate.z),Key.lod),Rank);
PriorityRanks.emplace(Prioritized[Rank],Rank);
}
for(FStandaloneTileJob& Job:Queue)Job.PriorityRank=PriorityRanks.at(Job.Key);
@@ -884,6 +952,10 @@ private:
TimelineMilliseconds(Started),TimelineMilliseconds(Finished),WorkerMs);
}
FStandaloneOwnerWorld* World=nullptr;
inline static std::atomic<bool> bCoarseFirstSchedulingEnabled{true};
FVector LastCameraPositionVoxels=FVector::ZeroVector;
FVector TravelDirection=FVector::ZeroVector;
bool bHasLastCameraPosition=false;
int32 WorkerCount=8;
bool bHashDensity=false;
const FStandaloneMeshCache* MeshCache=nullptr;