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

@@ -37,6 +37,7 @@ namespace
bool StreamBenchmark=false;
bool StreamPipeline=false;
bool StreamHash=false;
bool StreamHashTiles=false;
bool ProfileColumnOverlap=false;
bool UseSharedColumnCache=true;
bool ForceGenerate=false;
@@ -239,6 +240,7 @@ namespace
std::printf("Usage: %s [owner_world.json] --world-assembler-prototype --stream-benchmark --stream-pipeline [options]\n"
" --workers=N --clip-radius=N --max-clip-level=N --max-level=N\n"
" --camera=X,Y,Z,YAW,PITCH (position in metres) --stream-hash\n"
" --stream-hash-tiles (print per-tile hashes; implies --stream-hash)\n"
" --camera-step=X,Y,Z (optional second view step in metres)\n"
" --region-crossing (compile entering Core regions at the camera step)\n"
" --column-cache=shared|thread-local (default: shared)\n"
@@ -292,6 +294,7 @@ namespace
else if(arg=="--stream-benchmark")options.StreamBenchmark=true;
else if(arg=="--stream-pipeline")options.StreamPipeline=true;
else if(arg=="--stream-hash")options.StreamHash=true;
else if(arg=="--stream-hash-tiles")options.StreamHash=true,options.StreamHashTiles=true;
else if(arg=="--profile-column-overlap")options.ProfileColumnOverlap=true;
else if(arg=="--force-generate")options.ForceGenerate=true;
else if(arg=="--mesh-coverage")options.MeshCoverage=true;
@@ -795,5 +798,5 @@ int main(int argc,char** argv)
options.DiagnosticSlowShapeCompileMs,options.AuditBasePageEquivalence,
options.AuditRouteParity,options.AuditResolvedLayoutBoundaries,
options.AuditResolvedLayoutPassages,options.AuditStrateTransitions,
&resolvedLayout);
&resolvedLayout,options.StreamHashTiles);
}
+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);