streaming: split dense passage-junction grid fills; heavy-first order + far-parent deferral in Unreal (L85)
Tiles with passage-overlap score >= 9 split grid fill over up to 4 helper lanes (disjoint rows, same per-sample order, join before MC) when workers are idle. FI junction tile fill 173 -> 99 ms; estimated serial floor ~0.55-0.60 s. Readiness essentially unchanged (FI/TN LOD0-2 ~2.15 s @W12): the limit is now aggregate work, not single tiles. Unreal: LOD0-2 ordered by passage overlap before travel/distance (L80 modes kept); far parents built after LOD0-1, LOD2 gated on them; helper budget via ParallelFor. Unreal null-RHI FI arrival: LOD0-2 resident at 3.65 s. All tile hashes identical to L84 (four whole views). Fast tier PASS; Linux UE host builds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
1 parent
0a98da6fd0
commit
06f558dc91
17 files changed
+1561
-54
No files matched your search
@@ -435,6 +435,29 @@ namespace StandaloneWorldMesher
|
||||
}
|
||||
}
|
||||
|
||||
// Grid fills can be nested inside the tile worker pool. Keep at most one such fill active so a
|
||||
// burst of passage tiles adds only a bounded helper group instead of multiplying the worker count.
|
||||
class FStandaloneGridFillScheduler final : public VoxelForgeCore::JobScheduler
|
||||
{
|
||||
public:
|
||||
explicit FStandaloneGridFillScheduler(const VoxelForgeCore::JobScheduler* InInner)
|
||||
:Inner(InInner){}
|
||||
|
||||
double parallel_for(std::size_t Count,std::size_t BatchSize,std::size_t WorkerLimit,
|
||||
void* Context,Task Callback,double* WorkerActiveSeconds,
|
||||
std::size_t WorkerActiveCapacity) const override
|
||||
{
|
||||
if(!Inner)return 0.0;
|
||||
std::lock_guard<std::mutex> Lock(Mutex);
|
||||
return Inner->parallel_for(Count,BatchSize,WorkerLimit,Context,Callback,
|
||||
WorkerActiveSeconds,WorkerActiveCapacity);
|
||||
}
|
||||
|
||||
private:
|
||||
const VoxelForgeCore::JobScheduler* Inner=nullptr;
|
||||
mutable std::mutex Mutex;
|
||||
};
|
||||
|
||||
class FStandaloneStreamingGenerator
|
||||
{
|
||||
private:
|
||||
@@ -462,10 +485,14 @@ public:
|
||||
bool bInCaptureColumnCoordinates=false,
|
||||
int32 InLod8HorizonInteriorStepVoxels=0,
|
||||
bool bInSharedColumnCache=true,
|
||||
bool bInAllowUniformSkipsWhenHashing=false)
|
||||
bool bInAllowUniformSkipsWhenHashing=false,
|
||||
const VoxelForgeCore::JobScheduler* InGridFillScheduler=nullptr)
|
||||
:World(&InWorld),WorkerCount(FMath::Clamp(InWorkerCount,1,16)),bHashDensity(bInHashDensity),
|
||||
MeshCache(InMeshCache),MaxLevelFilter(InMaxLevelFilter),
|
||||
CoreWorld(InCoreWorld),bSkipUvAndColors(bInSkipUvAndColors),bSkipMaterialGroups(bInSkipMaterialGroups),
|
||||
CoreWorld(InCoreWorld),
|
||||
GridFillScheduler(InGridFillScheduler
|
||||
?std::make_unique<FStandaloneGridFillScheduler>(InGridFillScheduler):nullptr),
|
||||
bSkipUvAndColors(bInSkipUvAndColors),bSkipMaterialGroups(bInSkipMaterialGroups),
|
||||
bSkipUV(bInSkipUV),bSkipColors(bInSkipColors),
|
||||
bCaptureColumnCoordinates(bInCaptureColumnCoordinates),
|
||||
bSharedColumnCache(bInSharedColumnCache),
|
||||
@@ -1116,6 +1143,25 @@ private:
|
||||
Options.skipMaterialGroups=bSkipMaterialGroups;Options.skipUv=bSkipUV;Options.skipColors=bSkipColors;
|
||||
Options.captureColumnCoordinates=bCaptureColumnCoordinates;
|
||||
Options.useSharedColumnCache=bSharedColumnCache;
|
||||
// Split only dense passage/mouth overlaps, and spend only worker lanes left idle by
|
||||
// the tile pool. The grid fill runs on a second pool while this tile worker waits.
|
||||
const uint32 PassageScore=PassageOverlapScore(Job.Key);
|
||||
if(GridFillScheduler&&Job.Key.Level==0&&WorkerCount>1&&PassageScore>=9)
|
||||
{
|
||||
size_t ActiveTileCount=0;
|
||||
{
|
||||
std::lock_guard<std::mutex> Lock(Mutex);
|
||||
ActiveTileCount=Running.size();
|
||||
}
|
||||
const int32 AvailableHelperLanes=std::max(0,
|
||||
12-std::max(0,static_cast<int32>(ActiveTileCount)-1));
|
||||
const int32 GridFillWorkers=std::min({4,WorkerCount,AvailableHelperLanes});
|
||||
if(GridFillWorkers>1)
|
||||
{
|
||||
Options.gridFillScheduler=GridFillScheduler.get();
|
||||
Options.gridFillWorkerLimit=static_cast<std::uint32_t>(GridFillWorkers);
|
||||
}
|
||||
}
|
||||
Options.lod8HorizonInteriorStepVoxels=Lod8HorizonInteriorStepVoxels;
|
||||
Options.profileMesherStages=(bProfileMesherStages||bInstrumentTileDrain)&&!ForceGenerate;
|
||||
Options.profilePassageComposer=bProfilePassageComposer;
|
||||
@@ -1330,7 +1376,7 @@ private:
|
||||
const char* TileClassName=D.tileClass==VoxelForgeCore::TileClass::allAir?"air":
|
||||
D.tileClass==VoxelForgeCore::TileClass::allSolid?"solid":
|
||||
D.tileClass==VoxelForgeCore::TileClass::mixed?"mixed":"unknown";
|
||||
std::printf("[CpuTileStages] key=(%d,%d,%d,lod%d) worker_id=%d worker_ms=%.3f payload_ms=%.3f tile_classified=%d tile_class=%s tile_skip=%d density_point_calls=%llu density_float_points=%llu density_lattice_points=%llu density_unclamped_points=%llu density_x8_points=%llu field_eval_sample_ns=%llu field_eval_sample_points=%llu samples=%llu classify_ms=%.3f column_ms=%.3f column_exclusive_ms=%.3f mc_ms=%.3f mc_grid_ms=%.3f mc_cell_ms=%.3f mc_gradient_ms=%.3f mc_interpolation_ms=%.3f mc_dedup_ms=%.3f mc_skirt_ms=%.3f mc_other_ms=%.3f connector_ms=%.3f ground_ms=%.3f cap_ms=%.3f horizon_ms=%.3f mesh_assembly_ms=%.3f candidate_cells=%llu classified_cells=%llu surface_cells=%llu proof_solid_cells=%llu proof_air_cells=%llu proof_density_samples=%llu zband_reject_cells=%llu x8_calls=%llu x8_active_lanes=%llu grad_calls=%llu grad_memo_hits=%llu grad_fallback_calls=%llu midpoint_attempts=%llu midpoint_memo_hits=%llu skirt_edges=%llu skirt_boundary_edges=%llu skirt_density_probes=%llu skirt_triangles=%u fi_local_hit=%llu fi_local_miss=%llu fi_local_conflicts=%llu fi_shared_hit=%llu fi_shared_miss=%llu fi_shared_computes=%llu fi_shared_conflicts=%llu fi_lock_wait_us=%.3f\n",
|
||||
std::printf("[CpuTileStages] key=(%d,%d,%d,lod%d) worker_id=%d worker_ms=%.3f payload_ms=%.3f tile_classified=%d tile_class=%s tile_skip=%d density_point_calls=%llu density_float_points=%llu density_lattice_points=%llu density_unclamped_points=%llu density_x8_points=%llu field_eval_sample_ns=%llu field_eval_sample_points=%llu samples=%llu classify_ms=%.3f column_ms=%.3f column_exclusive_ms=%.3f mc_ms=%.3f mc_grid_ms=%.3f mc_grid_workers=%u mc_cell_ms=%.3f mc_gradient_ms=%.3f mc_interpolation_ms=%.3f mc_dedup_ms=%.3f mc_skirt_ms=%.3f mc_other_ms=%.3f connector_ms=%.3f ground_ms=%.3f cap_ms=%.3f horizon_ms=%.3f mesh_assembly_ms=%.3f candidate_cells=%llu classified_cells=%llu surface_cells=%llu proof_solid_cells=%llu proof_air_cells=%llu proof_density_samples=%llu zband_reject_cells=%llu x8_calls=%llu x8_active_lanes=%llu grad_calls=%llu grad_memo_hits=%llu grad_fallback_calls=%llu midpoint_attempts=%llu midpoint_memo_hits=%llu skirt_edges=%llu skirt_boundary_edges=%llu skirt_density_probes=%llu skirt_triangles=%u fi_local_hit=%llu fi_local_miss=%llu fi_local_conflicts=%llu fi_shared_hit=%llu fi_shared_miss=%llu fi_shared_computes=%llu fi_shared_conflicts=%llu fi_lock_wait_us=%.3f\n",
|
||||
Event.Key.Coord.X,Event.Key.Coord.Y,Event.Key.Coord.Z,Event.Key.Level,
|
||||
Event.WorkerId,Event.WorkerMilliseconds,Event.PayloadBuildMilliseconds,
|
||||
D.tileWasClassified?1:0,TileClassName,D.meshingSkipped?1:0,
|
||||
@@ -1344,7 +1390,8 @@ private:
|
||||
static_cast<unsigned long long>(Event.DensitySamples),D.classificationMilliseconds,
|
||||
D.columnComputeMilliseconds,D.columnEvaluationExclusiveMilliseconds,
|
||||
D.marchingCubesExclusiveMilliseconds+D.marchingCubesSkirtMilliseconds,
|
||||
D.marchingCubesDensityGridMilliseconds,D.marchingCubesCellClassificationMilliseconds,
|
||||
D.marchingCubesDensityGridMilliseconds,D.marchingCubesGridFillWorkers,
|
||||
D.marchingCubesCellClassificationMilliseconds,
|
||||
D.marchingCubesGradientNormalsMilliseconds,D.marchingCubesEdgeInterpolationMilliseconds,
|
||||
D.marchingCubesVertexDedupStreamMilliseconds,D.marchingCubesSkirtMilliseconds,
|
||||
D.marchingCubesOtherMilliseconds,D.farConnectorShellMilliseconds,
|
||||
@@ -1441,6 +1488,7 @@ private:
|
||||
const FStandaloneMeshCache* MeshCache=nullptr;
|
||||
int32 MaxLevelFilter=-1;
|
||||
VoxelForgeCore::World* CoreWorld=nullptr;
|
||||
std::unique_ptr<FStandaloneGridFillScheduler> GridFillScheduler;
|
||||
bool bSkipUvAndColors=false;
|
||||
bool bSkipMaterialGroups=false;
|
||||
bool bSkipUV=false;
|
||||
|
||||
Reference in new issue
Block a user