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
This commit is contained in:
1 parent
7770074503
commit
b21a19d561
33 files changed
+1977
-26
No files matched your search
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "OwnerWorldLoader.h"
|
||||
#include "StreamingWorld.h"
|
||||
#include "LinuxScreenSpaceGate.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
@@ -9,6 +10,8 @@
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
@@ -17,6 +20,76 @@
|
||||
|
||||
namespace StandaloneStreamBenchmark
|
||||
{
|
||||
struct FSceneExportWriter
|
||||
{
|
||||
std::ofstream File;
|
||||
bool bGood=true;
|
||||
std::uint32_t TileCount=0;
|
||||
|
||||
template<typename T> void Write(const T& Value)
|
||||
{
|
||||
File.write(reinterpret_cast<const char*>(&Value),sizeof(Value));
|
||||
bGood=bGood&&static_cast<bool>(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<double>(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<std::uint32_t>(Tile.Vertices.size());
|
||||
const std::uint32_t IndexCount=static_cast<std::uint32_t>(Tile.Indices.size());
|
||||
const std::uint32_t MaskCount=static_cast<std::uint32_t>(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<const char*>(Tile.Indices.data()),
|
||||
static_cast<std::streamsize>(sizeof(std::uint32_t)*Tile.Indices.size()));
|
||||
if(MaskCount)
|
||||
File.write(reinterpret_cast<const char*>(Tile.TriangleSkirtFaceMasks.data()),
|
||||
static_cast<std::streamsize>(Tile.TriangleSkirtFaceMasks.size()));
|
||||
bGood=bGood&&static_cast<bool>(File);
|
||||
++TileCount;
|
||||
}
|
||||
|
||||
bool Close(std::uint32_t ExpectedTiles)
|
||||
{
|
||||
File.flush();
|
||||
const bool bComplete=bGood&&static_cast<bool>(File)&&TileCount==ExpectedTiles;
|
||||
File.close();
|
||||
return bComplete;
|
||||
}
|
||||
};
|
||||
|
||||
inline void HashWord(uint64& Hash,uint64 Word,int32 Bytes=8)
|
||||
{
|
||||
for(int32 I=0;I<Bytes;++I)
|
||||
@@ -62,10 +135,92 @@ namespace StandaloneStreamBenchmark
|
||||
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)
|
||||
int32 FarHorizonLOD8InteriorStepVoxels,bool bReportMeshCoverage=false,
|
||||
const std::filesystem::path& MeshExportPath={},float CameraYawDegrees=0.0f,
|
||||
float CameraPitchDegrees=0.0f,bool bScreenSpaceGate=false,
|
||||
bool bApplyVisualDetailCutoff=false)
|
||||
{
|
||||
using Clock=std::chrono::steady_clock;
|
||||
FStandaloneOwnerWorld& World=*OwnerWorld;
|
||||
const VoxelForgeCore::WorldAssemblyManifest* Assembly=CoreSnapshot.worldAssembly();
|
||||
std::array<double,9> ClosestDisplayDistances{};
|
||||
std::array<std::int64_t,9> PixelBudgetsSubvoxels{};
|
||||
std::array<std::int64_t,9> AppliedPixelBudgetsSubvoxels{};
|
||||
if(bScreenSpaceGate||bApplyVisualDetailCutoff)
|
||||
{
|
||||
ClosestDisplayDistances=bScreenSpaceGate
|
||||
?StandaloneScreenSpaceGate::ClosestDisplayedDistancesMeters(
|
||||
World,CameraPositionVoxels,World.CoreVoxelSizeMicrons)
|
||||
:StandaloneScreenSpaceGate::ClipmapClosestDisplayedDistancesMeters(
|
||||
World,World.CoreVoxelSizeMicrons);
|
||||
const double VoxelMeters=static_cast<double>(World.CoreVoxelSizeMicrons)/1000000.0;
|
||||
for(int32 Lod=3;Lod<=World.MaxClipLevel&&Lod<9;++Lod)
|
||||
PixelBudgetsSubvoxels[static_cast<std::size_t>(Lod)]=static_cast<std::int64_t>(std::floor(
|
||||
ClosestDisplayDistances[static_cast<std::size_t>(Lod)]
|
||||
*StandaloneScreenSpaceGate::OnePixelRadians/VoxelMeters
|
||||
*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel));
|
||||
}
|
||||
AppliedPixelBudgetsSubvoxels=PixelBudgetsSubvoxels;
|
||||
if(Assembly&&(bScreenSpaceGate||bApplyVisualDetailCutoff))
|
||||
{
|
||||
for(int32 Lod=3;Lod<=World.MaxClipLevel&&Lod<9;++Lod)
|
||||
{
|
||||
const std::int32_t Cells=FMath::Max(1,World.CoarseTileCells);
|
||||
const std::int32_t Step=FMath::Max(1,(CHUNK_SIZE<<Lod)/Cells);
|
||||
VoxelForgeCore::VisualDetailCutoffV1 Probe;
|
||||
Probe.pixelBudgetSubvoxels=PixelBudgetsSubvoxels[static_cast<std::size_t>(Lod)];
|
||||
Probe.sampleStepSubvoxels=static_cast<std::int64_t>(Step)
|
||||
*VoxelForgeCore::WorldAssemblySubvoxelsPerVoxel;
|
||||
std::uint64_t TermCount=0,EligibleTermCount=0,PotentialSkippedOctaves=0;
|
||||
for(const auto& Plan:Assembly->plan.strates)
|
||||
{
|
||||
const VoxelForgeCore::Heightfield2D Field(Assembly->recipe,Plan);
|
||||
for(const auto& Term:Field.visualDetailContract().terms)
|
||||
{
|
||||
++TermCount;
|
||||
const auto Result=VoxelForgeCore::FindVisualDetailTailCutoffV1(Term,Probe);
|
||||
if(Result.firstSkippedOctave==0)continue;
|
||||
++EligibleTermCount;
|
||||
PotentialSkippedOctaves+=Term.octaveCount-Result.firstSkippedOctave;
|
||||
}
|
||||
}
|
||||
std::printf("[WorldAssemblerVisualDetailCutoffPlan] lod=%d terms=%llu eligible_terms=%llu potential_skipped_octaves=%llu per_call_budget_divisor=%u sample_step_vox=%d status=%s\n",
|
||||
Lod,static_cast<unsigned long long>(TermCount),
|
||||
static_cast<unsigned long long>(EligibleTermCount),
|
||||
static_cast<unsigned long long>(PotentialSkippedOctaves),
|
||||
Probe.callBudgetDivisor,Step,
|
||||
EligibleTermCount==0?"exact-no-eligible-tail":"candidate");
|
||||
if(bApplyVisualDetailCutoff&&EligibleTermCount==0)
|
||||
AppliedPixelBudgetsSubvoxels[static_cast<std::size_t>(Lod)]=0;
|
||||
}
|
||||
}
|
||||
if(bScreenSpaceGate&&Assembly)
|
||||
{
|
||||
for(const auto& Plan:Assembly->plan.strates)
|
||||
{
|
||||
const VoxelForgeCore::Heightfield2D Field(Assembly->recipe,Plan);
|
||||
for(const auto& Term:Field.visualDetailContract().terms)
|
||||
for(std::uint32_t Octave=0;Octave<Term.octaveCount;++Octave)
|
||||
{
|
||||
const std::int64_t Wavelength=Term.baseWavelengthSubvoxels
|
||||
/static_cast<std::int64_t>(1ull<<Octave);
|
||||
const long double Amplitude=static_cast<long double>(Term.maximumDisplacementSubvoxels)
|
||||
*Term.maximumNoiseAbsQ16/65536.0L
|
||||
/static_cast<long double>(1ull<<Octave);
|
||||
std::printf("[WorldAssemblerVisualDetailTerm] stratum=%d id=%llu octave=%u wavelength_vox=%.3f max_abs_surface_vox=%.3f declared=1\n",
|
||||
Plan.strateIndex,static_cast<unsigned long long>(Term.stableId),Octave,
|
||||
static_cast<double>(Wavelength)/256.0,static_cast<double>(Amplitude));
|
||||
}
|
||||
}
|
||||
for(const auto& Island:Assembly->floatingIslands)
|
||||
{
|
||||
const VoxelForgeCore::FloatingIslandFieldV1 Field(
|
||||
Island.manifest.recipe,Island.manifest.plan);
|
||||
const auto Contract=Field.visualDetailContract();
|
||||
std::printf("[WorldAssemblerVisualDetailContract] recipe=floating-islands strate=%d declared_terms=%zu exact_path=%d\n",
|
||||
Island.strateIndex,Contract.terms.size(),Contract.terms.empty()?1:0);
|
||||
}
|
||||
}
|
||||
const bool bRoundTunnels=World.Generator->bStandaloneResearchRoundTunnels;
|
||||
const bool bEnhancedTunnelWalls=World.Generator->bStandaloneResearchEnhancedWalls;
|
||||
VoxelForgeCore::World Shape(CoreSnapshot);
|
||||
@@ -154,6 +309,12 @@ namespace StandaloneStreamBenchmark
|
||||
FStandaloneStreamingGenerator Streamer(World,WorkerCount,bHashDensity,nullptr,MaxLevel,
|
||||
bSkipUvAndColors,bSkipMaterialGroups,bSkipUV,bSkipColors,&Shape,bProfileColumnOverlap,
|
||||
FarHorizonLOD8InteriorStepVoxels);
|
||||
if(bScreenSpaceGate||bApplyVisualDetailCutoff)
|
||||
{
|
||||
Streamer.SetVisualDetailCutoffBudgets(AppliedPixelBudgetsSubvoxels,
|
||||
bApplyVisualDetailCutoff);
|
||||
Streamer.SetVisualDetailProfilingEnabled(bScreenSpaceGate);
|
||||
}
|
||||
const auto StreamStart=Clock::now();
|
||||
const FStandaloneStreamingUpdate Update=Streamer.StartWithDesired(Desired);
|
||||
if(Update.DesiredTiles!=static_cast<int32>(Desired.Tiles.size()))
|
||||
@@ -162,6 +323,22 @@ namespace StandaloneStreamBenchmark
|
||||
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<std::uint32_t>(Update.DesiredTiles));
|
||||
if(!bSceneExportPassing)
|
||||
{
|
||||
Streamer.Stop();
|
||||
std::fprintf(stderr,"[MeshSceneExport] FAIL: could not open %s\n",
|
||||
MeshExportPath.string().c_str());
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<FHashedTile> DensityRows,MeshRows,PayloadRows,TopologyRows;
|
||||
int32 Finished=0,NeighborhoodFinished=0,FullDetailFinished=0;
|
||||
@@ -193,6 +370,11 @@ namespace StandaloneStreamBenchmark
|
||||
std::array<bool,9> ColumnCaptureCompleteByLOD{};
|
||||
ColumnCaptureCompleteByLOD.fill(true);
|
||||
std::array<double,9> WorkerSecondsByLOD{};
|
||||
std::array<std::array<std::uint64_t,8>,9> DetailOctaveEvaluationsByLOD{};
|
||||
std::array<std::array<std::uint64_t,8>,9> DetailOctaveEligibleByLOD{};
|
||||
std::array<std::array<std::uint64_t,8>,9> DetailOctaveSkipsByLOD{};
|
||||
std::array<std::array<double,8>,9> DetailOctaveMillisecondsByLOD{};
|
||||
std::array<std::array<double,8>,9> DetailOctaveEligibleMillisecondsByLOD{};
|
||||
std::array<double,9> ColumnEvalMsByLOD{},MarchingExclusiveMsByLOD{};
|
||||
std::array<double,9> GroundRefineExclusiveMsByLOD{},CapRefineExclusiveMsByLOD{};
|
||||
std::array<double,9> MeshAssemblyMsByLOD{};
|
||||
@@ -214,6 +396,9 @@ namespace StandaloneStreamBenchmark
|
||||
double NativeMeshingMilliseconds=0.0;
|
||||
for(const FVoxelTileKey& Tile:Desired.Tiles)
|
||||
if(Tile.Level<World.FullResClipLevels)++FullDetailExpected;
|
||||
std::array<std::optional<FStandaloneCpuTile>,9> GateSampleTiles{};
|
||||
std::array<double,9> GateSampleDistances{};
|
||||
GateSampleDistances.fill(std::numeric_limits<double>::infinity());
|
||||
Clock::time_point NeighborhoodReady{},FullDetailReady{},WholeViewReady{};
|
||||
bool bNeighborhoodReported=false,bFullDetailReported=false;
|
||||
while(Finished<Update.DesiredTiles)
|
||||
@@ -222,6 +407,7 @@ namespace StandaloneStreamBenchmark
|
||||
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)
|
||||
{
|
||||
@@ -239,6 +425,34 @@ namespace StandaloneStreamBenchmark
|
||||
GroundRefineExclusiveMsByLOD[LOD]+=Tile.CoreDiagnostics.groundRefinementExclusiveMilliseconds;
|
||||
CapRefineExclusiveMsByLOD[LOD]+=Tile.CoreDiagnostics.capRefinementExclusiveMilliseconds;
|
||||
MeshAssemblyMsByLOD[LOD]+=Tile.CoreDiagnostics.meshAssemblyMilliseconds;
|
||||
for(std::size_t Octave=0;Octave<8;++Octave)
|
||||
{
|
||||
DetailOctaveEvaluationsByLOD[LOD][Octave]+=
|
||||
Tile.CoreDiagnostics.visualDetailOctaveEvaluations[Octave];
|
||||
DetailOctaveEligibleByLOD[LOD][Octave]+=
|
||||
Tile.CoreDiagnostics.visualDetailOctaveBudgetEligible[Octave];
|
||||
DetailOctaveSkipsByLOD[LOD][Octave]+=
|
||||
Tile.CoreDiagnostics.visualDetailOctaveSkips[Octave];
|
||||
DetailOctaveMillisecondsByLOD[LOD][Octave]+=
|
||||
Tile.CoreDiagnostics.visualDetailOctaveMilliseconds[Octave];
|
||||
DetailOctaveEligibleMillisecondsByLOD[LOD][Octave]+=
|
||||
Tile.CoreDiagnostics.visualDetailOctaveEligibleMilliseconds[Octave];
|
||||
}
|
||||
if(bScreenSpaceGate&&Assembly&&Tile.Key.Level>=3&&Tile.Key.Level<9
|
||||
&&!Tile.Vertices.empty()
|
||||
&&StandaloneScreenSpaceGate::TileHasNativeSurface(Tile.Key,*Assembly,
|
||||
static_cast<double>(World.CoreVoxelSizeMicrons)/1000000.0))
|
||||
{
|
||||
const double Distance=StandaloneScreenSpaceGate::TileAabbDistanceMeters(
|
||||
Tile.Key,CameraPositionVoxels,
|
||||
static_cast<double>(World.CoreVoxelSizeMicrons)/1000000.0);
|
||||
const bool bCloser=Distance<GateSampleDistances[LOD]-1e-9;
|
||||
const bool bTied=std::abs(Distance-GateSampleDistances[LOD])<=1e-9;
|
||||
const bool bKeyLess=!GateSampleTiles[LOD]
|
||||
||TileKeyLessForHash(Tile.Key,GateSampleTiles[LOD]->Key);
|
||||
if(bCloser||(bTied&&bKeyLess))
|
||||
{GateSampleDistances[LOD]=Distance;GateSampleTiles[LOD]=Tile;}
|
||||
}
|
||||
}
|
||||
if(bProfileColumnOverlap&&Tile.Key.Level>=0
|
||||
&&Tile.Key.Level<static_cast<int32>(ColumnCaptureTilesByLOD.size()))
|
||||
@@ -321,6 +535,27 @@ namespace StandaloneStreamBenchmark
|
||||
}
|
||||
}
|
||||
Streamer.Stop();
|
||||
bool bScreenSpaceGatePassing=true;
|
||||
if(bScreenSpaceGate)
|
||||
{
|
||||
if(Assembly)
|
||||
bScreenSpaceGatePassing=StandaloneScreenSpaceGate::Run(GateSampleTiles,
|
||||
Streamer,*Assembly,ClosestDisplayDistances,World.CoreVoxelSizeMicrons,
|
||||
World.MaxClipLevel,PixelBudgetsSubvoxels);
|
||||
else
|
||||
{std::fprintf(stderr,"[ScreenSpaceGateResult] no-world-assembly status=REJECT\n");bScreenSpaceGatePassing=false;}
|
||||
}
|
||||
if(bExportRequested)
|
||||
{
|
||||
bSceneExportPassing=SceneExport.Close(static_cast<std::uint32_t>(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<unsigned long long>(FileSizeError?0:ExportBytes),
|
||||
bSceneExportPassing?"PASS":"FAIL",MeshExportPath.string().c_str());
|
||||
bSceneExportPassing=bSceneExportPassing&&!FileSizeError;
|
||||
}
|
||||
bool bColumnOverlapCapturePassing=true;
|
||||
if(bProfileColumnOverlap)
|
||||
{
|
||||
@@ -345,6 +580,15 @@ namespace StandaloneStreamBenchmark
|
||||
LOD,static_cast<unsigned long long>(TileCountByLOD[LOD]),WorkerSecondsByLOD[LOD],
|
||||
ColumnEvalMsByLOD[LOD],MarchingExclusiveMsByLOD[LOD],
|
||||
GroundRefineExclusiveMsByLOD[LOD],CapRefineExclusiveMsByLOD[LOD],MeshAssemblyMsByLOD[LOD]);
|
||||
if(bScreenSpaceGate)
|
||||
for(std::size_t Octave=0;Octave<8;++Octave)
|
||||
std::printf("[WorldAssemblerLODDetailOctave] lod=%zu octave=%zu evaluated=%llu budget_eligible=%llu skipped=%llu eval_ms=%.6f eligible_ms=%.6f\n",
|
||||
LOD,Octave,
|
||||
static_cast<unsigned long long>(DetailOctaveEvaluationsByLOD[LOD][Octave]),
|
||||
static_cast<unsigned long long>(DetailOctaveEligibleByLOD[LOD][Octave]),
|
||||
static_cast<unsigned long long>(DetailOctaveSkipsByLOD[LOD][Octave]),
|
||||
DetailOctaveMillisecondsByLOD[LOD][Octave],
|
||||
DetailOctaveEligibleMillisecondsByLOD[LOD][Octave]);
|
||||
}
|
||||
const double NeighborhoodSeconds=std::chrono::duration<double>(NeighborhoodReady-ColdStart).count();
|
||||
const double NeighborhoodMeshSeconds=std::chrono::duration<double>(NeighborhoodReady-ShapeReady).count();
|
||||
@@ -393,9 +637,59 @@ namespace StandaloneStreamBenchmark
|
||||
static_cast<unsigned long long>(HashTileRows(MeshRows)),
|
||||
static_cast<unsigned long long>(HashTileRows(PayloadRows)),
|
||||
static_cast<unsigned long long>(HashTileRows(TopologyRows)));
|
||||
for(std::size_t LOD=0;LOD<TileCountByLOD.size();++LOD)
|
||||
{
|
||||
const auto FilterLOD=[LOD](const std::vector<FHashedTile>& Rows)
|
||||
{
|
||||
std::vector<FHashedTile> Selected;
|
||||
for(const FHashedTile& Row:Rows)
|
||||
if(Row.Key.Level==static_cast<int32>(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<unsigned long long>(TileCountByLOD[LOD]),
|
||||
static_cast<unsigned long long>(HashTileRows(LodDensity)),
|
||||
static_cast<unsigned long long>(HashTileRows(LodMesh)),
|
||||
static_cast<unsigned long long>(HashTileRows(LodPayload)),
|
||||
static_cast<unsigned long long>(HashTileRows(LodTopology)));
|
||||
}
|
||||
const std::array<VoxelForgeCore::Vec3d,9> 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<uint32>(Density),4);
|
||||
HashWord(ExactUnclampedHash,std::bit_cast<uint32>(Unclamped),4);
|
||||
HashWord(ExactDetailHash,std::bit_cast<uint32>(Detail.displacement),4);
|
||||
HashWord(ExactDetailHash,std::bit_cast<uint32>(Detail.caveInfluence),4);
|
||||
HashWord(ExactDetailHash,std::bit_cast<uint32>(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<unsigned long long>(ExactDensityHash),
|
||||
static_cast<unsigned long long>(ExactUnclampedHash),
|
||||
static_cast<unsigned long long>(ExactDetailHash),
|
||||
static_cast<unsigned long long>(ExactCollisionHash));
|
||||
}
|
||||
return NeighborhoodFinished==static_cast<int32>(Neighborhood.size())
|
||||
&&FullDetailFinished==FullDetailExpected&&Finished==Update.DesiredTiles&&bHashesPassing
|
||||
&&(!bProfileColumnOverlap||bColumnOverlapCapturePassing)?0:6;
|
||||
&&(!bProfileColumnOverlap||bColumnOverlapCapturePassing)
|
||||
&&(!bExportRequested||bSceneExportPassing)&&bScreenSpaceGatePassing?0:6;
|
||||
}
|
||||
} // namespace StandaloneStreamBenchmark
|
||||
Reference in new issue
Block a user