wip(assembler): round L11 -- fix 24 m+ crossing crash; near ring ready 2x sooner at spawn
Crash: crossing tiles were coalesced into one huge rectangle, and BuildSpatialBins tried to resize to ~4.3e17 bytes (std::bad_alloc; the L7 32 m failure had the same cause). Analytic regions now skip unread dense bins and compile in world-aligned 128-voxel pages, published together; out-of-range keys error before allocation. 24 m, 32 m and 1 km crossings pass (1 km: 72 pages, peak RSS 700 MiB). Spawn: World::isTileShapeFree proves LOD0 SurfaceWorld tiles that never read the cave shape; those start before shape compile, and all others wait. Reviewer W12 no-hash: near ring 0.337 -> 0.159 s, whole view +2.1%. All SurfaceWorld/FloatingIslands hashes unchanged (W1/W8/W12, both compilers, forced-overlap run). Unreal VoxelWorld.cpp adapter changed but NOT built here. 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
b370908174
commit
b1cfaf53b8
8 files changed
+808
-59
No files matched your search
@@ -146,6 +146,10 @@ public:
|
||||
FVoxelForgeCoreTaskScheduler Scheduler;
|
||||
std::unordered_set<VoxelForgeCore::TileKey, VoxelForgeCore::TileKeyHash> RetainedTiles;
|
||||
FCriticalSection RetainedTilesLock;
|
||||
FCriticalSection ShapeReadinessLock;
|
||||
std::unordered_set<VoxelForgeCore::TileKey, VoxelForgeCore::TileKeyHash> ShapeFreeTiles;
|
||||
std::unordered_set<VoxelForgeCore::TileKey, VoxelForgeCore::TileKeyHash> ShapeDependentTiles;
|
||||
std::atomic<bool> bSnapshotReady{false};
|
||||
std::atomic<bool> bReady{false};
|
||||
std::atomic<bool> bInitialFailed{false};
|
||||
std::atomic<bool> bRegionCompileInFlight{false};
|
||||
@@ -7689,6 +7693,7 @@ bool AVoxelWorld::InitializeVoxelForgeCoreWorld(FString& OutFailureReason)
|
||||
Request.includeFarWorld = true;
|
||||
|
||||
VoxelForgeCoreState = State;
|
||||
State->bSnapshotReady.store(true, std::memory_order_release);
|
||||
ActiveTaskCount.fetch_add(1, std::memory_order_relaxed);
|
||||
UE::Tasks::Launch(TEXT("VoxelForgeCoreCompile"),
|
||||
[this, State, Request, InitialDesired, ActiveCoreClipRadius, ActiveCoreMaxClipLevel,
|
||||
@@ -7708,10 +7713,17 @@ bool AVoxelWorld::InitializeVoxelForgeCoreWorld(FString& OutFailureReason)
|
||||
|
||||
std::string Error;
|
||||
bool bCompiled = false;
|
||||
bCompiled = State->World->compile(Request, State->Scheduler, Error);
|
||||
if (bCompiled)
|
||||
{
|
||||
// The initial compile builds into local state and atomically publishes an immutable
|
||||
// shape. Proven native-only tiles may hold shared WorldLock readers during this work;
|
||||
// take the writer only for region retention after publication.
|
||||
// La compilation initiale construit un etat local puis publie une forme immuable.
|
||||
// Les tuiles natives validees gardent le verrou lecteur partage; le verrou ecrivain
|
||||
// ne sert qu'a retenir les regions apres publication.
|
||||
FWriteScopeLock Lock(State->WorldLock);
|
||||
bCompiled = State->World->compile(Request, State->Scheduler, Error);
|
||||
if (bCompiled)
|
||||
if (State->World)
|
||||
{
|
||||
State->World->retainTileRegions(InitialDesired);
|
||||
FScopeLock RetainedLock(&State->RetainedTilesLock);
|
||||
@@ -13019,9 +13031,33 @@ void AVoxelWorld::LoadCoreTile(const FVoxelTileKey& Tile, EVoxelTileWorkPriority
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (PendingTiles.Contains(Tile) || !IsVoxelForgeCoreReady()) return;
|
||||
if (PendingTiles.Contains(Tile)) return;
|
||||
const TSharedPtr<FVoxelForgeCoreRuntimeState, ESPMode::ThreadSafe> State = VoxelForgeCoreState;
|
||||
if (!State.IsValid() || State->bRegionCompileFailed.load(std::memory_order_acquire)) return;
|
||||
if (!State.IsValid()||State->bInitialFailed.load(std::memory_order_acquire)
|
||||
||State->bRegionCompileFailed.load(std::memory_order_acquire)
|
||||
||State->bShuttingDown.load(std::memory_order_acquire))return;
|
||||
const bool bShapeReady=State->bReady.load(std::memory_order_acquire);
|
||||
if(!bShapeReady)
|
||||
{
|
||||
if(!State->bSnapshotReady.load(std::memory_order_acquire))return;
|
||||
const VoxelForgeCore::TileKey CoreKey{
|
||||
{Tile.Coord.X,Tile.Coord.Y,Tile.Coord.Z},Tile.Level};
|
||||
bool bShapeFree=false;
|
||||
{
|
||||
FScopeLock ReadinessLock(&State->ShapeReadinessLock);
|
||||
if(State->ShapeFreeTiles.contains(CoreKey))bShapeFree=true;
|
||||
else if(State->ShapeDependentTiles.contains(CoreKey))return;
|
||||
else
|
||||
{
|
||||
FReadScopeLock WorldReadLock(State->WorldLock);
|
||||
if(!State->World)return;
|
||||
bShapeFree=State->World->isTileShapeFree(CoreKey);
|
||||
if(bShapeFree)State->ShapeFreeTiles.insert(CoreKey);
|
||||
else State->ShapeDependentTiles.insert(CoreKey);
|
||||
}
|
||||
}
|
||||
if(!bShapeFree)return;
|
||||
}
|
||||
if (IsStreamingResultBacklogCapped())
|
||||
{
|
||||
StreamingResultBacklogCapStops.fetch_add(1, std::memory_order_relaxed);
|
||||
|
||||
Reference in new issue
Block a user