core: per-tile passage route IDs and empty-feature early outs (L136, output = v236)
Passage visits -78..-89% near-ready; composer worker time back to baseline on Tunnel Network; v239 is 2-4% faster than v236 in 7/8 cells but still +4.3..+13.3% near-ready vs assembler/world. Surface World composer time equals baseline yet near-ready is +4-6%: unexplained. 16/16 seeds, fast tier, Clang/GCC green. 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
2d89023933
commit
08cc3bd89b
6 files changed
+469
-17
No files matched your search
@@ -333,10 +333,13 @@ public:
|
||||
candidate.maximumSubvoxels=bounds.maximumSubvoxels;
|
||||
candidate.sweepMinimumSubvoxels=bounds.minimumSubvoxels;
|
||||
candidate.sweepMaximumSubvoxels=bounds.maximumSubvoxels;
|
||||
if(passageRoutes_[feature.passageIndex]==0)
|
||||
routePassageIndices_.push_back(feature.passageIndex);
|
||||
passageRoutes_[feature.passageIndex]=1;
|
||||
passageRouteSegments_[feature.passageIndex].push_back(candidate);
|
||||
++routeSegmentCandidateCount_;
|
||||
}
|
||||
std::sort(routePassageIndices_.begin(),routePassageIndices_.end());
|
||||
for(auto& candidates:passageRouteSegments_)
|
||||
{
|
||||
std::sort(candidates.begin(),candidates.end(),[](const auto& a,const auto& b)
|
||||
@@ -352,6 +355,7 @@ public:
|
||||
maximumSubvoxels_(source.maximumSubvoxels_),featureIndices_(source.featureIndices_),
|
||||
stampIndices_(source.stampIndices_),cavernFeatureIndices_(source.cavernFeatureIndices_),
|
||||
passageRoutes_(source.passageRoutes_),
|
||||
routePassageIndices_(source.routePassageIndices_),
|
||||
passageRouteSegments_(source.passageRouteSegments_),
|
||||
previous_(ActivePassageTileQueries),profileStats_(source.profileStats_),
|
||||
profileLod_(source.profileLod_),
|
||||
@@ -463,6 +467,8 @@ public:
|
||||
}
|
||||
bool hasRouteFeature(std::size_t passageIndex) const
|
||||
{return passageIndex<passageRoutes_.size()&&passageRoutes_[passageIndex]!=0;}
|
||||
const std::vector<std::size_t>& routePassageIndices() const noexcept
|
||||
{return routePassageIndices_;}
|
||||
bool routeFeatureMayAffect(std::size_t passageIndex,double qx,double qy,
|
||||
double qz) const
|
||||
{
|
||||
@@ -502,6 +508,7 @@ public:
|
||||
std::array<std::int64_t,3> minimumSubvoxels_,maximumSubvoxels_;
|
||||
std::vector<std::uint32_t> featureIndices_,stampIndices_,cavernFeatureIndices_;
|
||||
std::vector<std::uint8_t> passageRoutes_;
|
||||
std::vector<std::size_t> routePassageIndices_;
|
||||
std::vector<std::vector<FCandidateSegment>> passageRouteSegments_;
|
||||
std::size_t routeSegmentCandidateCount_=0;
|
||||
bool mayContainResolvedBoundaryBand_=true,mayContainTransitionPassageFade_=true;
|
||||
@@ -1199,6 +1206,21 @@ public:
|
||||
VoxelForgeCore::Linux77Profiler::EPhase::Passage);
|
||||
if(!ResolvedLayout||ResolvedLayout->passages.empty()||!std::isfinite(X)
|
||||
||!std::isfinite(Y)||!std::isfinite(Z))return density;
|
||||
const auto* passageTileQueries=ActivePassageTileQueries;
|
||||
const bool passageTileScopeMatches=passageTileQueries
|
||||
&&passageTileQueries->matches(*this);
|
||||
auto* passageProfile=passageTileScopeMatches
|
||||
?passageTileQueries->profileStats():nullptr;
|
||||
if(passageProfile)++passageProfile->passageComposerQueries;
|
||||
if(passageProfile&&nativeTunnelFieldDensity
|
||||
!=std::numeric_limits<float>::lowest())
|
||||
++passageProfile->nativeCaveFieldSamples;
|
||||
// The tile feature list is a conservative broad phase. If no passage route
|
||||
// can affect this tile, none of the per-sample mouth, shell, or relief work
|
||||
// below can change the field.
|
||||
if(passageTileScopeMatches
|
||||
&&passageTileQueries->routePassageIndices().empty())return density;
|
||||
|
||||
constexpr double Q=static_cast<double>(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
|
||||
constexpr double FloorShellThicknessMetres=VF_PassageShellThicknessMetres;
|
||||
constexpr double WallReliefMetres=VF_PassageWallReliefMetres;
|
||||
@@ -1209,16 +1231,6 @@ public:
|
||||
const double qx=static_cast<double>(X)*Q,qy=static_cast<double>(Y)*Q,
|
||||
qz=static_cast<double>(Z)*Q;
|
||||
const double shellThickness=FloorShellThicknessMetres*qPerMetre;
|
||||
const auto* passageTileQueries=ActivePassageTileQueries;
|
||||
const bool passageTileScopeMatches=passageTileQueries
|
||||
&&passageTileQueries->matches(*this);
|
||||
auto* passageProfile=passageTileScopeMatches
|
||||
?passageTileQueries->profileStats():nullptr;
|
||||
if(passageProfile)++passageProfile->passageComposerQueries;
|
||||
if(passageProfile&&nativeTunnelFieldDensity
|
||||
!=std::numeric_limits<float>::lowest())
|
||||
++passageProfile->nativeCaveFieldSamples;
|
||||
|
||||
struct FNearestTubeSample
|
||||
{
|
||||
double signedDistance=std::numeric_limits<double>::infinity();
|
||||
@@ -1241,9 +1253,14 @@ public:
|
||||
&&queryStratum->Resolved->generatorKind=="TunnelNetwork"
|
||||
&&queryStratum->Resolved->recipeId=="Core.Caves.PrimitiveField"
|
||||
&&queryStratum->Resolved->recipeVersion==1;
|
||||
for(std::size_t passageIndex=0;passageIndex<ResolvedLayout->passages.size();
|
||||
++passageIndex)
|
||||
const auto* routePassageIndices=passageTileScopeMatches
|
||||
?&passageTileQueries->routePassageIndices():nullptr;
|
||||
const std::size_t routeCount=passageTileScopeMatches
|
||||
?routePassageIndices->size():ResolvedLayout->passages.size();
|
||||
for(std::size_t routeOffset=0;routeOffset<routeCount;++routeOffset)
|
||||
{
|
||||
const std::size_t passageIndex=passageTileScopeMatches
|
||||
?(*routePassageIndices)[routeOffset]:routeOffset;
|
||||
const auto& passage=ResolvedLayout->passages[passageIndex];
|
||||
if(passage.controlPoints.size()<2)continue;
|
||||
const bool surfaceDepartureLanding=queryStratum&&queryStratum->Resolved
|
||||
@@ -1275,8 +1292,6 @@ public:
|
||||
if(passageTargetsNativeCaveField&&!passageTargetsPlannedTunnelNetwork)
|
||||
continue;
|
||||
if(passageProfile)++passageProfile->passageIterations;
|
||||
if(passageTileScopeMatches&&!passageTileQueries->hasRouteFeature(passageIndex))
|
||||
continue;
|
||||
const auto& constants=PassageComposerConstants[passageIndex];
|
||||
|
||||
FNearestTubeSample nearest;
|
||||
@@ -7767,8 +7782,6 @@ private:
|
||||
*nativeFloorSupport=std::numeric_limits<float>::lowest();
|
||||
(void)density;
|
||||
const double metresPerVoxel=Owner->CoreVoxelSizeMicrons/1000000.0;
|
||||
const std::array<double,3> point={X*metresPerVoxel,Y*metresPerVoxel,
|
||||
Z*metresPerVoxel};
|
||||
std::vector<std::uint32_t> localCandidates;
|
||||
const std::vector<std::uint32_t>* candidates=nullptr;
|
||||
if(scoped)candidates=&tileQueries->cavernFeatureCandidates();
|
||||
@@ -7782,6 +7795,14 @@ private:
|
||||
localCandidates=BuildCavernFeatureTileList(coordinate,coordinate);
|
||||
candidates=&localCandidates;
|
||||
}
|
||||
// No cave feature overlaps this scoped tile (or unscoped point), so the
|
||||
// native field is exactly its constant host-rock value. Avoid per-sample
|
||||
// coordinate conversion and the empty feature-composition path.
|
||||
constexpr double HostRockMetres=-32.0;
|
||||
if(candidates->empty())
|
||||
return static_cast<float>(HostRockMetres/metresPerVoxel);
|
||||
const std::array<double,3> point={X*metresPerVoxel,Y*metresPerVoxel,
|
||||
Z*metresPerVoxel};
|
||||
double caveVoid=std::numeric_limits<double>::infinity();
|
||||
double nativeFloorSupportMinimum=std::numeric_limits<double>::infinity();
|
||||
double floorSupportScore=std::numeric_limits<double>::infinity();
|
||||
@@ -8024,7 +8045,6 @@ private:
|
||||
// resolved interval oracle uses the same finite -32 m solid value; using
|
||||
// the underlying legacy generator density here would leak its unrelated
|
||||
// terrain detail into the cave floor and invalidate those proofs.
|
||||
constexpr double HostRockMetres=-32.0;
|
||||
const double hostDistance=HostRockMetres;
|
||||
double composed=std::isfinite(caveVoid)
|
||||
?SmoothMaxMetres(hostDistance,-caveVoid,0.0):hostDistance;
|
||||
|
||||
Reference in new issue
Block a user