fix(core): worker-count-dependent tiles near passage support columns (L44); random-camera determinism sweep

L27 added passage support columns, but World::isTileShapeFree only bounded the route and bridge, so tiles
touched by a column could be approved for early native-only generation; depending on scheduling they used
that incomplete field or the compiled one (six LOD0 tiles differed between W1 and W12 at an SW camera near
the arrival mouth). The shape-free proof now includes a conservative envelope for every possible column.
The compiled world is unchanged (the old W1 variant), so no version bump. verify tiers gain a seeded
(SplitMix64 0x4c3434) random-camera W1/W8/W12 sweep across both recipes and several clip settings; it fails
before the fix and passes after. fast/medium/full PASS; cost within noise. Research R11: suspect review.

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-23 23:00:21 +02:00
1 parent 422dd7761a
commit 036bd530fc
6 files changed
+288 -18

No files matched your search

+27 -1
View File
@@ -423,7 +423,8 @@ namespace StandaloneStreamBenchmark
bool bAuditResolvedLayoutBoundaries=false,
bool bAuditResolvedLayoutPassages=false,
bool bAuditStrateTransitions=false,
const VoxelForgeCore::ResolvedLayoutSnapshotV3* ResolvedLayout=nullptr)
const VoxelForgeCore::ResolvedLayoutSnapshotV3* ResolvedLayout=nullptr,
bool bPrintTileHashes=false)
{
using Clock=std::chrono::steady_clock;
FStandaloneOwnerWorld& World=*OwnerWorld;
@@ -3824,6 +3825,31 @@ namespace StandaloneStreamBenchmark
&&MeshRows.size()==Desired.Tiles.size()
&&PayloadRows.size()==Desired.Tiles.size()
&&TopologyRows.size()==Desired.Tiles.size();
if(bPrintTileHashes)
{
const auto makeHashIndex=[](const std::vector<FHashedTile>& rows)
{
std::unordered_map<FVoxelTileKey,uint64,FStandaloneTileKeyHash> index;
index.reserve(rows.size());
for(const FHashedTile& row:rows)index.emplace(row.Key,row.Hash);
return index;
};
const auto MeshIndex=makeHashIndex(MeshRows);
const auto PayloadIndex=makeHashIndex(PayloadRows);
const auto TopologyIndex=makeHashIndex(TopologyRows);
const auto findHash=[](const auto& index,const FVoxelTileKey& key)
{
const auto found=index.find(key);
return found==index.end()?uint64{0}:found->second;
};
for(const FHashedTile& row:DensityRows)
std::printf("[PipelineTileHash] lod=%d x=%d y=%d z=%d density=0x%016llx mesh=0x%016llx payload=0x%016llx topology=0x%016llx\n",
row.Key.Level,row.Key.Coord.X,row.Key.Coord.Y,row.Key.Coord.Z,
static_cast<unsigned long long>(row.Hash),
static_cast<unsigned long long>(findHash(MeshIndex,row.Key)),
static_cast<unsigned long long>(findHash(PayloadIndex,row.Key)),
static_cast<unsigned long long>(findHash(TopologyIndex,row.Key)));
}
std::vector<FHashedTile> FullDensity,FullMesh,FullPayload,FullTopology;
for(const FHashedTile& Row:DensityRows)if(Row.Key.Level<World.FullResClipLevels)FullDensity.push_back(Row);
for(const FHashedTile& Row:MeshRows)if(Row.Key.Level<World.FullResClipLevels)FullMesh.push_back(Row);