Files
VoxelForge/Standalone/Source/StreamBenchmarkHeadless.cpp
T
Fr0zkaandClaude Opus 5.5 b21a19d561 wip(L5, side branch): Linux offscreen captures + sampled far-LOD gate + no-op octave cutoff
Not for assembler/world: no octave qualifies under the cutoff's supremum criterion (world
unchanged), and the build is +4.6% slower than L4 with the flag off (reviewer interleaved W12).
Keeps the working EGL/GLES capture path and a gate whose metric is vertical height error, which
overstates screen error on steep slopes; its "exact far meshes exceed 1 px / 126 px pop" claims are
unconfirmed. See Linux5/REPORT.md "Orchestrator review".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ED33VnqepD4YY6gDAAA832
2026-10-19 20:39:41 +02:00

322 lines
17 KiB
C++

#include "OwnerWorldLoader.h"
#include "StandaloneCoreScheduler.h"
#include "StreamBenchmarkPipeline.h"
#include "WorldAssemblyPrototype.h"
#include "StandaloneTlsProbe.h"
#include "../Core/src/StandaloneSnapshotAdapter.h"
#include <algorithm>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <iterator>
#include <limits>
#include <memory>
#include <string>
#include <string_view>
namespace
{
struct FOptions
{
std::filesystem::path DataPath;
int WorkerCount=8;
int ClipRadius=3;
int MaxClipLevel=8;
int MaxLevel=-1;
int FarHorizonLOD8InteriorStepVoxels=0;
bool WorldAssemblerPrototype=false;
bool StreamBenchmark=false;
bool StreamPipeline=false;
bool StreamHash=false;
bool ProfileColumnOverlap=false;
bool ForceGenerate=false;
bool MeshCoverage=false;
bool ScreenSpaceGate=false;
bool VisualDetailCutoff=false;
bool HasSeedOverride=false;
int SeedOverride=0;
bool HasRenderDistanceOverride=false;
int RenderDistanceOverride=0;
bool FloatingIslandsRecipe=false;
bool TlsProbeRequested=false;
int TlsProbeWorkers=0;
std::string TlsProbeTouch="none";
bool HasCamera=false;
bool AutoSurfaceCamera=false;
FVector CameraMeters=FVector::ZeroVector;
float CameraYawDegrees=0.0f;
float CameraPitchDegrees=0.0f;
std::filesystem::path MeshExportPath;
};
bool ParseInteger(std::string_view text,int& output)
{
if(text.empty())return false;
char* end=nullptr;
const std::string value(text);
const long parsed=std::strtol(value.c_str(),&end,10);
if(end==value.c_str()||*end!='\0'||parsed<INT32_MIN||parsed>INT32_MAX)return false;
output=static_cast<int>(parsed);
return true;
}
bool ParseCamera(std::string_view text,FVector& meters,float& yawDegrees,float& pitchDegrees)
{
const std::string values(text);
float x=0.0f,y=0.0f,z=0.0f,yaw=0.0f,pitch=0.0f;
if(std::sscanf(values.c_str(),"%f,%f,%f,%f,%f",&x,&y,&z,&yaw,&pitch)!=5)
return false;
meters={x,y,z};
yawDegrees=yaw;
pitchDegrees=pitch;
return true;
}
bool ParseOptions(int argc,char** argv,FOptions& options)
{
const std::filesystem::path executable=std::filesystem::absolute(argv[0]);
options.DataPath=executable.parent_path().parent_path()/"data/owner_world.json";
for(int index=1;index<argc;++index)
{
const std::string_view arg(argv[index]);
const auto readInt=[&](std::string_view prefix,int& value)
{return arg.starts_with(prefix)&&ParseInteger(arg.substr(prefix.size()),value);};
if(arg=="--help"||arg=="-h")
{
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"
" --mesh-export=FILE (write the exact generated tile meshes for offline rendering)\n"
" --profile-column-overlap --far-horizon-lod8-step=N --force-generate\n"
" --seed=N --recipe=surface-world|floating-islands\n"
" --auto-surface-camera (place the 27-tile cube on this seed's surface)\n"
" --mesh-coverage (report non-empty tiles and indexed triangles)\n"
" --screen-space-gate (measure display error and historical negative controls)\n"
" --visual-detail-cutoff (enable the declared far visual octave cutoff)\n"
" --render-distance-chunks=N (0 disables the extra far ring)\n"
" --tls-probe=N (Linux worker TLS/stack measurement; N=0..12)\n"
" --tls-probe-touch=none|surface-world|floating-islands (first-use probe)\n"
" --process-affinity=MASK --process-priority=Normal --frame-limit=FPS (viewer compatibility only)\n",
argv[0]);
return false;
}
if(arg=="--world-assembler-prototype")options.WorldAssemblerPrototype=true;
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=="--profile-column-overlap")options.ProfileColumnOverlap=true;
else if(arg=="--force-generate")options.ForceGenerate=true;
else if(arg=="--mesh-coverage")options.MeshCoverage=true;
else if(arg=="--screen-space-gate")options.ScreenSpaceGate=true;
else if(arg=="--visual-detail-cutoff")options.VisualDetailCutoff=true;
else if(arg=="--auto-surface-camera")options.AutoSurfaceCamera=true;
else if(arg.starts_with("--recipe="))
{
const std::string_view recipe=arg.substr(std::string_view("--recipe=").size());
if(recipe=="surface-world")options.FloatingIslandsRecipe=false;
else if(recipe=="floating-islands")options.FloatingIslandsRecipe=true;
else {std::fprintf(stderr,"Invalid --recipe value: %.*s\n",static_cast<int>(recipe.size()),recipe.data());return false;}
}
else if(arg.starts_with("--seed="))
{if(!readInt("--seed=",options.SeedOverride))return false;options.HasSeedOverride=true;}
else if(arg.starts_with("--render-distance-chunks="))
{
if(!readInt("--render-distance-chunks=",options.RenderDistanceOverride))return false;
options.RenderDistanceOverride=std::max(0,options.RenderDistanceOverride);
options.HasRenderDistanceOverride=true;
}
else if(arg.starts_with("--tls-probe="))
{
if(!readInt("--tls-probe=",options.TlsProbeWorkers))return false;
if(options.TlsProbeWorkers<0||options.TlsProbeWorkers>12)
{std::fprintf(stderr,"--tls-probe must be in 0..12\n");return false;}
options.TlsProbeRequested=true;
}
else if(arg.starts_with("--tls-probe-touch="))
{
const std::string_view touch=arg.substr(std::string_view("--tls-probe-touch=").size());
if(touch!="none"&&touch!="surface-world"&&touch!="floating-islands")
{std::fprintf(stderr,"Invalid --tls-probe-touch value: %.*s\n",static_cast<int>(touch.size()),touch.data());return false;}
options.TlsProbeTouch=touch;
}
else if(arg.starts_with("--camera="))
{
if(!ParseCamera(arg.substr(9),options.CameraMeters,
options.CameraYawDegrees,options.CameraPitchDegrees))
{std::fprintf(stderr,"Invalid --camera value: %.*s\n",static_cast<int>(arg.size()),arg.data());return false;}
options.HasCamera=true;
}
else if(arg.starts_with("--mesh-export="))
{
options.MeshExportPath=std::filesystem::path(arg.substr(14));
if(options.MeshExportPath.empty())
{std::fprintf(stderr,"--mesh-export needs a file path\n");return false;}
}
else if(arg.starts_with("--workers="))
{if(!readInt("--workers=",options.WorkerCount))return false;}
else if(arg.starts_with("--clip-radius="))
{if(!readInt("--clip-radius=",options.ClipRadius))return false;}
else if(arg.starts_with("--max-clip-level="))
{if(!readInt("--max-clip-level=",options.MaxClipLevel))return false;}
else if(arg.starts_with("--max-level="))
{if(!readInt("--max-level=",options.MaxLevel))return false;}
else if(arg.starts_with("--far-horizon-lod8-step="))
{if(!readInt("--far-horizon-lod8-step=",options.FarHorizonLOD8InteriorStepVoxels))return false;}
else if(arg.starts_with("--process-affinity=")||arg.starts_with("--process-priority=")
||arg.starts_with("--frame-limit="))
{
// These viewer switches are accepted for command-line parity. The caller pins
// this headless process with taskset, and a headless run has no frame limiter.
}
else if(!arg.empty()&&arg.front()!='-')options.DataPath=std::filesystem::path(arg);
else
{std::fprintf(stderr,"Unknown option: %.*s\n",static_cast<int>(arg.size()),arg.data());return false;}
}
options.WorkerCount=std::clamp(options.WorkerCount,1,16);
options.ClipRadius=std::clamp(options.ClipRadius,1,64);
options.MaxClipLevel=std::clamp(options.MaxClipLevel,0,8);
options.FarHorizonLOD8InteriorStepVoxels=std::max(0,options.FarHorizonLOD8InteriorStepVoxels);
if(!options.TlsProbeRequested&&options.TlsProbeTouch!="none")
{std::fprintf(stderr,"--tls-probe-touch requires --tls-probe=N\n");return false;}
if(options.TlsProbeRequested)return true;
if(!options.WorldAssemblerPrototype||!options.StreamBenchmark||!options.StreamPipeline)
{
std::fprintf(stderr,"This headless target runs the world-assembler streaming pipeline; pass --world-assembler-prototype --stream-benchmark --stream-pipeline.\n");
return false;
}
return true;
}
}
int main(int argc,char** argv)
{
using Clock=std::chrono::steady_clock;
const auto coldStart=Clock::now();
FOptions options;
if(!ParseOptions(argc,argv,options))return 2;
if(options.TlsProbeRequested)
return StandaloneTlsProbe::Run(options.TlsProbeWorkers,options.TlsProbeTouch);
std::printf("[HeadlessConfig] data=%s workers=%d clip_radius=%d max_clip_level=%d max_level=%d hash=%s column_overlap=%s force_generate=%s recipe=%s seed_override=%s render_distance_override=%s\n",
options.DataPath.string().c_str(),options.WorkerCount,options.ClipRadius,options.MaxClipLevel,
options.MaxLevel,options.StreamHash?"on":"off",options.ProfileColumnOverlap?"on":"off",
options.ForceGenerate?"on":"off",options.FloatingIslandsRecipe?"floating-islands":"surface-world",
options.HasSeedOverride?"yes":"no",options.HasRenderDistanceOverride?"yes":"no");
std::printf("[ColdTimeline] stage=owner_data_load begin_ms=%.3f\n",
std::chrono::duration<double,std::milli>(Clock::now()-coldStart).count());
std::string error;
auto ownerWorld=std::make_shared<FStandaloneOwnerWorld>();
VFJson::Value ownerJsonRoot;
{
std::ifstream jsonFile(options.DataPath,std::ios::binary);
if(!jsonFile)
{std::fprintf(stderr,"Owner data load failed: cannot open %s\n",options.DataPath.string().c_str());return 2;}
std::string ownerJsonText{std::istreambuf_iterator<char>(jsonFile),std::istreambuf_iterator<char>{}};
if(!jsonFile&&!jsonFile.eof())
{std::fprintf(stderr,"Owner data load failed: read error for %s\n",options.DataPath.string().c_str());return 2;}
if(!VFJson::Parser(std::move(ownerJsonText)).Parse(ownerJsonRoot,error))
{std::fprintf(stderr,"Owner data load failed: %s\n",error.c_str());return 2;}
}
if(options.HasSeedOverride
&&!StandaloneWorldAssemblyPrototype::OverrideStandaloneSeed(ownerJsonRoot,options.SeedOverride,error))
{std::fprintf(stderr,"Seed override failed: %s\n",error.c_str());return 2;}
if(options.HasRenderDistanceOverride
&&!StandaloneWorldAssemblyPrototype::OverrideStandaloneRenderDistance(
ownerJsonRoot,options.RenderDistanceOverride,error))
{std::fprintf(stderr,"Render-distance override failed: %s\n",error.c_str());return 2;}
if(options.FloatingIslandsRecipe
&&!StandaloneWorldAssemblyPrototype::SelectTopStrateAsFloatingIslands(ownerJsonRoot,error))
{std::fprintf(stderr,"Floating-island recipe selection failed: %s\n",error.c_str());return 2;}
if(!StandaloneOwnerLoader::Resolve(ownerJsonRoot,*ownerWorld,error))
{std::fprintf(stderr,"Owner data load failed: %s\n",error.c_str());return 2;}
std::printf("[ColdTimeline] stage=owner_data_load end_ms=%.3f\n",
std::chrono::duration<double,std::milli>(Clock::now()-coldStart).count());
const int seed=ownerWorld->Seed;
const int exportedMaxClipLevel=ownerWorld->MaxClipLevel;
ownerWorld->ClipRadius=options.ClipRadius;
ownerWorld->Settings->ClipRadius=options.ClipRadius;
ownerWorld->MaxClipLevel=options.MaxClipLevel;
ownerWorld->Settings->MaxClipLevel=options.MaxClipLevel;
if(exportedMaxClipLevel!=options.MaxClipLevel)
std::printf("Standalone max clip level override: exported=%d -> max_level=%d.\n",
exportedMaxClipLevel,options.MaxClipLevel);
FVector cameraVoxels=ownerWorld->ViewerStartVoxels;
if(options.HasCamera)
cameraVoxels=FVector(options.CameraMeters.X*4.0f,options.CameraMeters.Y*4.0f,options.CameraMeters.Z*4.0f);
const auto planStart=Clock::now();
VoxelForgeCore::WorldAssemblyManifest worldAssembly;
if(!StandaloneWorldAssemblyPrototype::AttachRound1WorldAssemblyPrototype(
*ownerWorld,ownerJsonRoot,error,{},&worldAssembly))
{std::fprintf(stderr,"World assembler prototype setup failed: %s\n",error.c_str());return 2;}
if(options.FloatingIslandsRecipe
&&!StandaloneWorldAssemblyPrototype::AttachFloatingIslandWorldAssembly(
*ownerWorld,ownerJsonRoot,worldAssembly,error))
{std::fprintf(stderr,"Floating-island assembly setup failed: %s\n",error.c_str());return 2;}
if(options.AutoSurfaceCamera)
{
constexpr std::int64_t UnitsPerVoxel=VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
if(options.FloatingIslandsRecipe)
{
const VoxelForgeCore::FloatingIslandAnchorV1* chosen=nullptr;
for(const auto& islandSet:worldAssembly.floatingIslands)
for(const auto& island:islandSet.manifest.plan.islands)
if(!chosen||island.radiusSubvoxels>chosen->radiusSubvoxels)chosen=&island;
if(!chosen)
{std::fprintf(stderr,"[SeedSurfacePlacement] FAIL: island plan has no anchors\n");return 2;}
cameraVoxels={
static_cast<float>(chosen->centerSubvoxels[0])/UnitsPerVoxel,
static_cast<float>(chosen->centerSubvoxels[1])/UnitsPerVoxel,
static_cast<float>(chosen->centerSubvoxels[2])/UnitsPerVoxel};
std::printf("[SeedSurfacePlacement] recipe=floating-islands seed=%d island_radius_vox=%.3f camera_voxel=(%.6f,%.6f,%.6f) status=PASS\n",
seed,static_cast<double>(chosen->radiusSubvoxels)/UnitsPerVoxel,
cameraVoxels.X,cameraVoxels.Y,cameraVoxels.Z);
}
else
{
const auto xSubvoxels=static_cast<std::int64_t>(std::llround(cameraVoxels.X*UnitsPerVoxel));
const auto ySubvoxels=static_cast<std::int64_t>(std::llround(cameraVoxels.Y*UnitsPerVoxel));
const auto currentZSubvoxels=static_cast<std::int64_t>(std::llround(cameraVoxels.Z*UnitsPerVoxel));
std::int64_t selectedGround=0,bestDistance=std::numeric_limits<std::int64_t>::max();
for(const auto& stratum:worldAssembly.plan.strates)
{
VoxelForgeCore::Heightfield2D field(worldAssembly.recipe,stratum);
if(!field.isValid())continue;
const auto column=field.point(xSubvoxels,ySubvoxels,0);
const std::int64_t distance=std::abs(column.groundHeightSubvoxels-currentZSubvoxels);
if(distance<bestDistance)
{bestDistance=distance;selectedGround=column.groundHeightSubvoxels;}
}
if(bestDistance==std::numeric_limits<std::int64_t>::max())
{std::fprintf(stderr,"[SeedSurfacePlacement] FAIL: no valid SurfaceWorld heightfield\n");return 2;}
cameraVoxels.Z=static_cast<float>(static_cast<double>(selectedGround)/UnitsPerVoxel);
std::printf("[SeedSurfacePlacement] recipe=surface-world seed=%d ground_voxel=%.6f camera_voxel=(%.6f,%.6f,%.6f) status=PASS\n",
seed,static_cast<double>(selectedGround)/UnitsPerVoxel,
cameraVoxels.X,cameraVoxels.Y,cameraVoxels.Z);
}
}
std::printf("[WorldAssemblerPlanTiming] total_ms=%.3f status=PASS\n",
std::chrono::duration<double,std::milli>(Clock::now()-planStart).count());
auto snapshot=VoxelForgeCore::MakeStandaloneSnapshotFromParsedJson(ownerJsonRoot,seed,
options.ClipRadius,options.MaxClipLevel,false,false,error);
if(!snapshot)
{std::fprintf(stderr,"Shape interval build failed: %s\n",error.c_str());return 2;}
FStandaloneCoreScheduler scheduler;
return StandaloneStreamBenchmark::RunPipelinedStreamingBenchmark(ownerWorld,snapshot,
cameraVoxels,options.WorkerCount,options.MaxLevel,VoxelForgeCore::DetailVariant::coherent,
scheduler,options.StreamHash,false,false,false,false,coldStart,
options.ProfileColumnOverlap,options.FarHorizonLOD8InteriorStepVoxels,
options.MeshCoverage,options.MeshExportPath,options.CameraYawDegrees,
options.CameraPitchDegrees,options.ScreenSpaceGate,options.VisualDetailCutoff);
}