wip(standalone): GPU step 14 -- warm-up 2.04 -> 1.05 s; cold path now waits on streaming, not shaders

Per-kernel fences in the production viewer put 1.73-1.98 s on the near-detail
Flush (shader creation 17-19 ms, dispatch calls ~0): skipping only that
dispatch cut idle warm-up 1.893 -> 0.521 s. Near detail rewritten with a
shared owner-roughness loop and shared Perlin samples: DXBC 448,588 -> 120,860
bytes, cold first use 1,596 -> 709 ms. Warm-up median 1.052 s, yet whole view
is unchanged (CPU 1.352 s vs hybrid 3.196 s): after input export the hybrid
spends 1.78-2.00 s streaming 1,082 GPU + 1,144 CPU-fallback tiles.
Audits: 0 diffs near/far vs CPU and WARP, hashes, walk 5,642/5,642, survival.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-10-07 08:03:00 +02:00
1 parent a96fd0b95b
commit f322b1c089
14 files changed
+774 -38

No files matched your search

@@ -289,6 +289,80 @@ FarFieldSpatialBin FarFieldFindBin(float3 position)
return emptyBin;
}
void NearOwnerFractalPair(float x,float y,float z,int octaves,
out float standardValue,out float ridgedValue)
{
float standardTotal=0.0f,ridgedTotal=0.0f,maxValue=0.0f;
float frequency=1.0f,amplitude=1.0f,weight=1.0f;
[loop]
for(int octave=0;octave<octaves;++octave)
{
const float noise=VF_FieldPerlin3D(x*frequency,y*frequency,z*frequency);
standardTotal+=noise*amplitude;
float ridge=noise*1.25f;
ridge=1.0f-abs(ridge);
ridge=ridge*ridge;
ridge*=weight;
weight=clamp(ridge*2.0f,0.0f,1.0f);
ridgedTotal+=ridge*amplitude;
maxValue+=amplitude;
amplitude*=0.5f;
frequency*=2.0f;
}
standardValue=standardTotal/maxValue;
ridgedValue=(ridgedTotal/maxValue)*2.0f-1.0f;
}
float NearOwnerRoughnessCore(float x,float y,float z,uint seed,
float surfaceRoughness,float roughnessFrequency,float verticalScale,
float domainWarpStrength,float domainWarpFrequency,uint noiseType)
{
if(!(roughnessFrequency>0.0f))return 0.0f;
const float effectiveZ=verticalScale>0.0f&&verticalScale!=1.0f?z/verticalScale:z;
const float mainX=x*roughnessFrequency+VF_FieldVoxelSeedOffset(seed,11.3f);
const float mainY=y*roughnessFrequency+VF_FieldVoxelSeedOffset(seed,13.7f);
const float mainZ=effectiveZ*roughnessFrequency+VF_FieldVoxelSeedOffset(seed,17.1f);
float fineX=x*roughnessFrequency*3.0f+VF_FieldVoxelSeedOffset(seed,19.1f)+2000.0f;
float fineY=y*roughnessFrequency*3.0f+VF_FieldVoxelSeedOffset(seed,23.7f)+2500.0f;
float fineZ=effectiveZ*roughnessFrequency*3.0f+VF_FieldVoxelSeedOffset(seed,29.3f)+3000.0f;
float mx=mainX,my=mainY,mz=mainZ;
if(domainWarpStrength>0.0f)
{
const float wf=domainWarpFrequency,ws=domainWarpStrength;
float wx=VF_FieldPerlin3D(x*wf+VF_FieldVoxelSeedOffset(seed,5.2f),
y*wf+VF_FieldVoxelSeedOffset(seed,1.3f),effectiveZ*wf+VF_FieldVoxelSeedOffset(seed,9.7f));
float wy=VF_FieldPerlin3D(x*wf+100.0f+VF_FieldVoxelSeedOffset(seed,7.7f),
y*wf+200.0f+VF_FieldVoxelSeedOffset(seed,3.1f),effectiveZ*wf+300.0f);
float wz=VF_FieldPerlin3D(x*wf+400.0f,y*wf+500.0f+VF_FieldVoxelSeedOffset(seed,11.9f),
effectiveZ*wf+600.0f+VF_FieldVoxelSeedOffset(seed,13.3f));
wx*=1.25f*ws;wy*=1.25f*ws;wz*=1.25f*ws;
mx+=wx;my+=wy;mz+=wz;
fineX+=wx;fineY+=wy;fineZ+=wz;
}
float rough=0.0f,fine=0.0f;
if(noiseType==3u)
{
rough=VF_FieldOwnerCellular(mx,my,mz);
fine=VF_FieldOwnerCellular(fineX,fineY,fineZ);
}
else
{
float roughStandard,roughRidged,fineStandard,fineRidged;
NearOwnerFractalPair(mx,my,mz,3,roughStandard,roughRidged);
NearOwnerFractalPair(fineX,fineY,fineZ,2,fineStandard,fineRidged);
if(noiseType==1u)
{ rough=roughRidged;fine=fineRidged; }
else if(noiseType==2u)
{
rough=(roughStandard+roughRidged)*0.5f;
fine=(fineStandard+fineRidged)*0.5f;
}
else
{ rough=roughStandard;fine=fineStandard; }
}
return (rough+fine*0.4f)*1.25f*surfaceRoughness;
}
float NearOwnerRoughnessAtStep(float3 position,float surfaceSdf,float caveInfluence,
FarFieldDetailLayer layer,uint anchorStep)
{
@@ -301,17 +375,17 @@ float NearOwnerRoughnessAtStep(float3 position,float surfaceSdf,float caveInflue
float total;
if(sampleZ1>sampleZ0)
{
const float lower=VF_FieldOwnerRoughnessCore(position.x,position.y,sampleZ0,
const float lower=NearOwnerRoughnessCore(position.x,position.y,sampleZ0,
FarFieldSeed,layer.surfaceRoughness,layer.roughnessFrequency,layer.verticalScale,
layer.domainWarpStrength,layer.domainWarpFrequency,layer.roughnessNoiseType);
const float upper=VF_FieldOwnerRoughnessCore(position.x,position.y,sampleZ1,
const float upper=NearOwnerRoughnessCore(position.x,position.y,sampleZ1,
FarFieldSeed,layer.surfaceRoughness,layer.roughnessFrequency,layer.verticalScale,
layer.domainWarpStrength,layer.domainWarpFrequency,layer.roughnessNoiseType);
const float alpha=(position.z-sampleZ0)/(sampleZ1-sampleZ0);
total=lower+(upper-lower)*alpha;
}
else
total=VF_FieldOwnerRoughnessCore(position.x,position.y,position.z,
total=NearOwnerRoughnessCore(position.x,position.y,position.z,
FarFieldSeed,layer.surfaceRoughness,layer.roughnessFrequency,layer.verticalScale,
layer.domainWarpStrength,layer.domainWarpFrequency,layer.roughnessNoiseType);
if(surfaceSdf<0.0f)
@@ -324,9 +398,18 @@ float NearOwnerRoughness(float3 position,float surfaceSdf,float caveInfluence,
float passageInfluence,FarFieldDetailLayer layer)
{
const float passage=saturate(passageInfluence);
const float anchored=NearOwnerRoughnessAtStep(position,surfaceSdf,caveInfluence,layer,8);
float anchored=0.0f,direct=0.0f;
[loop]
for(uint sampleIndex=0;sampleIndex<2;++sampleIndex)
{
if(sampleIndex==1&&passage<=0.40f)continue;
const uint anchorStep=sampleIndex==0?8u:2u;
const float value=NearOwnerRoughnessAtStep(position,surfaceSdf,caveInfluence,
layer,anchorStep);
if(sampleIndex==0)anchored=value;
else direct=value;
}
if(passage<=0.40f)return anchored;
const float direct=NearOwnerRoughnessAtStep(position,surfaceSdf,caveInfluence,layer,2);
if(passage>=0.60f)return direct;
const float directWeight=VF_FieldSmoothUnit((passage-0.40f)/0.20f);
const float anchoredWeight=1.0f-directWeight;