passages: memoized exact MC midpoints + wider conservative sweep bounds (L101, exact vs L100)
Off-grid census by caller (MC midpoints, skirts, far shells); all 63.0M sweep misses accounted (1.9M exact-route fallbacks, 61.1M counted bound skips). Exact MC midpoint queries memoized by float bits (Unreal enables it too); feature bounds expanded. L100/L101 whole-view hashes equal in all four strata (v216 unchanged); 0 added/removed crossings; 15 capture pairs pixel-identical. Near-ready @W12 L100 -> L101: FI 1.77 -> 1.65, TN 1.66 -> 1.54, SW 0.85 -> 0.84, VS 1.03 -> 1.03 s (L98 2.28/2.23/1.02/1.11). Fast tier PASS; Linux UE host builds. Unreal arrival traces not obtained (the runner wrongly applied the 6 GiB address-space cap to Unreal). 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
2d5822cdf7
commit
55e20f4a7e
48 files changed
+2087
-38
No files matched your search
@@ -177,6 +177,13 @@ namespace VoxelForgeCore
|
||||
std::uint64_t passageSweepBaseInfluenceHits = 0;
|
||||
std::uint64_t passageSweepOutOfInfluenceHits = 0;
|
||||
std::uint64_t passageSweepMissingSamples = 0;
|
||||
std::array<std::uint64_t,12> passageSweepMissingLookupsByCaller{};
|
||||
std::array<std::uint64_t,12> passageSweepExactRouteFallbacksByCaller{};
|
||||
std::array<std::uint64_t,12> passageSweepFeatureBoundSkipsByCaller{};
|
||||
std::array<std::uint64_t,12> passageSweepTileFreeSkipsByCaller{};
|
||||
std::array<std::uint64_t,12> passageSweepVerticalBoundSkipsByCaller{};
|
||||
std::array<std::uint64_t,12> passageSweepNegativeReachSkipsByCaller{};
|
||||
std::array<std::uint64_t,12> passageSweepPositiveReachSkipsByCaller{};
|
||||
std::uint64_t floatFieldCalls = 0;
|
||||
std::uint64_t latticeFieldCalls = 0;
|
||||
std::uint64_t unclampedFieldCalls = 0;
|
||||
@@ -184,6 +191,9 @@ namespace VoxelForgeCore
|
||||
std::uint64_t densityFloatPointCalls = 0;
|
||||
std::uint64_t densityLatticePointCalls = 0;
|
||||
std::uint64_t densityUnclampedPointCalls = 0;
|
||||
std::array<std::uint64_t,12> densityOffGridFloatByCaller{};
|
||||
std::array<std::uint64_t,12> densityOffGridUnclampedByCaller{};
|
||||
std::array<std::uint64_t,12> densityOffGridDetailByCaller{};
|
||||
std::uint64_t densityX8PointCalls = 0;
|
||||
std::uint64_t densityFieldEvalNanoseconds = 0;
|
||||
std::uint64_t densityFieldEvalSamplePoints = 0;
|
||||
@@ -254,6 +264,8 @@ namespace VoxelForgeCore
|
||||
std::uint64_t marchingCubesSkirtEdgeCandidates = 0;
|
||||
std::uint64_t marchingCubesSkirtBoundaryCandidates = 0;
|
||||
std::uint64_t marchingCubesSkirtDensityProbes = 0;
|
||||
std::array<std::uint64_t,5> marchingCubesSkirtDensityProbesByCaller{};
|
||||
std::array<std::uint64_t,5> marchingCubesSkirtDensityOffGridProbesByCaller{};
|
||||
double groundRefinementExclusiveMilliseconds = 0.0;
|
||||
double capRefinementExclusiveMilliseconds = 0.0;
|
||||
double meshAssemblyMilliseconds = 0.0;
|
||||
@@ -1837,7 +1849,7 @@ namespace VoxelForgeCore
|
||||
bool instrumentTileDrain = false;
|
||||
// Linux headless measurement only. Compiled out of ordinary builds.
|
||||
bool linux77Profile = false;
|
||||
bool exactMidpointDensityMemo = false;
|
||||
bool exactMidpointDensityMemo = true;
|
||||
bool activeLaneBatching = false;
|
||||
std::uint32_t proofBlockCells = 8;
|
||||
// Diagnostic only; fills and checks every lattice sample in blocks certified uniform.
|
||||
|
||||
@@ -154,6 +154,8 @@ inline bool ContainsFarTilePoint(const FVoxelTileKey& Key,const FVector& P)
|
||||
inline bool FindFarConnectorSurfaceRadius(const FStandaloneShapeWorld& Shape,const FVector& Center,
|
||||
const FVector& Direction,double PreferredRadius,double& OutRadius)
|
||||
{
|
||||
FStandaloneShapeWorld::FScopedPassageDensityQueryCaller queryCaller(
|
||||
EPassageDensityQueryCaller::FarShellSurfaceQuery);
|
||||
const double SearchLength=PreferredRadius*2.0+32.0;
|
||||
const double AcceptBand=std::max(16.0,PreferredRadius*0.75);
|
||||
constexpr double Stride=8.0;
|
||||
@@ -227,6 +229,8 @@ inline bool FindFarConnectorSurfaceRadius(const FStandaloneShapeWorld& Shape,con
|
||||
inline bool FindFarConnectorRadiusNearNominal(const FStandaloneShapeWorld& Shape,const FVector& Center,
|
||||
const FVector& Direction,double NominalRadius,double& OutRadius,double& OutUncertainty)
|
||||
{
|
||||
FStandaloneShapeWorld::FScopedPassageDensityQueryCaller queryCaller(
|
||||
EPassageDensityQueryCaller::FarShellSurfaceQuery);
|
||||
const double MatchTolerance=std::max(8.0,NominalRadius*0.35);
|
||||
const double HalfWidth=std::min(16.0,MatchTolerance*0.75);
|
||||
const double Lo=std::max(0.0,NominalRadius-HalfWidth),Hi=NominalRadius+HalfWidth;
|
||||
@@ -245,6 +249,8 @@ inline void AppendFarConnectorShells(const FStandaloneShapeWorld& Shape,const FV
|
||||
int32 Step,int32 Cells,FVoxelMeshData& Mesh)
|
||||
{
|
||||
if(Key.Level<6||Step<=0)return;
|
||||
FStandaloneShapeWorld::FScopedPassageDensityQueryCaller queryCaller(
|
||||
EPassageDensityQueryCaller::FarShellProjectionNormal);
|
||||
// Four axial panels are the coarsest cross-section the survival audit samples.
|
||||
constexpr int32 SideCount=4;
|
||||
const FIntVector TileOrigin=Key.OriginVoxels();
|
||||
@@ -963,6 +969,8 @@ private:
|
||||
inline std::vector<double> FindFarStratumCrossings(const FStandaloneShapeWorld& Shape,
|
||||
double X,double Y,double ZMin,double ZMax)
|
||||
{
|
||||
FStandaloneShapeWorld::FScopedPassageDensityQueryCaller queryCaller(
|
||||
EPassageDensityQueryCaller::FarShellSurfaceQuery);
|
||||
std::vector<double> Crossings;
|
||||
if(ZMax<=ZMin)return Crossings;
|
||||
double PreviousZ=ZMin;
|
||||
@@ -990,6 +998,8 @@ inline std::vector<double> FindFarStratumCrossings(const FStandaloneShapeWorld&
|
||||
inline bool FindNearestFarStratumCrossing(const FStandaloneShapeWorld& Shape,
|
||||
double X,double Y,double ZMin,double ZMax,double Prediction,double& OutCrossing)
|
||||
{
|
||||
FStandaloneShapeWorld::FScopedPassageDensityQueryCaller queryCaller(
|
||||
EPassageDensityQueryCaller::FarShellSurfaceQuery);
|
||||
if(ZMax<=ZMin||!std::isfinite(Prediction))return false;
|
||||
const int32 Center=std::clamp(static_cast<int32>(std::floor(Prediction)),
|
||||
static_cast<int32>(std::ceil(ZMin)),static_cast<int32>(std::floor(ZMax)));
|
||||
@@ -1052,6 +1062,8 @@ inline void AppendFarStratumShells(const FStandaloneOwnerWorld& World,const FSta
|
||||
const FVoxelTileKey& Key,int32 Step,FVoxelMeshData& Mesh)
|
||||
{
|
||||
if(Key.Level<7||Step<4||!World.Manager)return;
|
||||
FStandaloneShapeWorld::FScopedPassageDensityQueryCaller queryCaller(
|
||||
EPassageDensityQueryCaller::FarShellStratumRefinement);
|
||||
struct FBoundary { double Z=0.0,HalfWidth=8.0; };
|
||||
const auto& Layout=World.Manager->GetLayout();
|
||||
std::vector<FBoundary> Boundaries;
|
||||
@@ -1296,6 +1308,8 @@ inline int32 RemoveCoarseTransitionFaceTriangles(FVoxelMeshData& Mesh,
|
||||
inline void AppendStratumBoundaryCeilings(const FStandaloneOwnerWorld& World,
|
||||
const FStandaloneShapeWorld& Shape,const FVoxelTileKey& Key,int32 Step,FVoxelMeshData& Mesh)
|
||||
{
|
||||
FStandaloneShapeWorld::FScopedPassageDensityQueryCaller queryCaller(
|
||||
EPassageDensityQueryCaller::FarShellStratumRefinement);
|
||||
if(Key.Level<0||Step<=0||!World.Manager)return;
|
||||
const FIntVector Origin=Key.OriginVoxels();
|
||||
const int32 Extent=Key.ExtentVoxels();
|
||||
@@ -1496,6 +1510,8 @@ inline void AppendStratumBoundaryCeilings(const FStandaloneOwnerWorld& World,
|
||||
inline void AppendStratumBoundaryFloors(const FStandaloneOwnerWorld& World,
|
||||
const FStandaloneShapeWorld& Shape,const FVoxelTileKey& Key,int32 Step,FVoxelMeshData& Mesh)
|
||||
{
|
||||
FStandaloneShapeWorld::FScopedPassageDensityQueryCaller queryCaller(
|
||||
EPassageDensityQueryCaller::FarShellStratumRefinement);
|
||||
if(Key.Level<0||Step<=0||!World.Manager||!Shape.ResolvedLayout)return;
|
||||
const FIntVector Origin=Key.OriginVoxels();
|
||||
const int32 Extent=Key.ExtentVoxels();
|
||||
|
||||
@@ -105,12 +105,46 @@ static double VF_L93PassageCarveReachMetres()
|
||||
return 4.0;
|
||||
}
|
||||
|
||||
enum class EPassageDensityQueryCaller : std::size_t
|
||||
{
|
||||
Unknown,
|
||||
DensityGrid,
|
||||
GradientNormalFallback,
|
||||
MidpointCorrection,
|
||||
SkirtSurfaceVertex,
|
||||
SkirtExtrudedVertex,
|
||||
SkirtClippedVertex,
|
||||
SkirtRefinementFace,
|
||||
SkirtCoarseCentroid,
|
||||
FarShellSurfaceQuery,
|
||||
FarShellProjectionNormal,
|
||||
FarShellStratumRefinement,
|
||||
Count
|
||||
};
|
||||
inline constexpr std::size_t PassageDensityQueryCallerCount=
|
||||
static_cast<std::size_t>(EPassageDensityQueryCaller::Count);
|
||||
|
||||
// Standalone-only world compiler. It compiles the runtime room/tunnel/passages into
|
||||
// axis-line intervals, composes rock/cave signs into packed Z-column words, then displaces
|
||||
// only the conservative surface band. The copied Unreal generator remains the A/B reference.
|
||||
class FStandaloneShapeWorld
|
||||
{
|
||||
public:
|
||||
static EPassageDensityQueryCaller& CurrentPassageDensityQueryCaller() noexcept
|
||||
{
|
||||
static thread_local EPassageDensityQueryCaller Caller=
|
||||
EPassageDensityQueryCaller::Unknown;
|
||||
return Caller;
|
||||
}
|
||||
struct FScopedPassageDensityQueryCaller
|
||||
{
|
||||
explicit FScopedPassageDensityQueryCaller(EPassageDensityQueryCaller Caller)
|
||||
:Previous(CurrentPassageDensityQueryCaller())
|
||||
{CurrentPassageDensityQueryCaller()=Caller;}
|
||||
~FScopedPassageDensityQueryCaller()
|
||||
{CurrentPassageDensityQueryCaller()=Previous;}
|
||||
EPassageDensityQueryCaller Previous;
|
||||
};
|
||||
const VoxelForgeCore::ResolvedLayoutSnapshotV3* ResolvedLayout=nullptr;
|
||||
struct FResolvedStratumBounds
|
||||
{
|
||||
@@ -299,6 +333,11 @@ public:
|
||||
std::vector<FPassageSamples> passages;
|
||||
std::atomic<std::uint64_t> lookups{0},cacheHits{0},baseInfluenceHits{0},
|
||||
outOfInfluenceHits{0},missingSamples{0};
|
||||
std::array<std::atomic<std::uint64_t>,PassageDensityQueryCallerCount>
|
||||
missingLookupsByCaller{},exactRouteFallbacksByCaller{},
|
||||
featureBoundSkipsByCaller{},tileFreeSkipsByCaller{},
|
||||
verticalBoundSkipsByCaller{},negativeReachSkipsByCaller{},
|
||||
positiveReachSkipsByCaller{};
|
||||
};
|
||||
FScopedPassageTileQueries(const FStandaloneShapeWorld& shape,
|
||||
const std::array<std::int64_t,3>& minimumSubvoxels,
|
||||
@@ -397,10 +436,12 @@ public:
|
||||
&&feature.segmentIndex<shape.PassageSegmentData[
|
||||
feature.passageIndex].size())
|
||||
{
|
||||
const auto& segment=shape.PassageSegmentData[feature.passageIndex][
|
||||
feature.segmentIndex];
|
||||
candidate.sweepMinimumSubvoxels=segment.sweepMinimumSubvoxels;
|
||||
candidate.sweepMaximumSubvoxels=segment.sweepMaximumSubvoxels;
|
||||
// Cover the full conservative route feature box when preparing
|
||||
// the lattice sweep. The wider exact samples avoid rescanning the
|
||||
// direct route for in-bound bridge/tread/clearance points; the
|
||||
// existing carve-reach check still rejects out-of-influence values.
|
||||
candidate.sweepMinimumSubvoxels=featureBounds.minimumSubvoxels;
|
||||
candidate.sweepMaximumSubvoxels=featureBounds.maximumSubvoxels;
|
||||
}
|
||||
if(feature.bColumn)passageColumns_[feature.passageIndex]=1;
|
||||
else if(feature.bMouthSupport)
|
||||
@@ -480,6 +521,30 @@ public:
|
||||
passageSweepData_->outOfInfluenceHits.load(std::memory_order_relaxed);
|
||||
profileStats_->passageSweepMissingSamples=passageSweepData_->missingSamples.load(
|
||||
std::memory_order_relaxed);
|
||||
for(std::size_t caller=0;caller<PassageDensityQueryCallerCount;++caller)
|
||||
{
|
||||
profileStats_->passageSweepMissingLookupsByCaller[caller]=
|
||||
passageSweepData_->missingLookupsByCaller[caller].load(
|
||||
std::memory_order_relaxed);
|
||||
profileStats_->passageSweepExactRouteFallbacksByCaller[caller]=
|
||||
passageSweepData_->exactRouteFallbacksByCaller[caller].load(
|
||||
std::memory_order_relaxed);
|
||||
profileStats_->passageSweepFeatureBoundSkipsByCaller[caller]=
|
||||
passageSweepData_->featureBoundSkipsByCaller[caller].load(
|
||||
std::memory_order_relaxed);
|
||||
profileStats_->passageSweepTileFreeSkipsByCaller[caller]=
|
||||
passageSweepData_->tileFreeSkipsByCaller[caller].load(
|
||||
std::memory_order_relaxed);
|
||||
profileStats_->passageSweepVerticalBoundSkipsByCaller[caller]=
|
||||
passageSweepData_->verticalBoundSkipsByCaller[caller].load(
|
||||
std::memory_order_relaxed);
|
||||
profileStats_->passageSweepNegativeReachSkipsByCaller[caller]=
|
||||
passageSweepData_->negativeReachSkipsByCaller[caller].load(
|
||||
std::memory_order_relaxed);
|
||||
profileStats_->passageSweepPositiveReachSkipsByCaller[caller]=
|
||||
passageSweepData_->positiveReachSkipsByCaller[caller].load(
|
||||
std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
if(ownsReuseCounters_&&reuseCounters_)
|
||||
std::printf("[L98PassageReuseTile] lod=%d projection_columns=%llu projection_computes=%llu projection_hits=%llu floor_profile_reads=%llu carve_prepared=%llu support_prepared=%llu capsule_prepared=%llu mouth_prepared=%llu\n",
|
||||
@@ -558,6 +623,7 @@ public:
|
||||
FScopedPassageTileQueries& operator=(const FScopedPassageTileQueries&)=delete;
|
||||
|
||||
bool matches(const FStandaloneShapeWorld& shape) const{return shape_==&shape;}
|
||||
bool capturesCallerDiagnostics() const noexcept{return profileStats_!=nullptr;}
|
||||
void prepareSweptTubeBase(const FIntVector& origin,std::int32_t step,
|
||||
std::int32_t cells,std::uint32_t seed);
|
||||
const FPassageSweepSample* sweptSample(std::size_t passageIndex,
|
||||
@@ -576,6 +642,72 @@ public:
|
||||
passageSweepData_->outOfInfluenceHits.load(std::memory_order_relaxed);
|
||||
profileStats_->passageSweepMissingSamples=passageSweepData_->missingSamples.load(
|
||||
std::memory_order_relaxed);
|
||||
for(std::size_t caller=0;caller<PassageDensityQueryCallerCount;++caller)
|
||||
{
|
||||
profileStats_->passageSweepMissingLookupsByCaller[caller]=
|
||||
passageSweepData_->missingLookupsByCaller[caller].load(
|
||||
std::memory_order_relaxed);
|
||||
profileStats_->passageSweepExactRouteFallbacksByCaller[caller]=
|
||||
passageSweepData_->exactRouteFallbacksByCaller[caller].load(
|
||||
std::memory_order_relaxed);
|
||||
profileStats_->passageSweepFeatureBoundSkipsByCaller[caller]=
|
||||
passageSweepData_->featureBoundSkipsByCaller[caller].load(
|
||||
std::memory_order_relaxed);
|
||||
profileStats_->passageSweepTileFreeSkipsByCaller[caller]=
|
||||
passageSweepData_->tileFreeSkipsByCaller[caller].load(
|
||||
std::memory_order_relaxed);
|
||||
profileStats_->passageSweepVerticalBoundSkipsByCaller[caller]=
|
||||
passageSweepData_->verticalBoundSkipsByCaller[caller].load(
|
||||
std::memory_order_relaxed);
|
||||
profileStats_->passageSweepNegativeReachSkipsByCaller[caller]=
|
||||
passageSweepData_->negativeReachSkipsByCaller[caller].load(
|
||||
std::memory_order_relaxed);
|
||||
profileStats_->passageSweepPositiveReachSkipsByCaller[caller]=
|
||||
passageSweepData_->positiveReachSkipsByCaller[caller].load(
|
||||
std::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
void recordExactRouteFallback() const noexcept
|
||||
{
|
||||
if(!profileStats_||!passageSweepData_)return;
|
||||
const auto caller=static_cast<std::size_t>(
|
||||
FStandaloneShapeWorld::CurrentPassageDensityQueryCaller());
|
||||
if(caller<PassageDensityQueryCallerCount)
|
||||
passageSweepData_->exactRouteFallbacksByCaller[caller].fetch_add(
|
||||
1,std::memory_order_relaxed);
|
||||
}
|
||||
void recordFeatureBoundSkip() const noexcept
|
||||
{
|
||||
if(!profileStats_||!passageSweepData_)return;
|
||||
const auto caller=static_cast<std::size_t>(
|
||||
FStandaloneShapeWorld::CurrentPassageDensityQueryCaller());
|
||||
if(caller<PassageDensityQueryCallerCount)
|
||||
passageSweepData_->featureBoundSkipsByCaller[caller].fetch_add(
|
||||
1,std::memory_order_relaxed);
|
||||
}
|
||||
enum class ESweepMissSkipReason : std::uint8_t
|
||||
{
|
||||
TileFree,VerticalBound,NegativeReach,PositiveReach
|
||||
};
|
||||
void recordSweepMissSkip(ESweepMissSkipReason reason) const noexcept
|
||||
{
|
||||
if(!profileStats_||!passageSweepData_)return;
|
||||
const auto caller=static_cast<std::size_t>(
|
||||
FStandaloneShapeWorld::CurrentPassageDensityQueryCaller());
|
||||
if(caller>=PassageDensityQueryCallerCount)return;
|
||||
std::atomic<std::uint64_t>* counts=nullptr;
|
||||
switch(reason)
|
||||
{
|
||||
case ESweepMissSkipReason::TileFree:
|
||||
counts=&passageSweepData_->tileFreeSkipsByCaller[caller];break;
|
||||
case ESweepMissSkipReason::VerticalBound:
|
||||
counts=&passageSweepData_->verticalBoundSkipsByCaller[caller];break;
|
||||
case ESweepMissSkipReason::NegativeReach:
|
||||
counts=&passageSweepData_->negativeReachSkipsByCaller[caller];break;
|
||||
case ESweepMissSkipReason::PositiveReach:
|
||||
counts=&passageSweepData_->positiveReachSkipsByCaller[caller];break;
|
||||
}
|
||||
if(counts)counts->fetch_add(1,std::memory_order_relaxed);
|
||||
}
|
||||
bool beginProjectionColumn() const
|
||||
{
|
||||
@@ -1945,25 +2077,34 @@ public:
|
||||
const bool usePreparedPassageSweep=preparedSweepSample!=nullptr;
|
||||
// Candidate route bounds include the carve reach, tread/clearance extents,
|
||||
// and conservative padding. A missing lattice sample outside every route
|
||||
// bound cannot affect this query; keep direct evaluation for all in-bound
|
||||
// misses and for the separate column and mouth-support paths.
|
||||
// bound cannot affect this query, even when another segment or column in
|
||||
// this tile overlaps elsewhere. Column composition above and mouth-support
|
||||
// paths below remain separate and are preserved.
|
||||
if(preparedPassageSweepRequested&&!preparedSweepSample
|
||||
&&!passageTileQueries->hasFeature(passageIndex,true)
|
||||
&&!passageTileQueries->hasMouthSupport(passageIndex)
|
||||
&&!passageTileQueries->hasUpperMouthSupport(passageIndex)
|
||||
&&!passageTileQueries->routeFeatureMayAffect(passageIndex,qx,qy,qz))
|
||||
&&!passageTileQueries->routeFeatureMayAffect(passageIndex,qx,qy,qz))
|
||||
{
|
||||
passageTileQueries->recordFeatureBoundSkip();
|
||||
continue;
|
||||
}
|
||||
if(usePreparedPassageSweep
|
||||
&&preparedSweepSample->signedDistance>passageCarveReachQ)continue;
|
||||
const bool tilePassageFree=passageTileScopeMatches
|
||||
&&!ActivePassageTileQueries->hasFeature(passageIndex,false);
|
||||
if(composed>=0.0f&&tilePassageFree)
|
||||
{
|
||||
if(preparedPassageSweepRequested&&!preparedSweepSample)
|
||||
passageTileQueries->recordSweepMissSkip(
|
||||
FScopedPassageTileQueries::ESweepMissSkipReason::TileFree);
|
||||
continue;
|
||||
}
|
||||
if(qz>firstFloorQ+2.0*passage.mouthRadiusSubvoxels
|
||||
||qz<lastFloorQ-2.0*passage.mouthRadiusSubvoxels)
|
||||
{
|
||||
if(preparedPassageSweepRequested&&!preparedSweepSample)
|
||||
passageTileQueries->recordSweepMissSkip(
|
||||
FScopedPassageTileQueries::ESweepMissSkipReason::VerticalBound);
|
||||
continue;
|
||||
}
|
||||
const std::ptrdiff_t lastIndex=passageConstants.lastIndex;
|
||||
@@ -2018,6 +2159,9 @@ public:
|
||||
carveSourceReachQ(composed)))
|
||||
{
|
||||
if(passageProfile)++passageProfile->passageNegativeBoundRejects;
|
||||
if(preparedPassageSweepRequested&&!preparedSweepSample)
|
||||
passageTileQueries->recordSweepMissSkip(
|
||||
FScopedPassageTileQueries::ESweepMissSkipReason::NegativeReach);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -2037,6 +2181,9 @@ public:
|
||||
carveSourceReachQ(composed)))
|
||||
{
|
||||
if(passageProfile)++passageProfile->passagePositiveBoundRejects;
|
||||
if(preparedPassageSweepRequested&&!preparedSweepSample)
|
||||
passageTileQueries->recordSweepMissSkip(
|
||||
FScopedPassageTileQueries::ESweepMissSkipReason::PositiveReach);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -2153,6 +2300,7 @@ public:
|
||||
}
|
||||
else if(passageTileScopeMatches)
|
||||
{
|
||||
passageTileQueries->recordExactRouteFallback();
|
||||
VisitNearestPassageSegmentRange(passageIndex,carveBegin,carveEnd,qx,qy,qz,
|
||||
0,bestSignedDistance,considerCarveSegment);
|
||||
VisitNearestPassageSegmentRange(passageIndex,0,
|
||||
@@ -3123,6 +3271,8 @@ public:
|
||||
bool CaptureDensityQueryProfile=false;
|
||||
uint64 DensityPointCalls=0,DensityFloatPointCalls=0,DensityLatticePointCalls=0,
|
||||
DensityUnclampedPointCalls=0,DensityX8PointCalls=0;
|
||||
std::array<uint64,PassageDensityQueryCallerCount> DensityOffGridFloatByCaller{},
|
||||
DensityOffGridUnclampedByCaller{},DensityOffGridDetailByCaller{};
|
||||
uint64 DensityFieldEvalNanoseconds=0,DensityFieldEvalSamplePoints=0;
|
||||
std::array<uint64,4> DensityFieldEvalNanosecondsByKind{},DensityFieldEvalSamplePointsByKind{};
|
||||
static constexpr std::size_t LegacyFieldTermCount=9;
|
||||
@@ -3149,6 +3299,16 @@ public:
|
||||
{ThreadClassificationStats().CaptureDensityQueryProfile=Enabled;}
|
||||
static FClassificationThreadStats GetThreadClassificationStats()
|
||||
{ return ThreadClassificationStats(); }
|
||||
static void RecordOffGridDensityQuery(float X,float Y,float Z,
|
||||
std::array<uint64,PassageDensityQueryCallerCount>& Counts)
|
||||
{
|
||||
if((std::abs(static_cast<double>(X)-std::round(static_cast<double>(X)))<=1.0e-5
|
||||
&&std::abs(static_cast<double>(Y)-std::round(static_cast<double>(Y)))<=1.0e-5
|
||||
&&std::abs(static_cast<double>(Z)-std::round(static_cast<double>(Z)))<=1.0e-5))
|
||||
return;
|
||||
const auto Caller=static_cast<std::size_t>(CurrentPassageDensityQueryCaller());
|
||||
if(Caller<Counts.size())++Counts[Caller];
|
||||
}
|
||||
static void RecordLinux77Dispatch(VoxelForgeCore::Linux77Profiler::ERoute route,
|
||||
uint64 points)
|
||||
{
|
||||
@@ -4326,6 +4486,10 @@ public:
|
||||
float DensityAt(float X,float Y,float Z) const
|
||||
{
|
||||
if(SharedDensitySource)return SharedDensitySource->DensityAt(X,Y,Z);
|
||||
if(const auto* QueryProfile=FScopedPassageTileQueries::CurrentFor(*this);
|
||||
QueryProfile&&QueryProfile->capturesCallerDiagnostics())
|
||||
RecordOffGridDensityQuery(X,Y,Z,
|
||||
ThreadClassificationStats().DensityOffGridFloatByCaller);
|
||||
FScopedDensityQueryProfile queryProfile(EDensityQueryKind::Float);
|
||||
using namespace VoxelForgeCore::Linux77Profiler;
|
||||
FScopedRoute l77DispatchRoute(ERoute::Dispatch);
|
||||
@@ -4547,6 +4711,10 @@ public:
|
||||
FScopedPhase l77Phase(EPhase::BaseField);
|
||||
return SharedDensitySource->DensityAtUnclamped(X,Y,Z);
|
||||
}
|
||||
if(const auto* QueryProfile=FScopedPassageTileQueries::CurrentFor(*this);
|
||||
QueryProfile&&QueryProfile->capturesCallerDiagnostics())
|
||||
RecordOffGridDensityQuery(X,Y,Z,
|
||||
ThreadClassificationStats().DensityOffGridUnclampedByCaller);
|
||||
FScopedDensityQueryProfile queryProfile(EDensityQueryKind::Unclamped);
|
||||
FScopedRoute l77DispatchRoute(ERoute::Dispatch);
|
||||
FScopedPhase l77DispatchPhase(EPhase::Dispatch);
|
||||
@@ -4596,6 +4764,10 @@ public:
|
||||
VoxelForgeCore::DetailFieldSample DetailSampleAt(float X,float Y,float Z) const
|
||||
{
|
||||
if(SharedDensitySource)return SharedDensitySource->DetailSampleAt(X,Y,Z);
|
||||
if(const auto* QueryProfile=FScopedPassageTileQueries::CurrentFor(*this);
|
||||
QueryProfile&&QueryProfile->capturesCallerDiagnostics())
|
||||
RecordOffGridDensityQuery(X,Y,Z,
|
||||
ThreadClassificationStats().DensityOffGridDetailByCaller);
|
||||
VoxelForgeCore::DetailFieldSample Sample;
|
||||
if(bNativeOnly)
|
||||
{RecordNativeOnlyViolation();return Sample;}
|
||||
@@ -14354,15 +14526,24 @@ FStandaloneShapeWorld::FScopedPassageTileQueries::sweptSample(
|
||||
const auto sweep=passageSweepData_;
|
||||
if(!sweep)return nullptr;
|
||||
sweep->lookups.fetch_add(1,std::memory_order_relaxed);
|
||||
if(passageIndex>=sweep->passageToSweep.size())
|
||||
const auto recordMissing=[&]()
|
||||
{
|
||||
sweep->missingSamples.fetch_add(1,std::memory_order_relaxed);
|
||||
if(!profileStats_)return;
|
||||
const auto caller=static_cast<std::size_t>(
|
||||
FStandaloneShapeWorld::CurrentPassageDensityQueryCaller());
|
||||
if(caller<PassageDensityQueryCallerCount)
|
||||
sweep->missingLookupsByCaller[caller].fetch_add(1,std::memory_order_relaxed);
|
||||
};
|
||||
if(passageIndex>=sweep->passageToSweep.size())
|
||||
{
|
||||
recordMissing();
|
||||
return nullptr;
|
||||
}
|
||||
const std::int32_t passageSweepIndex=sweep->passageToSweep[passageIndex];
|
||||
if(passageSweepIndex<0||static_cast<std::size_t>(passageSweepIndex)>=sweep->passages.size())
|
||||
{
|
||||
sweep->missingSamples.fetch_add(1,std::memory_order_relaxed);
|
||||
recordMissing();
|
||||
return nullptr;
|
||||
}
|
||||
const std::array<double,3> query={qx,qy,qz};
|
||||
@@ -14375,7 +14556,7 @@ FStandaloneShapeWorld::FScopedPassageTileQueries::sweptSample(
|
||||
if(rounded<0||rounded>=sweep->dimension
|
||||
||std::abs(coordinate-static_cast<double>(rounded))>1.0e-5)
|
||||
{
|
||||
sweep->missingSamples.fetch_add(1,std::memory_order_relaxed);
|
||||
recordMissing();
|
||||
return nullptr;
|
||||
}
|
||||
grid[axis]=rounded;
|
||||
@@ -14386,7 +14567,7 @@ FStandaloneShapeWorld::FScopedPassageTileQueries::sweptSample(
|
||||
const auto& samples=sweep->passages[static_cast<std::size_t>(passageSweepIndex)].samples;
|
||||
if(index>=samples.size()||!samples[index].valid)
|
||||
{
|
||||
sweep->missingSamples.fetch_add(1,std::memory_order_relaxed);
|
||||
recordMissing();
|
||||
return nullptr;
|
||||
}
|
||||
sweep->cacheHits.fetch_add(1,std::memory_order_relaxed);
|
||||
|
||||
@@ -2287,6 +2287,12 @@ namespace VoxelForgeCore
|
||||
out.diagnostics.densityFloatPointCalls=QueryCounts.DensityFloatPointCalls;
|
||||
out.diagnostics.densityLatticePointCalls=QueryCounts.DensityLatticePointCalls;
|
||||
out.diagnostics.densityUnclampedPointCalls=QueryCounts.DensityUnclampedPointCalls;
|
||||
out.diagnostics.densityOffGridFloatByCaller=
|
||||
QueryCounts.DensityOffGridFloatByCaller;
|
||||
out.diagnostics.densityOffGridUnclampedByCaller=
|
||||
QueryCounts.DensityOffGridUnclampedByCaller;
|
||||
out.diagnostics.densityOffGridDetailByCaller=
|
||||
QueryCounts.DensityOffGridDetailByCaller;
|
||||
out.diagnostics.densityX8PointCalls=QueryCounts.DensityX8PointCalls;
|
||||
out.diagnostics.densityFieldEvalNanoseconds=QueryCounts.DensityFieldEvalNanoseconds;
|
||||
out.diagnostics.densityFieldEvalSamplePoints=QueryCounts.DensityFieldEvalSamplePoints;
|
||||
@@ -3024,6 +3030,10 @@ namespace VoxelForgeCore
|
||||
out.diagnostics.marchingCubesSkirtBoundaryCandidates=
|
||||
McStageTimings.SkirtBoundaryCandidates;
|
||||
out.diagnostics.marchingCubesSkirtDensityProbes=McStageTimings.SkirtDensityProbes;
|
||||
out.diagnostics.marchingCubesSkirtDensityProbesByCaller=
|
||||
McStageTimings.SkirtDensityProbesByCaller;
|
||||
out.diagnostics.marchingCubesSkirtDensityOffGridProbesByCaller=
|
||||
McStageTimings.SkirtDensityOffGridProbesByCaller;
|
||||
}
|
||||
const double MeshingMilliseconds=std::chrono::duration<double,std::milli>(
|
||||
std::chrono::steady_clock::now()-MeshingStart).count();
|
||||
|
||||
Reference in new issue
Block a user