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:
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);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user