streaming: near LODs first (walkable ring, LOD0, LOD1, LOD2, then far); exact passage trims (L78)

- Headless and Unreal schedulers drain the collision-critical ring, then LOD0-2, then far LODs
  at low priority. LOD0-2 ready (W8 medians): SW 4.36->1.76, FI 6.89->5.26, TN 4.88->3.22,
  VS 2.71->1.56 s. Whole view roughly unchanged (FI/VS slightly later).
  KNOWN RISK: far tiles wait until every near tile is ready, so far LODs may starve while
  moving fast (to address next).
- Exact composer trims: tile-level upper-mouth candidate list, segment-index min/max rejection
  before lower_bound, 64-entry thread-local value-noise corner cache. Passage share 65 -> 63%.
- World exact: 24/24 hash matrix + pinned L75 owner hash. Fast tier PASS. Linux UE host builds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-27 19:13:45 +01:00
1 parent 5e091d254c
commit ec20994a8e
10 files changed
+718 -52

No files matched your search

@@ -20,6 +20,7 @@
#define VF_FIELD_CLAMP(v,a,b) clamp(v,a,b)
#define VF_FIELD_LERP(a,b,t) lerp(a,b,t)
#else
#include <array>
#include <algorithm>
#include <cmath>
#include <cstdint>
@@ -244,11 +245,70 @@ VF_FIELD_INLINE float VF_FieldValueNoise(float x, float y, float z,
return VF_FieldLerp(VF_FieldLerp(z00, z10, ty), VF_FieldLerp(z01, z11, ty), tz);
}
#if !defined(VF_FIELD_HLSL)
struct VF_FieldValueNoiseCacheEntry
{
VF_FieldI32 x=0,y=0,z=0,wavelength=0;
VF_FieldU32 seed=0;
bool valid=false;
std::array<float,8> corners{};
};
// Reuse the eight lattice values while adjacent voxel samples remain in the same
// value-noise cell. Only the integer hash lookups are shared; interpolation keeps
// the same inputs and operation order as VF_FieldValueNoise.
VF_FIELD_INLINE float VF_FieldCachedValueNoise(float x,float y,float z,
VF_FieldI32 wavelength,VF_FieldU32 seed)
{
static thread_local std::array<VF_FieldValueNoiseCacheEntry,64> cache{};
const float inv=1.0f/VF_FIELD_CAST_F32(wavelength);
const float fx=x*inv,fy=y*inv,fz=z*inv;
const VF_FieldI32 x0=VF_FIELD_CAST_I32(VF_FIELD_FLOOR(fx));
const VF_FieldI32 y0=VF_FIELD_CAST_I32(VF_FIELD_FLOOR(fy));
const VF_FieldI32 z0=VF_FIELD_CAST_I32(VF_FIELD_FLOOR(fz));
const VF_FieldU32 cellHash=VF_FieldMix(seed
^VF_FIELD_CAST_U32(x0)*0x68E31DA4u
^VF_FIELD_CAST_U32(y0)*0x1B56C4E9u
^VF_FIELD_CAST_U32(z0)*0x9E3779B9u
^VF_FIELD_CAST_U32(wavelength)*0x85EBCA77u);
auto& entry=cache[cellHash&(cache.size()-1)];
if(!entry.valid||entry.x!=x0||entry.y!=y0||entry.z!=z0
||entry.wavelength!=wavelength||entry.seed!=seed)
{
entry.x=x0;entry.y=y0;entry.z=z0;entry.wavelength=wavelength;
entry.seed=seed;entry.valid=true;
entry.corners={
VF_FieldNoiseValue(x0,y0,z0,seed),
VF_FieldNoiseValue(x0+1,y0,z0,seed),
VF_FieldNoiseValue(x0,y0+1,z0,seed),
VF_FieldNoiseValue(x0+1,y0+1,z0,seed),
VF_FieldNoiseValue(x0,y0,z0+1,seed),
VF_FieldNoiseValue(x0+1,y0,z0+1,seed),
VF_FieldNoiseValue(x0,y0+1,z0+1,seed),
VF_FieldNoiseValue(x0+1,y0+1,z0+1,seed)};
}
const float tx=VF_FieldFade(fx-VF_FIELD_CAST_F32(x0));
const float ty=VF_FieldFade(fy-VF_FIELD_CAST_F32(y0));
const float tz=VF_FieldFade(fz-VF_FIELD_CAST_F32(z0));
const float z00=VF_FieldLerp(entry.corners[0],entry.corners[1],tx);
const float z10=VF_FieldLerp(entry.corners[2],entry.corners[3],tx);
const float z01=VF_FieldLerp(entry.corners[4],entry.corners[5],tx);
const float z11=VF_FieldLerp(entry.corners[6],entry.corners[7],tx);
return VF_FieldLerp(VF_FieldLerp(z00,z10,ty),VF_FieldLerp(z01,z11,ty),tz);
}
#endif
VF_FIELD_INLINE float VF_FieldSurfaceRelief(float x, float y, float z, VF_FieldU32 seed)
{
#if defined(VF_FIELD_HLSL)
const float macro = VF_FieldValueNoise(x, y, z, 32, seed ^ 0xB5297A4Du);
const float mid = VF_FieldValueNoise(x, y, z, 16, seed ^ 0x63D83595u);
const float fine = VF_FieldValueNoise(x, y, z, 4, seed ^ 0xA511E9B3u);
#else
const float macro=VF_FieldCachedValueNoise(x,y,z,32,seed^0xB5297A4Du);
const float mid=VF_FieldCachedValueNoise(x,y,z,16,seed^0x63D83595u);
const float fine=VF_FieldCachedValueNoise(x,y,z,4,seed^0xA511E9B3u);
#endif
return 1.20f * macro + (0.80f + 0.25f * macro) * (0.40f * mid + 0.60f * fine);
}
@@ -335,12 +395,21 @@ VF_FIELD_INLINE float VF_FieldPassageWallRelief(float x,float y,float z,VF_Field
{
// Use long, non-commensurate rotated scales. The shared passage wall keeps broad,
// uneven rock relief without a short wavelength that can read as repeated rings.
#if defined(VF_FIELD_HLSL)
const float broad=VF_FieldValueNoise(x+17.0f,y-23.0f,z+11.0f,43,
seed^0xB5297A4Du);
const float mid=VF_FieldValueNoise(y-7.0f,z+19.0f,x-31.0f,29,
seed^0x63D83595u);
const float fine=VF_FieldValueNoise(z+5.0f,x+29.0f,y-13.0f,19,
seed^0xA511E9B3u);
#else
const float broad=VF_FieldCachedValueNoise(x+17.0f,y-23.0f,z+11.0f,43,
seed^0xB5297A4Du);
const float mid=VF_FieldCachedValueNoise(y-7.0f,z+19.0f,x-31.0f,29,
seed^0x63D83595u);
const float fine=VF_FieldCachedValueNoise(z+5.0f,x+29.0f,y-13.0f,19,
seed^0xA511E9B3u);
#endif
return 0.50f*broad+0.35f*mid+0.15f*fine;
}