wip(standalone): speed round -- interrupted by a PC hard reset at 10:16 (Kernel-Power 41)
Verified before the reset (density + full mesh hashes equal at 1/8/16 workers, routes 5642/5642, look audits green): - merged field lookups, parallel mask merge, compact inline spatial bins, line-local relief hash cache, lattice-specific mesher entry, fused sign+magnitude evaluation, far connectors as one capsule each (181,836 -> 16,491 far primitives). - crater edit (sphere+box+capsule, one transaction across LOD0/1): 15-27 ms; player 3x3x3 neighbourhood meshes ready ~18 ms after streaming starts. NOT yet verified (in the tree, unhashed): standalone-only skips of UV/colour arrays and of the ceiling/ground material grouping (best cold whole view 0.958 s @16 workers) and a far-bin reserve tweak. Those skips drop data the plugin's materials may need: not a game-path win as-is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
97c0455939
commit
ee5b05b357
16 files changed
+1011
-156
No files matched your search
@@ -6,6 +6,7 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <bit>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
@@ -36,11 +37,36 @@ struct FStandaloneCpuTile
|
||||
std::vector<uint32> Indices;
|
||||
uint64 DensitySamples=0;
|
||||
double WorkerSeconds=0.0;
|
||||
std::chrono::steady_clock::time_point CompletedAt{};
|
||||
uint64 DensityHash=14695981039346656037ull;
|
||||
bool bHasDensityHash=false;
|
||||
uint64 MeshHash=14695981039346656037ull;
|
||||
bool bHasMeshHash=false;
|
||||
std::array<uint64,VoxelDensityProfile::BucketCount> ProfileCycles{};
|
||||
};
|
||||
|
||||
inline uint64 HashStandaloneCpuTileMesh(const FStandaloneCpuTile& Tile)
|
||||
{
|
||||
uint64 Hash=14695981039346656037ull;
|
||||
const auto AddWord=[&](uint64 Word,int32 Bytes)
|
||||
{
|
||||
for(int32 I=0;I<Bytes;++I)
|
||||
{
|
||||
Hash^=static_cast<uint8>(Word>>(I*8));
|
||||
Hash*=1099511628211ull;
|
||||
}
|
||||
};
|
||||
AddWord(Tile.Vertices.size(),8);
|
||||
for(const FStandaloneCpuVertex& Vertex:Tile.Vertices)
|
||||
{
|
||||
for(const float Value:Vertex.Position)AddWord(std::bit_cast<uint32>(Value),4);
|
||||
for(const float Value:Vertex.Normal)AddWord(std::bit_cast<uint32>(Value),4);
|
||||
}
|
||||
AddWord(Tile.Indices.size(),8);
|
||||
for(const uint32 Index:Tile.Indices)AddWord(Index,4);
|
||||
return Hash;
|
||||
}
|
||||
|
||||
struct FStandaloneMeshCacheMetadata
|
||||
{
|
||||
uint64 SourceDataHash=0;
|
||||
@@ -308,6 +334,13 @@ public:
|
||||
return UpdateDesired(CameraPositionVoxels,ResidentKeys,CrossingIndex);
|
||||
}
|
||||
|
||||
void SetDesiredTileFilter(const std::vector<FVoxelTileKey>& Keys)
|
||||
{
|
||||
TileFilter.clear();TileFilter.reserve(Keys.size()*2+1);
|
||||
for(const FVoxelTileKey& Key:Keys)TileFilter.insert(Key);
|
||||
bUseTileFilter=true;
|
||||
}
|
||||
|
||||
void Stop()
|
||||
{
|
||||
{
|
||||
@@ -330,6 +363,9 @@ public:
|
||||
if(MaxLevelFilter>=0)
|
||||
NewDesired.Tiles.erase(std::remove_if(NewDesired.Tiles.begin(),NewDesired.Tiles.end(),
|
||||
[&](const FVoxelTileKey& Key){return Key.Level>MaxLevelFilter;}),NewDesired.Tiles.end());
|
||||
if(bUseTileFilter)
|
||||
NewDesired.Tiles.erase(std::remove_if(NewDesired.Tiles.begin(),NewDesired.Tiles.end(),
|
||||
[&](const FVoxelTileKey& Key){return !TileFilter.contains(Key);}),NewDesired.Tiles.end());
|
||||
FStandaloneStreamingUpdate Stats;
|
||||
Stats.CenterChunk=NewDesired.CenterChunk;
|
||||
Stats.DesiredTiles=static_cast<int32>(NewDesired.Tiles.size());
|
||||
@@ -409,12 +445,16 @@ private:
|
||||
{
|
||||
Out=*Cached;Out.RequestedCrossing=Job.RequestedCrossing;
|
||||
Out.WorkerSeconds=std::chrono::duration<double>(FClock::now()-StartTime).count();
|
||||
Out.CompletedAt=FClock::now();
|
||||
if(bHashDensity)
|
||||
{Out.MeshHash=HashStandaloneCpuTileMesh(Out);Out.bHasMeshHash=true;}
|
||||
CacheHitCount.fetch_add(1,std::memory_order_relaxed);
|
||||
return Out;
|
||||
}
|
||||
}
|
||||
UVoxelMarchingCubesMesher Mesher;
|
||||
Mesher.SetGenerator(World->Generator.get());
|
||||
Mesher.bStandaloneCompactPayload=true;
|
||||
Mesher.bGenerateSkirts=World->bGenerateSkirts;
|
||||
Mesher.SkirtCells=static_cast<float>(World->SkirtCells);
|
||||
Mesher.LODOctaveDrop=World->LODOctaveDrop;
|
||||
@@ -460,7 +500,10 @@ private:
|
||||
}
|
||||
Out.Indices.reserve(static_cast<size_t>(Mesh.Triangles.Num()));
|
||||
for(const int32 Index:Mesh.Triangles)Out.Indices.push_back(static_cast<uint32>(Index));
|
||||
if(bHashDensity)
|
||||
{Out.MeshHash=HashStandaloneCpuTileMesh(Out);Out.bHasMeshHash=true;}
|
||||
Out.WorkerSeconds=std::chrono::duration<double>(FClock::now()-StartTime).count();
|
||||
Out.CompletedAt=FClock::now();
|
||||
return Out;
|
||||
}
|
||||
|
||||
@@ -500,6 +543,8 @@ private:
|
||||
std::vector<FStandaloneCpuTile> Ready;
|
||||
std::unordered_set<FVoxelTileKey,FStandaloneTileKeyHash> Desired;
|
||||
std::unordered_set<FVoxelTileKey,FStandaloneTileKeyHash> Outstanding;
|
||||
std::unordered_set<FVoxelTileKey,FStandaloneTileKeyHash> TileFilter;
|
||||
bool bUseTileFilter=false;
|
||||
FStandaloneDesiredTileSet CurrentDesired;
|
||||
int32 FullResTileCount=0;
|
||||
};
|
||||
Reference in new issue
Block a user