perf(core): FI LOD0 attribution, exact Z-inner traversal; fix a mesh gap at the passage shaft foot (L57); R26

Sampled cycle attribution of FI LOD0 field work: grid fill 83%, boundary 13%, skirts 4%; island roots,
columns and helix dominate, the column cache path is real but secondary (no thrashing). FI-only Z-inner
traversal at LOD0 (same lattice samples, exact) cuts FI whole view 5.35 -> 5.03 s and moving p50 by 12%;
global Z-inner and <=4-island culling were measured and rejected. The meshing band now includes the planned
passage support column's conservative bounds, closing a real gap where the arrival shaft meets the floor
(WorldAssemblyEvaluatorVersion 208 -> 209). fast/medium/full PASS, Clang and GCC.
Research R26 (self-checked): native lattice (maze/shaft) generator design.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-25 10:47:44 +01:00
1 parent 4e64b75044
commit 1e3e04bbac
14 files changed
+777 -48

No files matched your search

@@ -0,0 +1,55 @@
#pragma once
#include <cstdint>
#include <algorithm>
#include <limits>
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
#include <intrin.h>
#elif defined(__i386__) || defined(__x86_64__)
#include <immintrin.h>
#endif
namespace VoxelForgeCoreShared
{
inline std::uint64_t ReadCpuCycles() noexcept
{
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
_mm_lfence();
const std::uint64_t value=__rdtsc();
_mm_lfence();
return value;
#elif defined(__i386__) || defined(__x86_64__)
_mm_lfence();
const std::uint64_t value=__rdtsc();
_mm_lfence();
return value;
#else
return 0;
#endif
}
inline std::uint64_t CpuCycleReadPairOverhead() noexcept
{
static const std::uint64_t overhead=[]()
{
std::uint64_t minimum=std::numeric_limits<std::uint64_t>::max();
for(unsigned i=0;i<64;++i)
{
const std::uint64_t start=ReadCpuCycles();
const std::uint64_t end=ReadCpuCycles();
minimum=std::min(minimum,end-start);
}
return minimum==std::numeric_limits<std::uint64_t>::max()?0:minimum;
}();
return overhead;
}
inline std::uint64_t AdjustedCpuCycleDelta(std::uint64_t start,
std::uint64_t end) noexcept
{
const std::uint64_t delta=end-start;
const std::uint64_t overhead=CpuCycleReadPairOverhead();
return delta>overhead?delta-overhead:0;
}
}
@@ -0,0 +1,180 @@
#pragma once
#include "VoxelForgeCore/CpuCycleCounter.h"
#include <array>
#include <cstddef>
#include <cstdint>
namespace VoxelForgeCore::floating_island_detail
{
enum class EIslandFieldCaller : std::uint8_t
{
GridFill=0,Skirt=1,Boundary=2,PassageFilter=3,Other=4,Count=5
};
enum class EIslandAttributionBucket : std::uint8_t
{
Field=0,Island=1,Root=2,Connector=3,Helix=4,Column=5,
LocalProbe=6,SharedCache=7,MouthFilter=8,Boundary=9,CallerGrid=10,
CallerSkirt=11,CallerBoundary=12,CallerPassageFilter=13,CallerOther=14,
Count=15
};
struct FIslandFieldAttributionInstrumentation
{
static constexpr std::uint64_t SampleMask=255;
std::array<std::uint64_t,static_cast<std::size_t>(EIslandFieldCaller::Count)> sampledFieldCalls{};
std::array<std::uint64_t,static_cast<std::size_t>(EIslandFieldCaller::Count)> fieldCycles{};
std::array<std::uint64_t,static_cast<std::size_t>(EIslandFieldCaller::Count)> sampledNativeCalls{};
std::array<std::uint64_t,static_cast<std::size_t>(EIslandFieldCaller::Count)> nativeCycles{};
std::array<std::uint64_t,static_cast<std::size_t>(EIslandAttributionBucket::Count)> exclusiveCycles{};
std::array<std::uint64_t,static_cast<std::size_t>(EIslandAttributionBucket::Count)> scopeSamples{};
std::uint64_t traceSampledMisses=0,traceSeenBefore=0,traceEvictions=0,
traceReusedEvictions=0;
std::array<std::uint64_t,8> traceSet{};
std::array<std::int64_t,8> traceX{},traceY{},traceEvictedX{},traceEvictedY{};
std::array<std::uint64_t,8> traceIsland{},traceEvictedIsland{};
std::array<std::uint8_t,8> traceFlags{};
std::size_t traceCount=0;
};
inline FIslandFieldAttributionInstrumentation*& ActiveIslandFieldAttribution() noexcept
{
static thread_local FIslandFieldAttributionInstrumentation* active=nullptr;
return active;
}
inline FIslandFieldAttributionInstrumentation* SetActiveIslandFieldAttribution(
FIslandFieldAttributionInstrumentation* value) noexcept
{
auto* previous=ActiveIslandFieldAttribution();
ActiveIslandFieldAttribution()=value;
return previous;
}
inline EIslandFieldCaller& ActiveIslandFieldCaller() noexcept
{
static thread_local EIslandFieldCaller caller=EIslandFieldCaller::Other;
return caller;
}
struct FScopedIslandFieldCaller
{
explicit FScopedIslandFieldCaller(EIslandFieldCaller value) noexcept
:previous(ActiveIslandFieldCaller()),enabled(ActiveIslandFieldAttribution()!=nullptr)
{if(enabled)ActiveIslandFieldCaller()=value;}
~FScopedIslandFieldCaller(){if(enabled)ActiveIslandFieldCaller()=previous;}
EIslandFieldCaller previous;
bool enabled=false;
};
inline std::array<std::uint64_t,
static_cast<std::size_t>(EIslandAttributionBucket::Count)>&
IslandComponentSampleSequence() noexcept
{
static thread_local std::array<std::uint64_t,
static_cast<std::size_t>(EIslandAttributionBucket::Count)> sequence{};
return sequence;
}
inline std::array<std::uint64_t,
static_cast<std::size_t>(EIslandFieldCaller::Count)>&
IslandFieldSampleSequence() noexcept
{
static thread_local std::array<std::uint64_t,
static_cast<std::size_t>(EIslandFieldCaller::Count)> sequence{};
return sequence;
}
inline std::array<std::uint64_t,
static_cast<std::size_t>(EIslandFieldCaller::Count)>&
IslandNativeSampleSequence() noexcept
{
static thread_local std::array<std::uint64_t,
static_cast<std::size_t>(EIslandFieldCaller::Count)> sequence{};
return sequence;
}
struct FScopedIslandAttributionTimer
{
explicit FScopedIslandAttributionTimer(EIslandAttributionBucket bucket) noexcept
:metrics(ActiveIslandFieldAttribution()),bucketIndex(static_cast<std::size_t>(bucket))
{
if(!metrics)return;
if(bucketIndex==static_cast<std::size_t>(EIslandAttributionBucket::Field))
{
const auto callerIndex=static_cast<std::size_t>(ActiveIslandFieldCaller());
const auto calls=++IslandFieldSampleSequence()[callerIndex];
const std::uint64_t phase=(callerIndex*43u+17u)
&FIslandFieldAttributionInstrumentation::SampleMask;
sampled=(((calls+phase)&FIslandFieldAttributionInstrumentation::SampleMask)==0);
}
else
{
auto& calls=IslandComponentSampleSequence()[bucketIndex];
++calls;
const std::uint64_t phase=(static_cast<std::uint64_t>(bucketIndex)*29u+17u)
&FIslandFieldAttributionInstrumentation::SampleMask;
sampled=(((calls+phase)&FIslandFieldAttributionInstrumentation::SampleMask)==0);
}
if(sampled)start=VoxelForgeCoreShared::ReadCpuCycles();
}
~FScopedIslandAttributionTimer(){Stop();}
std::uint64_t Stop() noexcept
{
if(!sampled)return 0;
sampled=false;
const std::uint64_t raw=VoxelForgeCoreShared::ReadCpuCycles()-start;
const std::uint64_t overhead=VoxelForgeCoreShared::CpuCycleReadPairOverhead();
const std::uint64_t cycles=raw>overhead?raw-overhead:0;
metrics->exclusiveCycles[bucketIndex]+=cycles;
++metrics->scopeSamples[bucketIndex];
if(bucketIndex==static_cast<std::size_t>(EIslandAttributionBucket::Field))
{
const std::size_t callerIndex=static_cast<std::size_t>(ActiveIslandFieldCaller());
metrics->fieldCycles[callerIndex]+=cycles;
++metrics->sampledFieldCalls[callerIndex];
}
return cycles;
}
FIslandFieldAttributionInstrumentation* metrics=nullptr;
std::size_t bucketIndex=0;
std::uint64_t start=0;
bool sampled=false;
};
struct FScopedIslandAttributionSample
{
explicit FScopedIslandAttributionSample() noexcept
{
auto* attribution=ActiveIslandFieldAttribution();
if(!attribution)return;
const auto caller=ActiveIslandFieldCaller();
const std::size_t callerIndex=static_cast<std::size_t>(caller);
const std::uint64_t sequence=++IslandNativeSampleSequence()[callerIndex];
const std::uint64_t phase=(callerIndex*43u+93u)
&FIslandFieldAttributionInstrumentation::SampleMask;
if(((sequence+phase)&FIslandFieldAttributionInstrumentation::SampleMask)!=0)return;
sampledAttribution=attribution;
sampledCaller=caller;
sampled=true;
start=VoxelForgeCoreShared::ReadCpuCycles();
++attribution->sampledNativeCalls[callerIndex];
}
~FScopedIslandAttributionSample()
{
if(!sampled)return;
const std::uint64_t raw=VoxelForgeCoreShared::ReadCpuCycles()-start;
const std::uint64_t overhead=VoxelForgeCoreShared::CpuCycleReadPairOverhead();
const std::uint64_t duration=raw>overhead?raw-overhead:0;
const std::size_t callerIndex=static_cast<std::size_t>(sampledCaller);
sampledAttribution->nativeCycles[callerIndex]+=duration;
}
FIslandFieldAttributionInstrumentation* sampledAttribution=nullptr;
EIslandFieldCaller sampledCaller=EIslandFieldCaller::Other;
std::uint64_t start=0;
bool sampled=false;
};
}
@@ -1,5 +1,7 @@
#pragma once
#include "VoxelForgeCore/CpuCycleCounter.h"
#include <array>
#include <atomic>
#include <cstddef>
@@ -20,6 +22,14 @@ namespace VoxelForgeCoreShared
std::uint64_t computes = 0;
std::uint64_t conflictReplacements = 0;
std::uint64_t lockWaitNanoseconds = 0;
std::uint64_t sampledInitialReadCycles = 0;
std::uint64_t sampledInitialReads = 0;
std::uint64_t sampledLockedReadCycles = 0;
std::uint64_t sampledLockedReads = 0;
std::uint64_t sampledLockCycles = 0;
std::uint64_t sampledLocks = 0;
std::uint64_t sampledBuildCycles = 0;
std::uint64_t sampledBuilds = 0;
};
// Exact input identity for a pure XY column value. LOD is deliberately not part of this key:
@@ -79,17 +89,24 @@ namespace VoxelForgeCoreShared
struct FSpinGuard
{
explicit FSpinGuard(std::atomic_flag& value, FColumnCacheMetrics* metrics)
explicit FSpinGuard(std::atomic_flag& value, FColumnCacheMetrics* metrics,
bool sampleCycles)
: Flag(value), Metrics(metrics)
{
const auto started = Metrics ? std::chrono::steady_clock::now()
: std::chrono::steady_clock::time_point{};
const std::uint64_t cycleStart=sampleCycles?ReadCpuCycles():0;
while (Flag.test_and_set(std::memory_order_acquire))
std::this_thread::yield();
if (Metrics)
Metrics->lockWaitNanoseconds += static_cast<std::uint64_t>(
std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::steady_clock::now() - started).count());
if(sampleCycles)
{
Metrics->sampledLockCycles+=AdjustedCpuCycleDelta(cycleStart,ReadCpuCycles());
++Metrics->sampledLocks;
}
}
~FSpinGuard() { Flag.clear(std::memory_order_release); }
std::atomic_flag& Flag;
@@ -120,21 +137,45 @@ namespace VoxelForgeCoreShared
const std::size_t setIndex = static_cast<std::size_t>(tag) & (SetCount - 1);
FSet& set = Sets[setIndex];
TValue value{};
if (TryReadSet(set, keyWords, tag, value))
static thread_local std::uint64_t timingSequence=0;
const bool sampleCycles=metrics&&((++timingSequence&127u)==0);
const std::uint64_t initialReadStart=sampleCycles?ReadCpuCycles():0;
const bool initialHit=TryReadSet(set, keyWords, tag, value);
if(sampleCycles)
{
metrics->sampledInitialReadCycles+=AdjustedCpuCycleDelta(
initialReadStart,ReadCpuCycles());
++metrics->sampledInitialReads;
}
if (initialHit)
{
if (metrics) ++metrics->hits;
return value;
}
if (metrics) ++metrics->misses;
FSpinGuard lock(set.Writer, metrics);
if (TryReadSet(set, keyWords, tag, value))
FSpinGuard lock(set.Writer, metrics,sampleCycles);
const std::uint64_t lockedReadStart=sampleCycles?ReadCpuCycles():0;
const bool lockedHit=TryReadSet(set, keyWords, tag, value);
if(sampleCycles)
{
metrics->sampledLockedReadCycles+=AdjustedCpuCycleDelta(
lockedReadStart,ReadCpuCycles());
++metrics->sampledLockedReads;
}
if (lockedHit)
{
if (metrics) ++metrics->hits;
return value;
}
const std::uint64_t buildStart=sampleCycles?ReadCpuCycles():0;
value = std::forward<TFactory>(factory)();
if(sampleCycles)
{
metrics->sampledBuildCycles+=AdjustedCpuCycleDelta(buildStart,ReadCpuCycles());
++metrics->sampledBuilds;
}
computed = true;
if (metrics) ++metrics->computes;
FValueWords valueWords{};
@@ -400,7 +400,7 @@ namespace VoxelForgeCore
// version 169 sank every connector 2 m; it left four FI route support probes low.
// version 170 sinks only connectors touching the anchored root by 1 m.
// Version 208 keeps the crater tread scoped to style-zero FI mouths.
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 208;
inline constexpr std::uint32_t WorldAssemblyEvaluatorVersion = 209;
enum class FieldChannel : std::uint32_t
{
@@ -56,6 +56,7 @@
#include "VoxelForgeCore/VoxelForgeCore.h"
#include "VoxelForgeCore/ThreadLocalStorage.h"
#include "VoxelForgeCore/SharedColumnCache.h"
#include "VoxelForgeCore/FloatingIslandInstrumentation.h"
// Keep Core's expression-level FMA behavior fixed regardless of the toolchain setting.
// Clang's "fast" mode ignores the pragma, so Core's runtime self-test rejects that build.
+116 -9
View File
@@ -1,6 +1,9 @@
#pragma once
#include "VoxelForgeCore/ThreadLocalStorage.h"
#include "VoxelForgeCore/CpuCycleCounter.h"
#include "VoxelForgeCore/FloatingIslandInstrumentation.h"
#include "VoxelForgeCore/SharedColumnCache.h"
#include "Json.h"
#include "VoxelForgeCore/VoxelForgeCore.h"
@@ -474,7 +477,10 @@ namespace floating_island_detail
struct FIslandColumnCacheInstrumentation
{
std::uint64_t localHits=0,localMisses=0,localConflictReplacements=0;
std::uint64_t localProbeCycles=0,localProbeSamples=0;
std::uint64_t tileStartCycles=0,tileCycles=0;
VoxelForgeCoreShared::FColumnCacheMetrics shared;
FIslandFieldAttributionInstrumentation attribution;
};
inline FIslandColumnCacheInstrumentation*& ActiveIslandColumnCacheInstrumentation() noexcept
@@ -488,16 +494,49 @@ namespace floating_island_detail
{
FIslandColumnCacheInstrumentation* previous=ActiveIslandColumnCacheInstrumentation();
ActiveIslandColumnCacheInstrumentation()=value;
SetActiveIslandFieldAttribution(value?&value->attribution:nullptr);
return previous;
}
using FSharedIslandColumnCache =
VoxelForgeCoreShared::TSharedColumnValueCache<FIslandColumnCacheEntry,16384,4>;
struct FIslandColumnTraceKey
{
bool valid=false;
std::uint64_t recipeHash=0,planHash=0,island=0;
std::int64_t x=0,y=0;
};
struct FIslandColumnReuseTrace
{
std::array<FIslandColumnTraceKey,128> recentMisses{};
std::array<FIslandColumnTraceKey,128> recentEvictions{};
std::uint64_t missSequence=0,printedEvents=0;
};
inline bool SameTraceKey(const FIslandColumnTraceKey& left,
const FIslandColumnTraceKey& right) noexcept
{
return left.valid&&right.valid&&left.recipeHash==right.recipeHash
&&left.planHash==right.planHash&&left.island==right.island
&&left.x==right.x&&left.y==right.y;
}
inline std::size_t TraceKeyIndex(const FIslandColumnTraceKey& key) noexcept
{
std::uint64_t hash=key.island^static_cast<std::uint64_t>(key.x)*0x9e3779b97f4a7c15ull
^static_cast<std::uint64_t>(key.y)*0xc2b2ae3d27d4eb4full
^key.recipeHash^std::rotl(key.planHash,17);
hash^=hash>>33;hash*=0xff51afd7ed558ccdull;hash^=hash>>33;
return static_cast<std::size_t>(hash&127u);
}
inline const FIslandColumnCacheEntry& IslandColumnCache(
const FloatingIslandRecipeV1& recipe,const FloatingIslandPlanV1& plan,
const FloatingIslandAnchorV1& island,double x,double y)
{
FScopedIslandAttributionTimer columnTimer(EIslandAttributionBucket::Column);
// Density samples arrive on integer Core lattice columns; reuse the exact column metrics
// across Z samples without changing the field value or touching shared world state.
// Les echantillons suivent les colonnes Core entieres; reutiliser les memes metriques XY.
@@ -507,6 +546,7 @@ namespace floating_island_detail
static thread_local VoxelForgeCoreThreadLocal::FLazy<
std::array<FIslandColumnCacheEntry,SetCount*Ways>> Cache;
auto& cache=Cache.Get();
FScopedIslandAttributionTimer localProbeTimer(EIslandAttributionBucket::LocalProbe);
const std::int64_t SampleX=static_cast<std::int64_t>(x);
const std::int64_t SampleY=static_cast<std::int64_t>(y);
std::uint64_t IndexKey=island.stableId
@@ -545,10 +585,56 @@ namespace floating_island_detail
if(!Entry.bValid&&!bFoundInvalid)
{Replacement=&Entry;bFoundInvalid=true;}
}
localProbeTimer.Stop();
if(auto* stats=ActiveIslandColumnCacheInstrumentation())
{
++stats->localMisses;
if(!bFoundInvalid)++stats->localConflictReplacements;
static thread_local FIslandColumnReuseTrace trace;
if((++trace.missSequence&1023u)==0)
{
auto& a=stats->attribution;
++a.traceSampledMisses;
const FIslandColumnTraceKey requested{true,recipe.contentHash,
plan.contentHash,island.stableId,SampleX,SampleY};
const std::size_t requestSlot=TraceKeyIndex(requested);
const bool seenBefore=SameTraceKey(trace.recentMisses[requestSlot],requested);
const bool reusedEviction=SameTraceKey(
trace.recentEvictions[requestSlot],requested);
if(seenBefore)++a.traceSeenBefore;
if(reusedEviction)
{
++a.traceReusedEvictions;
trace.recentEvictions[requestSlot].valid=false;
}
FIslandColumnTraceKey evicted{};
std::size_t replacementWay=0;
if(!bFoundInvalid&&Replacement)
{
evicted={Replacement->bValid,Replacement->RecipeContentHash,
Replacement->PlanContentHash,Replacement->StableId,
Replacement->SampleX,Replacement->SampleY};
replacementWay=static_cast<std::size_t>(Replacement-&cache[Base]);
++a.traceEvictions;
if(evicted.valid)
trace.recentEvictions[TraceKeyIndex(evicted)]=evicted;
}
trace.recentMisses[requestSlot]=requested;
if(trace.printedEvents<16&&a.traceCount<a.traceSet.size())
{
const std::size_t event=a.traceCount++;
++trace.printedEvents;
a.traceSet[event]=Base/Ways;
a.traceX[event]=SampleX;a.traceY[event]=SampleY;
a.traceIsland[event]=island.stableId;
a.traceEvictedX[event]=evicted.valid?evicted.x:0;
a.traceEvictedY[event]=evicted.valid?evicted.y:0;
a.traceEvictedIsland[event]=evicted.valid?evicted.island:0;
a.traceFlags[event]=static_cast<std::uint8_t>(
(!bFoundInvalid?1u:0u)|(seenBefore?2u:0u)|(reusedEviction?4u:0u)
|(replacementWay<<3));
}
}
}
const auto build=[&]()
@@ -575,9 +661,14 @@ namespace floating_island_detail
Entry.Radial=std::hypot(Entry.DeltaX,Entry.DeltaY);
Entry.Angle=std::atan2(Entry.DeltaY,Entry.DeltaX);
Entry.LobePhase=LobePhase(recipe,island);
double contourOffset=0.0;
{
FScopedIslandAttributionTimer helixTimer(EIslandAttributionBucket::Helix);
contourOffset=LobeOffsetWithPhase(recipe,Entry.Angle,
static_cast<double>(island.topZSubvoxels),Entry.LobePhase);
}
const double EffectiveRadius=std::max(1.0,static_cast<double>(island.radiusSubvoxels)
+LobeOffsetWithPhase(recipe,Entry.Angle,static_cast<double>(island.topZSubvoxels),
Entry.LobePhase));
+contourOffset);
const double Edge=std::clamp(Entry.Radial/EffectiveRadius,0.0,1.0);
const double Drop=(1.0-Q16ToDouble(recipe.topFlattenQ16))
*static_cast<double>(island.topHalfSubvoxels)*2.0*Edge*Edge;
@@ -594,8 +685,11 @@ namespace floating_island_detail
plan.contentHash,SampleX,SampleY,island.stableId};
bool computed=false;
auto* stats=ActiveIslandColumnCacheInstrumentation();
Entry=shared->getOrCompute(key,build,computed,
stats?&stats->shared:nullptr);
{
FScopedIslandAttributionTimer sharedCacheTimer(EIslandAttributionBucket::SharedCache);
Entry=shared->getOrCompute(key,build,computed,
stats?&stats->shared:nullptr);
}
}
else Entry=build();
*Replacement=Entry;
@@ -658,6 +752,7 @@ namespace floating_island_detail
const FloatingIslandAnchorV1& island,
std::int32_t rootIndex, double x, double y, double z)
{
FScopedIslandAttributionTimer attributionTimer(EIslandAttributionBucket::Root);
// Cache derived root constants per worker. The complete immutable input key keeps this
// value-only cache safe across worlds, epochs and worker schedules.
// Mettre en cache les constantes par worker; la cle complete evite tout partage d'etat.
@@ -778,6 +873,7 @@ namespace floating_island_detail
const FloatingIslandAnchorV1& island,
double x, double y, double z)
{
FScopedIslandAttributionTimer islandTimer(EIslandAttributionBucket::Island);
if (recipe.geometryVersion < 2)
{
const double dx = x - static_cast<double>(island.centerSubvoxels[0]);
@@ -805,8 +901,13 @@ namespace floating_island_detail
const double radial=Column.Radial;
const double topZ = static_cast<double>(island.topZSubvoxels);
const double radius = static_cast<double>(island.radiusSubvoxels);
double contourOffset=0.0;
{
FScopedIslandAttributionTimer helixTimer(EIslandAttributionBucket::Helix);
contourOffset=LobeOffsetWithPhase(recipe,Column.Angle,z,Column.LobePhase);
}
const double effectiveRadius = std::max(0.0,
radius + LobeOffsetWithPhase(recipe,Column.Angle,z,Column.LobePhase));
radius + contourOffset);
const double edge = std::clamp(radial / std::max(effectiveRadius, 1.0), 0.0, 1.0);
const double lowerSurface = static_cast<double>(IslandCrustBottom(recipe, island))
+ radius * 0.16 * edge * edge;
@@ -853,6 +954,7 @@ namespace floating_island_detail
bool* topSurface = nullptr,
double* alongFraction = nullptr)
{
FScopedIslandAttributionTimer connectorTimer(EIslandAttributionBucket::Connector);
const double ax = static_cast<double>(edge.startSubvoxels[0]);
const double ay = static_cast<double>(edge.startSubvoxels[1]);
const double az = static_cast<double>(edge.startSubvoxels[2]);
@@ -2184,14 +2286,19 @@ bool FloatingIslandFieldV1::isValid() const noexcept
std::int64_t FloatingIslandFieldV1::densitySubvoxels(std::int64_t x,
std::int64_t y, std::int64_t z) const noexcept
{
floating_island_detail::FScopedIslandAttributionTimer fieldTimer(
floating_island_detail::EIslandAttributionBucket::Field);
// The selected evaluator validates once; do not scan the plan twice per scoped sample.
// L'evaluateur choisi valide une seule fois; ne pas reparcourir le plan a chaque echantillon.
std::int64_t density=floating_island_detail::MaxDensity;
if (const auto* list = ScopedWorldAssemblyFeatureQueriesV1::find(recipe_, plan_, x, y, z))
return densitySubvoxelsForTile(x, y, z, *list);
if (!isValid() || !floating_island_detail::ValidScalar(x)
density=densitySubvoxelsForTile(x, y, z, *list);
else if (!isValid() || !floating_island_detail::ValidScalar(x)
|| !floating_island_detail::ValidScalar(y) || !floating_island_detail::ValidScalar(z))
return floating_island_detail::MaxDensity;
return floating_island_detail::FieldDensity(*recipe_, *plan_, x, y, z);
density=floating_island_detail::MaxDensity;
else density=floating_island_detail::FieldDensity(*recipe_, *plan_, x, y, z);
fieldTimer.Stop();
return density;
}
std::vector<WorldAssemblyFeatureBoundsV1> FloatingIslandFieldV1::solidSupportBounds() const
+16
View File
@@ -8,6 +8,7 @@
#include "VoxelDensityPrimitives.h"
#include "VoxelForgeCore/VoxelForgeCore.h"
#include "VoxelForgeFieldShared.h"
#include "VoxelForgeCore/FloatingIslandInstrumentation.h"
#include <algorithm>
#include <array>
@@ -414,6 +415,12 @@ public:
return FindBoundStratumForChunk(FMath::FloorToInt(Z/LayoutWidth));
}
bool IsFloatingIslandFieldAtZ(float Z) const
{
const FBoundStratumField* Bound=FindBoundStratumForZ(Z);
return Bound&&Bound->Kind==FBoundStratumField::EKind::FloatingIslands;
}
const FBoundStratumField* FindBoundStratumForManagerZ(float Z) const
{
if(!std::isfinite(Z)||!Owner||!(BoundManagerLayoutChunkWidthVoxels>0.0f))
@@ -6139,6 +6146,7 @@ private:
const auto* FieldAdapter=std::get_if<FFloatingIslandFieldAdapter>(
&Bound->Evaluator);
if(!FieldAdapter||!FieldAdapter->Evaluator.isValid())return false;
VoxelForgeCore::floating_island_detail::FScopedIslandAttributionSample attributionSample;
constexpr double Scale=static_cast<double>(VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel);
constexpr double Maximum=1000000000000.0/Scale;
if(std::abs(static_cast<double>(X))>Maximum||std::abs(static_cast<double>(Y))>Maximum
@@ -6266,8 +6274,12 @@ private:
}
if(mouthFilterWeight>0.0)
{
VoxelForgeCore::floating_island_detail::FScopedIslandAttributionTimer mouthFilterTimer(
VoxelForgeCore::floating_island_detail::EIslandAttributionBucket::MouthFilter);
constexpr std::int64_t FilterStep=8*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
std::int64_t weightedSum=0;
VoxelForgeCore::floating_island_detail::FScopedIslandFieldCaller passageFilterCaller(
VoxelForgeCore::floating_island_detail::EIslandFieldCaller::PassageFilter);
for(int dz=-1;dz<=1;++dz)
for(int dy=-1;dy<=1;++dy)
for(int dx=-1;dx<=1;++dx)
@@ -6306,6 +6318,8 @@ private:
{
bool surroundedByAir=true;
std::int64_t minimumAirDensity=std::numeric_limits<std::int64_t>::max();
VoxelForgeCore::floating_island_detail::FScopedIslandFieldCaller passageFilterCaller(
VoxelForgeCore::floating_island_detail::EIslandFieldCaller::PassageFilter);
for(std::size_t axis=0;axis<3&&surroundedByAir;++axis)
for(const int sign:{-1,1})
{
@@ -6323,6 +6337,8 @@ private:
if(surroundedByAir)Density=std::max(Density,minimumAirDensity);
}
}
VoxelForgeCore::floating_island_detail::FScopedIslandAttributionTimer boundaryTimer(
VoxelForgeCore::floating_island_detail::EIslandAttributionBucket::Boundary);
const std::int64_t Bottom=Plan->manifest.recipe.layoutMinimumZSubvoxels;
const std::int64_t Top=Plan->manifest.recipe.layoutMaximumZSubvoxels;
const std::int64_t Seal=Plan->manifest.recipe.boundarySealSubvoxels;
+95
View File
@@ -17,6 +17,7 @@
#include <thread>
#include <new>
#include <stdexcept>
#include <sstream>
namespace vfcore::detail
{
@@ -2013,6 +2014,7 @@ namespace VoxelForgeCore
?impl_->sharedHeightfieldColumns.get():nullptr,
options.useSharedColumnCache?impl_->sharedIslandColumns.get():nullptr);
floating_island_detail::FIslandColumnCacheInstrumentation islandCacheInstrumentation;
islandCacheInstrumentation.tileStartCycles=VoxelForgeCoreShared::ReadCpuCycles();
FScopedIslandColumnCacheInstrumentation islandCacheScope(
&islandCacheInstrumentation,options.instrumentTileDrain);
const auto& world=*impl_->owner;
@@ -2161,6 +2163,8 @@ namespace VoxelForgeCore
const auto CopyIslandCacheMetrics=[&]()
{
if(!options.instrumentTileDrain)return;
islandCacheInstrumentation.tileCycles=VoxelForgeCoreShared::ReadCpuCycles()
-islandCacheInstrumentation.tileStartCycles;
out.diagnostics.islandLocalCacheHits=islandCacheInstrumentation.localHits;
out.diagnostics.islandLocalCacheMisses=islandCacheInstrumentation.localMisses;
out.diagnostics.islandLocalCacheConflictReplacements=
@@ -2172,6 +2176,73 @@ namespace VoxelForgeCore
islandCacheInstrumentation.shared.conflictReplacements;
out.diagnostics.islandSharedCacheLockWaitNanoseconds=
islandCacheInstrumentation.shared.lockWaitNanoseconds;
const auto& a=islandCacheInstrumentation.attribution;
const auto Estimate=[](std::uint64_t cycles,std::uint64_t calls,
std::uint64_t samples)->std::uint64_t
{
return samples?static_cast<std::uint64_t>(
static_cast<long double>(cycles)*calls/samples):0;
};
constexpr std::array<const char*,5> CallerNames={
"grid","skirt","boundary","filter","other"};
constexpr std::array<const char*,10> BucketNames={
"field","island","roots","connectors","helix","column",
"local_probe","shared_cache","mouth_filter","boundary"};
std::uint64_t sampledNativeCalls=0;
for(const auto samples:a.sampledNativeCalls)sampledNativeCalls+=samples;
std::ostringstream line;
line<<"[FiFieldAttribution] key=("<<key.coordinate.x<<","<<key.coordinate.y<<","<<key.coordinate.z
<<",lod"<<key.lod<<") tile_cycles="<<islandCacheInstrumentation.tileCycles
<<" sample_period=256 native_calls_est="<<sampledNativeCalls*256
<<" native_samples="<<sampledNativeCalls;
for(std::size_t i=0;i<a.sampledNativeCalls.size();++i)
{
line<<" native_"<<CallerNames[i]<<"="<<a.sampledNativeCalls[i]*256<<"/"
<<a.sampledNativeCalls[i]<<"/"
<<Estimate(a.nativeCycles[i],a.sampledNativeCalls[i]*256,
a.sampledNativeCalls[i]);
line<<" field_"<<CallerNames[i]<<"="<<a.sampledFieldCalls[i]*256<<"/"
<<a.sampledFieldCalls[i]<<"/"
<<Estimate(a.fieldCycles[i],a.sampledFieldCalls[i]*256,
a.sampledFieldCalls[i]);
}
for(std::size_t i=0;i<BucketNames.size();++i)
line<<" comp_"<<BucketNames[i]<<"="
<<Estimate(a.exclusiveCycles[i],a.scopeSamples[i]*256,
a.scopeSamples[i])
<<"/"<<a.scopeSamples[i]<<"/"<<a.scopeSamples[i]*256;
const auto& shared=islandCacheInstrumentation.shared;
line<<" local_probe_calls="<<(islandCacheInstrumentation.localHits
+islandCacheInstrumentation.localMisses)
<<" shared_calls_est="<<shared.sampledInitialReads*128
<<" shared_initial_read="<<shared.sampledInitialReads<<"/"
<<Estimate(shared.sampledInitialReadCycles,shared.sampledInitialReads*128,
shared.sampledInitialReads)
<<" shared_locked_read="<<shared.sampledLockedReads<<"/"
<<Estimate(shared.sampledLockedReadCycles,shared.sampledLockedReads*128,
shared.sampledLockedReads)
<<" shared_lock="<<shared.sampledLocks<<"/"
<<Estimate(shared.sampledLockCycles,shared.sampledLocks*128,
shared.sampledLocks)
<<" shared_build="<<shared.sampledBuilds<<"/"
<<Estimate(shared.sampledBuildCycles,shared.sampledBuilds*128,
shared.sampledBuilds)
<<" trace_sampled="<<a.traceSampledMisses
<<" trace_seen_before="<<a.traceSeenBefore
<<" trace_evictions="<<a.traceEvictions
<<" trace_reused_evictions="<<a.traceReusedEvictions
<<" trace_events="<<a.traceCount;
std::printf("%s\n",line.str().c_str());
for(std::size_t i=0;i<a.traceCount;++i)
std::printf("[FiReuseTrace] tile=(%d,%d,%d,lod%d) set=%llu island=%llu xy=(%lld,%lld) evicted_island=%llu evicted_xy=(%lld,%lld) flags=%u\n",
key.coordinate.x,key.coordinate.y,key.coordinate.z,key.lod,
static_cast<unsigned long long>(a.traceSet[i]),
static_cast<unsigned long long>(a.traceIsland[i]),
static_cast<long long>(a.traceX[i]),static_cast<long long>(a.traceY[i]),
static_cast<unsigned long long>(a.traceEvictedIsland[i]),
static_cast<long long>(a.traceEvictedX[i]),
static_cast<long long>(a.traceEvictedY[i]),
static_cast<unsigned>(a.traceFlags[i]));
};
out.diagnostics.featureRefinedResolution=bFeatureRefinedResolution;
if(options.profileMesherStages)
@@ -2419,6 +2490,30 @@ namespace VoxelForgeCore
RelevantMinimum=std::min(RelevantMinimum,FeatureMinimum);
RelevantMaximum=std::max(RelevantMaximum,FeatureMaximum);
}
// A resolved passage void column can add solid support above or
// below the native heightfield's local Z range. Its finite radial
// and vertical bounds must participate before the mesh band is clipped.
for(const auto& Crossing:tileShape.GetPassageVoidCrossings())
{
if(!Crossing.needsColumn||Crossing.maximumRadiusSubvoxels<=0
||Crossing.topZSubvoxels<=Crossing.bottomZSubvoxels)continue;
const double Radius=static_cast<double>(Crossing.maximumRadiusSubvoxels)
/static_cast<double>(SubvoxelScale);
const double CenterX=static_cast<double>(Crossing.centerXSubvoxels)
/static_cast<double>(SubvoxelScale);
const double CenterY=static_cast<double>(Crossing.centerYSubvoxels)
/static_cast<double>(SubvoxelScale);
if(CenterX+Radius<TileMinimum[0]/static_cast<double>(SubvoxelScale)
||CenterX-Radius>TileMaximum[0]/static_cast<double>(SubvoxelScale)
||CenterY+Radius<TileMinimum[1]/static_cast<double>(SubvoxelScale)
||CenterY-Radius>TileMaximum[1]/static_cast<double>(SubvoxelScale))continue;
RelevantMinimum=std::min(RelevantMinimum,
static_cast<double>(Crossing.bottomZSubvoxels)
/static_cast<double>(SubvoxelScale));
RelevantMaximum=std::max(RelevantMaximum,
static_cast<double>(Crossing.topZSubvoxels)
/static_cast<double>(SubvoxelScale));
}
// The native heightfield band only covers the owner terrain and its
// manifest features. Resolved SDF stamps can carve below that band or
// add a floor there, so include every overlapping stamp's bounded Z