unreal: parallel sign-edge repair + cheap SW route prefilter (L94); SW startup 2.75 -> 0.43 s
- Unreal requests Core's deterministic parallel sign-edge repair (UE ParallelFor, capped at 10 workers); headless defaults to parallel (--serial-sign-edge-repair for A/B). SW sign_edge_distances 1,942 -> 37 ms, ShapeStage 2,156 -> 198 ms. - SW fallback route planner checks the exact mouth-radius endpoint constraints before sampling terrain (58,480 of 78,408 candidates skip heightfield work); same 35 eligible, same chosen route. SerializeResolvedWorld 468 -> 115 ms; BeginPlay block 0.58 -> 0.22 s. - Unreal SW: first admission 2.75 -> 0.43 s, LOD0-2 settled 5.20 -> 2.81 s; FI 3.40 -> 3.12 s. - World identical: assembly/recipe/plan hashes unchanged; serial vs parallel per-tile hashes equal. 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
1e111cc042
commit
35f0a67fe3
5 files changed
+273
-37
No files matched your search
@@ -470,12 +470,61 @@ bool BuildFiniteSurfaceRoute(VoxelForgeCore::WorldAssemblyRecipeV1& Recipe,
|
||||
Candidate.CenterY = CenterY;
|
||||
Candidate.Direction = DirectionIndex;
|
||||
Candidate.HalfLength = HalfLength;
|
||||
const auto EndpointCoordinates = [&](std::int32_t Index)
|
||||
{
|
||||
const std::int64_t Along = (Index - 16) * HalfLength / 16;
|
||||
return std::array<std::int64_t, 2>{
|
||||
CenterX + WorldAssemblyRoundRatio(
|
||||
Along * Directions[DirectionIndex].X, 65536),
|
||||
CenterY + WorldAssemblyRoundRatio(
|
||||
Along * Directions[DirectionIndex].Y, 65536)};
|
||||
};
|
||||
const auto ArrivalEndpoint = EndpointCoordinates(0);
|
||||
const auto DepartureEndpoint = EndpointCoordinates(32);
|
||||
const std::int64_t ArrivalXQ = WorldAssemblyFixed(
|
||||
static_cast<double>(ArrivalEndpoint[0]));
|
||||
const std::int64_t ArrivalYQ = WorldAssemblyFixed(
|
||||
static_cast<double>(ArrivalEndpoint[1]));
|
||||
const std::int64_t DepartureXQ = WorldAssemblyFixed(
|
||||
static_cast<double>(DepartureEndpoint[0]));
|
||||
const std::int64_t DepartureYQ = WorldAssemblyFixed(
|
||||
static_cast<double>(DepartureEndpoint[1]));
|
||||
const auto InRadius = [](std::int64_t XValue, std::int64_t YValue,
|
||||
std::int64_t Radius)
|
||||
{
|
||||
return Radius <= 0 || XValue * XValue + YValue * YValue <= Radius * Radius;
|
||||
};
|
||||
if ((ArrivalRadiusQ > 0
|
||||
&& !InRadius(ArrivalXQ, ArrivalYQ, ArrivalRadiusQ))
|
||||
|| (DepartureRadiusQ > 0
|
||||
&& !InRadius(DepartureXQ, DepartureYQ, DepartureRadiusQ)))
|
||||
{
|
||||
// Mouth placement is independent of terrain, so reject it before
|
||||
// allocating points or sampling the heightfield for grade.
|
||||
++FallbackPlacementRejected;
|
||||
continue;
|
||||
}
|
||||
Candidate.Points.reserve(33);
|
||||
if (ArrivalRadiusQ > 0)
|
||||
{
|
||||
Candidate.EndpointProximityCost += static_cast<std::uint64_t>(
|
||||
ArrivalXQ * ArrivalXQ + ArrivalYQ * ArrivalYQ) * 16ull;
|
||||
}
|
||||
if (DepartureRadiusQ > 0)
|
||||
{
|
||||
Candidate.EndpointProximityCost += static_cast<std::uint64_t>(
|
||||
DepartureXQ * DepartureXQ + DepartureYQ * DepartureYQ);
|
||||
// Approach the surface portal from the world-facing side. The
|
||||
// resolved passage leaves the mouth along its outward tangent;
|
||||
// a route that approaches from beyond the mouth overlaps that
|
||||
// bore and turns its centerline into solid ground.
|
||||
Candidate.OutwardProjection = DepartureXQ * Directions[DirectionIndex].X
|
||||
+ DepartureYQ * Directions[DirectionIndex].Y;
|
||||
}
|
||||
std::int64_t PreviousGround = 0;
|
||||
std::int64_t PreviousX = 0;
|
||||
std::int64_t PreviousY = 0;
|
||||
bool bGradePass = true;
|
||||
bool bPlacementPass = true;
|
||||
for (std::int32_t Index = 0; Index <= 32; ++Index)
|
||||
{
|
||||
const std::int64_t Along = (Index - 16) * HalfLength / 16;
|
||||
@@ -485,33 +534,6 @@ bool BuildFiniteSurfaceRoute(VoxelForgeCore::WorldAssemblyRecipeV1& Recipe,
|
||||
Along * Directions[DirectionIndex].Y, 65536);
|
||||
const std::int64_t XQ = WorldAssemblyFixed(static_cast<double>(X));
|
||||
const std::int64_t YQ = WorldAssemblyFixed(static_cast<double>(Y));
|
||||
const auto InRadius = [](std::int64_t XValue, std::int64_t YValue,
|
||||
std::int64_t Radius)
|
||||
{
|
||||
return Radius <= 0 || XValue * XValue + YValue * YValue <= Radius * Radius;
|
||||
};
|
||||
if ((Index == 0 && ArrivalRadiusQ > 0
|
||||
&& !InRadius(XQ, YQ, ArrivalRadiusQ))
|
||||
|| (Index == 32 && DepartureRadiusQ > 0
|
||||
&& !InRadius(XQ, YQ, DepartureRadiusQ)))
|
||||
{
|
||||
bPlacementPass = false;
|
||||
}
|
||||
if (Index == 0 && ArrivalRadiusQ > 0)
|
||||
{
|
||||
Candidate.EndpointProximityCost += static_cast<std::uint64_t>(XQ * XQ + YQ * YQ) * 16ull;
|
||||
}
|
||||
if (Index == 32 && DepartureRadiusQ > 0)
|
||||
{
|
||||
Candidate.EndpointProximityCost += static_cast<std::uint64_t>(XQ * XQ + YQ * YQ);
|
||||
// Approach the surface portal from the world-facing side. The
|
||||
// resolved passage leaves the mouth along its outward tangent;
|
||||
// a route that approaches from beyond the mouth overlaps that
|
||||
// bore and turns its centerline into solid ground.
|
||||
const std::int64_t OutwardProjection = XQ * Directions[DirectionIndex].X
|
||||
+ YQ * Directions[DirectionIndex].Y;
|
||||
Candidate.OutwardProjection = OutwardProjection;
|
||||
}
|
||||
const auto Column = BaseField.point(WorldAssemblyFixed(static_cast<double>(X)),
|
||||
WorldAssemblyFixed(static_cast<double>(Y)), 0);
|
||||
const std::int64_t DeltaX = X - PreviousX;
|
||||
@@ -557,11 +579,10 @@ bool BuildFiniteSurfaceRoute(VoxelForgeCore::WorldAssemblyRecipeV1& Recipe,
|
||||
BestGradeCandidate.HalfLength = HalfLength;
|
||||
}
|
||||
}
|
||||
if (bGradePass && bPlacementPass) Candidates.push_back(std::move(Candidate));
|
||||
if (bGradePass) Candidates.push_back(std::move(Candidate));
|
||||
else
|
||||
{
|
||||
if (!bGradePass) ++FallbackGradeRejected;
|
||||
if (!bPlacementPass) ++FallbackPlacementRejected;
|
||||
++FallbackGradeRejected;
|
||||
}
|
||||
}
|
||||
UE_LOG(LogTemp, Display,
|
||||
|
||||
@@ -7812,6 +7812,7 @@ bool AVoxelWorld::InitializeVoxelForgeCoreWorld(FString& OutFailureReason)
|
||||
Request.workerLimit = static_cast<std::uint32_t>(FMath::Clamp(GetMaxConcurrentTasks(), 1, 16));
|
||||
Request.detail = VoxelForgeCore::DetailVariant::coherent;
|
||||
Request.includeFarWorld = false;
|
||||
Request.parallelSignEdgeRepair = true;
|
||||
|
||||
VoxelForgeCoreState = State;
|
||||
State->bSnapshotReady.store(true, std::memory_order_release);
|
||||
|
||||
Reference in new issue
Block a user