#pragma once #include "OwnerWorldLoader.h" #include "StreamingWorld.h" #include "LinuxScreenSpaceGate.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace StandaloneStreamBenchmark { struct FSceneExportWriter { std::ofstream File; bool bGood=true; std::uint32_t TileCount=0; template void Write(const T& Value) { File.write(reinterpret_cast(&Value),sizeof(Value)); bGood=bGood&&static_cast(File); } bool Open(const std::filesystem::path& Path,std::uint32_t VoxelSizeMicrons, const FVector& CameraVoxels,float YawDegrees,float PitchDegrees, std::uint32_t ExpectedTiles) { std::error_code Error; if(!Path.parent_path().empty()) std::filesystem::create_directories(Path.parent_path(),Error); if(Error)return false; File.open(Path,std::ios::binary|std::ios::trunc); if(!File)return false; constexpr char Magic[8]={'V','F','M','S','H','0','0','1'}; File.write(Magic,sizeof(Magic)); const std::uint32_t Version=1; Write(Version);Write(VoxelSizeMicrons);Write(ExpectedTiles); const double MicronsToMeters=static_cast(VoxelSizeMicrons)/1000000.0; const double Camera[3]={CameraVoxels.X*MicronsToMeters, CameraVoxels.Y*MicronsToMeters,CameraVoxels.Z*MicronsToMeters}; for(const double Value:Camera)Write(Value); const double Yaw=YawDegrees,Pitch=PitchDegrees; Write(Yaw);Write(Pitch); return bGood; } void Add(const FStandaloneCpuTile& Tile) { const std::int32_t Key[4]={Tile.Key.Coord.X,Tile.Key.Coord.Y, Tile.Key.Coord.Z,Tile.Key.Level}; for(const auto Value:Key)Write(Value); const std::uint32_t SurfaceVertexCount=Tile.SurfaceVertexCount; const std::uint32_t SkirtTriangleCount=Tile.SkirtTriangleCount; const std::uint32_t VertexCount=static_cast(Tile.Vertices.size()); const std::uint32_t IndexCount=static_cast(Tile.Indices.size()); const std::uint32_t MaskCount=static_cast(Tile.TriangleSkirtFaceMasks.size()); Write(SurfaceVertexCount);Write(SkirtTriangleCount); Write(VertexCount);Write(IndexCount);Write(MaskCount); for(const FStandaloneCpuVertex& Vertex:Tile.Vertices) for(const float Value:Vertex.Position)Write(Value); for(const FStandaloneCpuVertex& Vertex:Tile.Vertices) for(const float Value:Vertex.Normal)Write(Value); if(IndexCount) File.write(reinterpret_cast(Tile.Indices.data()), static_cast(sizeof(std::uint32_t)*Tile.Indices.size())); if(MaskCount) File.write(reinterpret_cast(Tile.TriangleSkirtFaceMasks.data()), static_cast(Tile.TriangleSkirtFaceMasks.size())); bGood=bGood&&static_cast(File); ++TileCount; } bool Close(std::uint32_t ExpectedTiles) { File.flush(); const bool bComplete=bGood&&static_cast(File)&&TileCount==ExpectedTiles; File.close(); return bComplete; } }; inline void HashWord(uint64& Hash,uint64 Word,int32 Bytes=8) { for(int32 I=0;I(Word>>(I*8)); Hash*=1099511628211ull; } } struct FHashedTile { FVoxelTileKey Key; uint64 Hash=14695981039346656037ull; }; inline bool TileKeyLessForHash(const FVoxelTileKey& A,const FVoxelTileKey& B) { if(A.Level!=B.Level)return A.Level& Rows) { std::sort(Rows.begin(),Rows.end(),[](const FHashedTile& A,const FHashedTile& B) {return TileKeyLessForHash(A.Key,B.Key);}); uint64 Hash=14695981039346656037ull; for(const FHashedTile& Row:Rows) { HashWord(Hash,static_cast(Row.Key.Level),4); HashWord(Hash,static_cast(Row.Key.Coord.X),4); HashWord(Hash,static_cast(Row.Key.Coord.Y),4); HashWord(Hash,static_cast(Row.Key.Coord.Z),4); HashWord(Hash,Row.Hash); } return Hash; } inline int RunPipelinedStreamingBenchmark(std::shared_ptr OwnerWorld, const VoxelForgeCore::ResolvedWorldSnapshot& CoreSnapshot, const FVector& CameraPositionVoxels,int32 WorkerCount,int32 MaxLevel, VoxelForgeCore::DetailVariant DetailVariant,const VoxelForgeCore::JobScheduler& Scheduler, bool bHashDensity,bool bSkipUvAndColors,bool bSkipMaterialGroups,bool bSkipUV,bool bSkipColors, std::chrono::steady_clock::time_point ColdStart,bool bProfileColumnOverlap, int32 FarHorizonLOD8InteriorStepVoxels,bool bReportMeshCoverage=false, const std::filesystem::path& MeshExportPath={},float CameraYawDegrees=0.0f, float CameraPitchDegrees=0.0f,bool bScreenSpaceGate=false) { using Clock=std::chrono::steady_clock; FStandaloneOwnerWorld& World=*OwnerWorld; const VoxelForgeCore::WorldAssemblyManifest* Assembly=CoreSnapshot.worldAssembly(); std::array ClosestDisplayDistances{}; std::array PixelBudgetsSubvoxels{}; if(bScreenSpaceGate) { ClosestDisplayDistances=StandaloneScreenSpaceGate::ClosestDisplayedDistancesMeters( World,CameraPositionVoxels,World.CoreVoxelSizeMicrons); const double VoxelMeters=static_cast(World.CoreVoxelSizeMicrons)/1000000.0; for(int32 Lod=3;Lod<=World.MaxClipLevel&&Lod<9;++Lod) PixelBudgetsSubvoxels[static_cast(Lod)]=static_cast(std::floor( ClosestDisplayDistances[static_cast(Lod)] *StandaloneScreenSpaceGate::OnePixelRadians/VoxelMeters *VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel)); } const bool bRoundTunnels=World.Generator->bStandaloneResearchRoundTunnels; const bool bEnhancedTunnelWalls=World.Generator->bStandaloneResearchEnhancedWalls; VoxelForgeCore::World Shape(CoreSnapshot); FStandaloneDesiredTileSet Desired=StandaloneWorldMesher::BuildDesiredSet(World,CameraPositionVoxels); const auto CoreTiles=Shape.desiredTiles( {CameraPositionVoxels.X,CameraPositionVoxels.Y,CameraPositionVoxels.Z}); Desired.Tiles.clear();Desired.Tiles.reserve(CoreTiles.size()); for(const auto& Key:CoreTiles) Desired.Tiles.emplace_back(FIntVector(Key.coordinate.x,Key.coordinate.y,Key.coordinate.z),Key.lod); if(MaxLevel>=0) Desired.Tiles.erase(std::remove_if(Desired.Tiles.begin(),Desired.Tiles.end(), [&](const FVoxelTileKey& Tile){return Tile.Level>MaxLevel;}),Desired.Tiles.end()); if(!Desired.Tiles.empty()) { FIntVector volumeMin(INT32_MAX,INT32_MAX,INT32_MAX); FIntVector volumeMax(INT32_MIN,INT32_MIN,INT32_MIN); int32 minimumLod=INT32_MAX,maximumLod=INT32_MIN; for(const FVoxelTileKey& tile:Desired.Tiles) { const FIntVector origin=tile.OriginVoxels(); const int32 extent=tile.ExtentVoxels(); volumeMin.X=std::min(volumeMin.X,origin.X); volumeMin.Y=std::min(volumeMin.Y,origin.Y); volumeMin.Z=std::min(volumeMin.Z,origin.Z); volumeMax.X=std::max(volumeMax.X,origin.X+extent); volumeMax.Y=std::max(volumeMax.Y,origin.Y+extent); volumeMax.Z=std::max(volumeMax.Z,origin.Z+extent); minimumLod=std::min(minimumLod,tile.Level); maximumLod=std::max(maximumLod,tile.Level); } std::printf("[PipelineVolume] tiles=%zu lod=%d..%d min_voxel=(%d,%d,%d) max_voxel=(%d,%d,%d)\n", Desired.Tiles.size(),minimumLod,maximumLod,volumeMin.X,volumeMin.Y,volumeMin.Z, volumeMax.X,volumeMax.Y,volumeMax.Z); } FIntVector FineMin(INT32_MAX,INT32_MAX,INT32_MAX),FineMax(INT32_MIN,INT32_MIN,INT32_MIN); FIntVector ClipMin(INT32_MAX,INT32_MAX,INT32_MAX),ClipMax(INT32_MIN,INT32_MIN,INT32_MIN); for(const FVoxelTileKey& Tile:Desired.Tiles) { const FIntVector Origin=Tile.OriginVoxels();const int32 Extent=Tile.ExtentVoxels(); ClipMin.X=std::min(ClipMin.X,Origin.X);ClipMin.Y=std::min(ClipMin.Y,Origin.Y);ClipMin.Z=std::min(ClipMin.Z,Origin.Z); ClipMax.X=std::max(ClipMax.X,Origin.X+Extent);ClipMax.Y=std::max(ClipMax.Y,Origin.Y+Extent);ClipMax.Z=std::max(ClipMax.Z,Origin.Z+Extent); if(Tile.Level Neighborhood; Neighborhood.reserve(32); for(const FVoxelTileKey& Tile:Desired.Tiles) if(Tile.Level==0&&std::abs(Tile.Coord.X-CenterChunk.X)<=1 &&std::abs(Tile.Coord.Y-CenterChunk.Y)<=1&&std::abs(Tile.Coord.Z-CenterChunk.Z)<=1) Neighborhood.insert(Tile); if(Neighborhood.size()!=27) {std::fprintf(stderr,"[StreamPipeline] expected 27 player-neighborhood tiles, found %zu.\n",Neighborhood.size());return 7;} // The initial desired set now owns all clipmap metadata needed by this Core-only run. // Release the separate compatibility-world generation graph before compiling Core. World.Generator.reset(); World.Manager.reset(); World.DefinitionStorage.clear(); World.BiomeStorage.clear(); World.OperationStorage.clear(); World.DensitySamples.clear(); std::string BuildError; const bool bIncludeFarWorld=MaxLevel<0||MaxLevel>=World.FullResClipLevels; const auto ShapeBuildStart=Clock::now(); VoxelForgeCore::ShapeBuildRequest ShapeRequest; ShapeRequest.minVoxel={FineMin.X,FineMin.Y,FineMin.Z}; ShapeRequest.maxVoxel={FineMax.X,FineMax.Y,FineMax.Z}; ShapeRequest.clipMinVoxel={ClipMin.X,ClipMin.Y,ClipMin.Z}; ShapeRequest.clipMaxVoxel={ClipMax.X,ClipMax.Y,ClipMax.Z}; ShapeRequest.workerLimit=static_cast(std::clamp(WorkerCount,1,16)); ShapeRequest.detail=DetailVariant;ShapeRequest.includeFarWorld=bIncludeFarWorld; ShapeRequest.roundTunnels=bRoundTunnels; ShapeRequest.enhancedTunnelWalls=bEnhancedTunnelWalls; if(!Shape.compile(ShapeRequest,Scheduler,BuildError)) {std::fprintf(stderr,"[StreamPipeline] full shape build failed: %s\n",BuildError.c_str());return 2;} const auto ShapeReady=Clock::now(); const double ShapeSeconds=std::chrono::duration(ShapeReady-ShapeBuildStart).count(); FStandaloneStreamingGenerator Streamer(World,WorkerCount,bHashDensity,nullptr,MaxLevel, bSkipUvAndColors,bSkipMaterialGroups,bSkipUV,bSkipColors,&Shape,bProfileColumnOverlap, FarHorizonLOD8InteriorStepVoxels); if(bScreenSpaceGate)Streamer.SetMesherStageProfilingEnabled(true); const auto StreamStart=Clock::now(); const FStandaloneStreamingUpdate Update=Streamer.StartWithDesired(Desired); if(Update.DesiredTiles!=static_cast(Desired.Tiles.size())) { Streamer.Stop(); std::fprintf(stderr,"[StreamPipeline] expected %zu tiles but queued %d.\n", Desired.Tiles.size(),Update.DesiredTiles);return 7; } FSceneExportWriter SceneExport; const bool bExportRequested=!MeshExportPath.empty(); bool bSceneExportPassing=true; if(bExportRequested) { bSceneExportPassing=SceneExport.Open(MeshExportPath,World.CoreVoxelSizeMicrons, CameraPositionVoxels,CameraYawDegrees,CameraPitchDegrees, static_cast(Update.DesiredTiles)); if(!bSceneExportPassing) { Streamer.Stop(); std::fprintf(stderr,"[MeshSceneExport] FAIL: could not open %s\n", MeshExportPath.string().c_str()); return 8; } } std::vector DensityRows,MeshRows,PayloadRows,TopologyRows; int32 Finished=0,NeighborhoodFinished=0,FullDetailFinished=0; int32 FullDetailExpected=0; uint64 WholeNonEmptyMeshTiles=0,WholeTriangleCount=0; struct FColumnXY { std::int64_t X=0,Y=0; bool operator==(const FColumnXY&)const=default; }; struct FColumnXYHash { std::size_t operator()(const FColumnXY& Value)const noexcept { const std::size_t X=std::hash{}(Value.X); const std::size_t Y=std::hash{}(Value.Y); return X^(Y+static_cast(0x9E3779B9u)+(X<<6)+(X>>2)); } }; struct FFirstColumnUse { FVoxelTileKey Tile; std::uint64_t WorkerHash=0; }; std::array,FColumnXYHash>,9> ColumnUsesByLOD; std::array ColumnDuplicateEventsByLOD{},NeighbourDuplicateEventsByLOD{}; std::array CrossWorkerNeighbourDuplicateEventsByLOD{}; std::array ColumnCaptureTilesByLOD{},ExpectedTilesByLOD{}; std::array ColumnCaptureCompleteByLOD{}; ColumnCaptureCompleteByLOD.fill(true); std::array WorkerSecondsByLOD{}; std::array ColumnEvalMsByLOD{},MarchingExclusiveMsByLOD{}; std::array GroundRefineExclusiveMsByLOD{},CapRefineExclusiveMsByLOD{}; std::array MeshAssemblyMsByLOD{}; std::array SkirtMsByLOD{}; std::array SkirtTrianglesByLOD{}; std::array TileCountByLOD{}; for(const FVoxelTileKey& Tile:Desired.Tiles) if(Tile.Level>=0&&Tile.Level(ExpectedTilesByLOD.size())) ++ExpectedTilesByLOD[static_cast(Tile.Level)]; const auto AreSameLODNeighbours=[](const FVoxelTileKey& A,const FVoxelTileKey& B) { if(A.Level!=B.Level)return false; const std::int64_t DX=std::abs(static_cast(A.Coord.X)-B.Coord.X); const std::int64_t DY=std::abs(static_cast(A.Coord.Y)-B.Coord.Y); const std::int64_t DZ=std::abs(static_cast(A.Coord.Z)-B.Coord.Z); return std::max({DX,DY,DZ})<=1&&(DX+DY+DZ)>0; }; uint64 NativeSolidBoxes=0,NativeAirBoxes=0,NativeMixedBoxes=0,NativeUnknownBoxes=0; uint64 NativeFieldCalls=0,NativeColumnHits=0,NativeColumnMisses=0,NativeMeshingSkips=0; double NativeClassificationMilliseconds=0.0,NativeColumnComputeMilliseconds=0.0; double NativeMeshingMilliseconds=0.0; for(const FVoxelTileKey& Tile:Desired.Tiles) if(Tile.Level,9> GateSampleTiles{}; std::array GateSampleDistances{}; GateSampleDistances.fill(std::numeric_limits::infinity()); Clock::time_point NeighborhoodReady{},FullDetailReady{},WholeViewReady{}; bool bNeighborhoodReported=false,bFullDetailReported=false; while(Finished Ready=Streamer.TakeReady(); if(Ready.empty()){std::this_thread::sleep_for(std::chrono::milliseconds(1));continue;} for(const FStandaloneCpuTile& Tile:Ready) { if(bExportRequested)SceneExport.Add(Tile); ++Finished; if(bReportMeshCoverage) { const uint64 TileTriangleCount=static_cast(Tile.Indices.size()/3); WholeTriangleCount+=TileTriangleCount; if(TileTriangleCount>0)++WholeNonEmptyMeshTiles; } if(Tile.Key.Level>=0&&Tile.Key.Level(TileCountByLOD.size())) { const std::size_t LOD=static_cast(Tile.Key.Level); ++TileCountByLOD[LOD]; WorkerSecondsByLOD[LOD]+=Tile.WorkerSeconds; ColumnEvalMsByLOD[LOD]+=Tile.CoreDiagnostics.columnEvaluationExclusiveMilliseconds; MarchingExclusiveMsByLOD[LOD]+=Tile.CoreDiagnostics.marchingCubesExclusiveMilliseconds; GroundRefineExclusiveMsByLOD[LOD]+=Tile.CoreDiagnostics.groundRefinementExclusiveMilliseconds; CapRefineExclusiveMsByLOD[LOD]+=Tile.CoreDiagnostics.capRefinementExclusiveMilliseconds; MeshAssemblyMsByLOD[LOD]+=Tile.CoreDiagnostics.meshAssemblyMilliseconds; SkirtMsByLOD[LOD]+=Tile.CoreDiagnostics.marchingCubesSkirtMilliseconds; SkirtTrianglesByLOD[LOD]+=Tile.SkirtTriangleCount; if(bScreenSpaceGate&&Assembly&&Tile.Key.Level>=3&&Tile.Key.Level<9 &&!Tile.Vertices.empty() &&StandaloneScreenSpaceGate::TileHasNativeSurface(Tile.Key,*Assembly, static_cast(World.CoreVoxelSizeMicrons)/1000000.0)) { const double Distance=StandaloneScreenSpaceGate::TileAabbDistanceMeters( Tile.Key,CameraPositionVoxels, static_cast(World.CoreVoxelSizeMicrons)/1000000.0); const bool bCloser=DistanceKey); if(bCloser||(bTied&&bKeyLess)) {GateSampleDistances[LOD]=Distance;GateSampleTiles[LOD]=Tile;} } } if(bProfileColumnOverlap&&Tile.Key.Level>=0 &&Tile.Key.Level(ColumnCaptureTilesByLOD.size())) { const std::size_t LOD=static_cast(Tile.Key.Level); ++ColumnCaptureTilesByLOD[LOD]; ColumnCaptureCompleteByLOD[LOD]=ColumnCaptureCompleteByLOD[LOD] &&Tile.CoreDiagnostics.columnCoordinateCaptureComplete; std::vector> Coordinates= Tile.CoreDiagnostics.evaluatedColumnCoordinates; std::sort(Coordinates.begin(),Coordinates.end()); Coordinates.erase(std::unique(Coordinates.begin(),Coordinates.end()),Coordinates.end()); for(const auto& Coordinate:Coordinates) { const FColumnXY XY{Coordinate[0],Coordinate[1]}; auto [Uses,Inserted]=ColumnUsesByLOD[LOD].try_emplace(XY); std::vector& PriorUses=Uses->second; if(Inserted) { PriorUses.push_back({Tile.Key,Tile.CoreDiagnostics.columnEvaluationWorkerHash}); continue; } ++ColumnDuplicateEventsByLOD[LOD]; bool bHasNeighbourDuplicate=false,bHasCrossWorkerNeighbourDuplicate=false; for(const FFirstColumnUse& Prior:PriorUses) { if(!AreSameLODNeighbours(Prior.Tile,Tile.Key))continue; bHasNeighbourDuplicate=true; bHasCrossWorkerNeighbourDuplicate=bHasCrossWorkerNeighbourDuplicate ||Prior.WorkerHash!=Tile.CoreDiagnostics.columnEvaluationWorkerHash; } if(bHasNeighbourDuplicate)++NeighbourDuplicateEventsByLOD[LOD]; if(bHasCrossWorkerNeighbourDuplicate) ++CrossWorkerNeighbourDuplicateEventsByLOD[LOD]; PriorUses.push_back({Tile.Key,Tile.CoreDiagnostics.columnEvaluationWorkerHash}); } } WholeViewReady=std::max(WholeViewReady,Tile.CompletedAt); if(Neighborhood.contains(Tile.Key)) { ++NeighborhoodFinished; NeighborhoodReady=std::max(NeighborhoodReady,Tile.CompletedAt); } if(Tile.Key.Level(Neighborhood.size())) { std::printf("[PipelineMilestone] neighborhood_ready=%.3fs generated=%d/27\n", std::chrono::duration(NeighborhoodReady-ColdStart).count(),NeighborhoodFinished); bNeighborhoodReported=true; } if(!bFullDetailReported&&FullDetailFinished==FullDetailExpected) { std::printf("[PipelineMilestone] full_detail_ready=%.3fs generated=%d/%d\n", std::chrono::duration(FullDetailReady-ColdStart).count(), FullDetailFinished,FullDetailExpected); bFullDetailReported=true; } } Streamer.Stop(); bool bScreenSpaceGatePassing=true; if(bScreenSpaceGate) { if(Assembly) bScreenSpaceGatePassing=StandaloneScreenSpaceGate::Run(GateSampleTiles, Streamer,*Assembly,ClosestDisplayDistances,World.CoreVoxelSizeMicrons, World.MaxClipLevel,PixelBudgetsSubvoxels,CameraYawDegrees, CameraPitchDegrees); else {std::fprintf(stderr,"[ScreenSpaceGateResult] no-world-assembly status=REJECT\n");bScreenSpaceGatePassing=false;} } if(bExportRequested) { bSceneExportPassing=SceneExport.Close(static_cast(Update.DesiredTiles)); std::error_code FileSizeError; const std::uintmax_t ExportBytes=std::filesystem::file_size(MeshExportPath,FileSizeError); std::printf("[MeshSceneExport] tiles=%u expected=%d bytes=%llu status=%s path=%s\n", SceneExport.TileCount,Update.DesiredTiles, static_cast(FileSizeError?0:ExportBytes), bSceneExportPassing?"PASS":"FAIL",MeshExportPath.string().c_str()); bSceneExportPassing=bSceneExportPassing&&!FileSizeError; } bool bColumnOverlapCapturePassing=true; if(bProfileColumnOverlap) { for(std::size_t LOD=0;LOD(ColumnCaptureTilesByLOD[LOD]), static_cast(ExpectedTilesByLOD[LOD]), ColumnUsesByLOD[LOD].size(), static_cast(ColumnDuplicateEventsByLOD[LOD]), static_cast(NeighbourDuplicateEventsByLOD[LOD]), static_cast(CrossWorkerNeighbourDuplicateEventsByLOD[LOD]), bLODComplete?1:0); } } for(std::size_t LOD=0;LOD(TileCountByLOD[LOD]),WorkerSecondsByLOD[LOD], ColumnEvalMsByLOD[LOD],MarchingExclusiveMsByLOD[LOD], GroundRefineExclusiveMsByLOD[LOD],CapRefineExclusiveMsByLOD[LOD], SkirtMsByLOD[LOD],static_cast(SkirtTrianglesByLOD[LOD]), MeshAssemblyMsByLOD[LOD]); } const double NeighborhoodSeconds=std::chrono::duration(NeighborhoodReady-ColdStart).count(); const double NeighborhoodMeshSeconds=std::chrono::duration(NeighborhoodReady-ShapeReady).count(); const double FullDetailSeconds=std::chrono::duration(FullDetailReady-ColdStart).count(); const double WholeViewSeconds=std::chrono::duration(WholeViewReady-ColdStart).count(); const double StreamSeconds=std::chrono::duration(WholeViewReady-StreamStart).count(); std::printf("[StreamPipeline] workers=%d shape=%.3fs neighborhood_mesh=%.3fs neighborhood_ready=%.3fs full_detail_ready=%.3fs whole_view_ready=%.3fs neighborhood_tiles=%d/27 full_detail_tiles=%d/%d whole_tiles=%d/%zu stream_wall=%.3fs cache_hits=0 full_payload=1\n", WorkerCount,ShapeSeconds,NeighborhoodMeshSeconds,NeighborhoodSeconds, FullDetailSeconds,WholeViewSeconds,NeighborhoodFinished, FullDetailFinished,FullDetailExpected,Finished,Desired.Tiles.size(),StreamSeconds); if(bReportMeshCoverage) std::printf("[PipelineMeshCoverage] tiles=%d nonempty_mesh_tiles=%llu indexed_triangles=%llu\n", Finished,static_cast(WholeNonEmptyMeshTiles), static_cast(WholeTriangleCount)); std::printf("[WorldAssemblerTilePipeline] full_detail_tiles=%d solid_boxes=%llu air_boxes=%llu mixed_boxes=%llu unknown_boxes=%llu whole_tile_skips=%llu field_calls=%llu column_cache_hits=%llu column_cache_misses=%llu column_compute_worker_ms=%.3f classification_worker_ms=%.3f meshing_worker_ms=%.3f\n", FullDetailExpected,static_cast(NativeSolidBoxes), static_cast(NativeAirBoxes), static_cast(NativeMixedBoxes), static_cast(NativeUnknownBoxes), static_cast(NativeMeshingSkips), static_cast(NativeFieldCalls), static_cast(NativeColumnHits), static_cast(NativeColumnMisses), NativeColumnComputeMilliseconds,NativeClassificationMilliseconds, NativeMeshingMilliseconds); bool bHashesPassing=true; if(bHashDensity) { bHashesPassing=DensityRows.size()==Desired.Tiles.size() &&MeshRows.size()==Desired.Tiles.size() &&PayloadRows.size()==Desired.Tiles.size() &&TopologyRows.size()==Desired.Tiles.size(); std::vector FullDensity,FullMesh,FullPayload,FullTopology; for(const FHashedTile& Row:DensityRows)if(Row.Key.Level(HashTileRows(FullDensity)), static_cast(HashTileRows(FullMesh)), static_cast(HashTileRows(FullPayload)), static_cast(HashTileRows(FullTopology))); std::printf("[PipelineWholeViewHash] tiles=%zu density=0x%016llx mesh=0x%016llx payload=0x%016llx topology=0x%016llx\n", Desired.Tiles.size(),static_cast(HashTileRows(DensityRows)), static_cast(HashTileRows(MeshRows)), static_cast(HashTileRows(PayloadRows)), static_cast(HashTileRows(TopologyRows))); for(std::size_t LOD=0;LOD& Rows) { std::vector Selected; for(const FHashedTile& Row:Rows) if(Row.Key.Level==static_cast(LOD))Selected.push_back(Row); return Selected; }; auto LodDensity=FilterLOD(DensityRows),LodMesh=FilterLOD(MeshRows); auto LodPayload=FilterLOD(PayloadRows),LodTopology=FilterLOD(TopologyRows); std::printf("[PipelineLODHash] lod=%zu tiles=%llu density=0x%016llx mesh=0x%016llx payload=0x%016llx topology=0x%016llx\n", LOD,static_cast(TileCountByLOD[LOD]), static_cast(HashTileRows(LodDensity)), static_cast(HashTileRows(LodMesh)), static_cast(HashTileRows(LodPayload)), static_cast(HashTileRows(LodTopology))); } const std::array QueryPoints={{ {CameraPositionVoxels.X,CameraPositionVoxels.Y,CameraPositionVoxels.Z}, {CameraPositionVoxels.X+8.0,CameraPositionVoxels.Y,CameraPositionVoxels.Z}, {CameraPositionVoxels.X-8.0,CameraPositionVoxels.Y,CameraPositionVoxels.Z}, {CameraPositionVoxels.X,CameraPositionVoxels.Y+8.0,CameraPositionVoxels.Z}, {CameraPositionVoxels.X,CameraPositionVoxels.Y-8.0,CameraPositionVoxels.Z}, {CameraPositionVoxels.X,CameraPositionVoxels.Y,CameraPositionVoxels.Z+8.0}, {CameraPositionVoxels.X,CameraPositionVoxels.Y,CameraPositionVoxels.Z-8.0}, {CameraPositionVoxels.X+64.0,CameraPositionVoxels.Y-32.0,CameraPositionVoxels.Z+16.0}, {CameraPositionVoxels.X-128.0,CameraPositionVoxels.Y+96.0,CameraPositionVoxels.Z-64.0}}}; uint64 ExactDensityHash=14695981039346656037ull; uint64 ExactUnclampedHash=14695981039346656037ull; uint64 ExactDetailHash=14695981039346656037ull; uint64 ExactCollisionHash=14695981039346656037ull; for(const auto& Point:QueryPoints) { const float Density=Shape.densityAt(Point); const float Unclamped=Shape.unclampedDensityAt(Point); const auto Detail=Shape.detailSampleAt(Point); HashWord(ExactDensityHash,std::bit_cast(Density),4); HashWord(ExactUnclampedHash,std::bit_cast(Unclamped),4); HashWord(ExactDetailHash,std::bit_cast(Detail.displacement),4); HashWord(ExactDetailHash,std::bit_cast(Detail.caveInfluence),4); HashWord(ExactDetailHash,std::bit_cast(Detail.floorInfluence),4); HashWord(ExactCollisionHash,Shape.isSolidAt(Point)?1u:0u,1); } std::printf("[PipelineExactQueryHash] probes=%zu density=0x%016llx unclamped=0x%016llx detail=0x%016llx collision=0x%016llx path=direct-Core-queries\n", QueryPoints.size(),static_cast(ExactDensityHash), static_cast(ExactUnclampedHash), static_cast(ExactDetailHash), static_cast(ExactCollisionHash)); } return NeighborhoodFinished==static_cast(Neighborhood.size()) &&FullDetailFinished==FullDetailExpected&&Finished==Update.DesiredTiles&&bHashesPassing &&(!bProfileColumnOverlap||bColumnOverlapCapturePassing) &&(!bExportRequested||bSceneExportPassing)&&bScreenSpaceGatePassing?0:6; } } // namespace StandaloneStreamBenchmark