wip(standalone): GPU step 12 -- far evaluator cold use 1704 -> 3 ms; near detail now the floor
Split ordinary far evaluation from near-detail evaluation; [loop] in connector refinement and skirt clipping. Cold first use: EvaluateFarField 1704 -> 3.3 ms, connector rings 775 -> 630, skirt emit 948 -> 909, near detail 1783 ms (the floor). Warm-up still ~2.2 s; whole view CPU 1.351 s vs hybrid 3.210 s. Output-slot reuse fixed: crossing probe 1/1, 2,226/2,226 tiles. Audits: 0 topology/protected/thin diffs vs CPU and WARP, hashes + walk unchanged. 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
7f64e2e0aa
commit
05b1523c54
24 files changed
+1033
-66
No files matched your search
@@ -464,73 +464,85 @@ void EvaluateFarFieldCS(uint3 dispatchId : SV_DispatchThreadID)
|
||||
+ float3(int(x) - 1, int(y) - 1, int(z) - 1) * StepVoxels;
|
||||
float density;
|
||||
uint distanceEvaluations=0;
|
||||
float nearNormalDensity=0.0f;
|
||||
if(NearFieldMode!=0)
|
||||
const FarFieldSpatialBin range = FarFieldFindBin(position);
|
||||
float cave = 100000.0f, overlay = -100000.0f;
|
||||
[loop]
|
||||
for(uint item=0;item<range.count;++item)
|
||||
{
|
||||
nearNormalDensity=NearFieldDensityAt(position,0,distanceEvaluations);
|
||||
density=nearNormalDensity;
|
||||
if(abs(density)<0.05f)
|
||||
density=density<0.0f?-0.05f:(density>0.0f?0.05f:-0.05f);
|
||||
const uint packedProxy=FarNearPackedProxy[index];
|
||||
if(packedProxy!=0xffffffffu)
|
||||
const VF_FieldPrimitive shape=FarShapes[FarSpatialBinShapeIds[range.offset+item]];
|
||||
if((shape.flags&VF_FIELD_PRIMITIVE_CARVE)!=0)
|
||||
{
|
||||
// The CPU uploads sparse interpolation magnitudes. The GPU decides
|
||||
// ordinary signs, except for the one-quantum band where float sign
|
||||
// noise can flip an entire cell against the packed CPU cache.
|
||||
const bool packedSignOverride=(packedProxy&0x40000000u)!=0u;
|
||||
const bool packedRockSign=(packedProxy&0x80000000u)!=0u;
|
||||
const uint magnitudeQ=packedProxy&0x3fffffffu;
|
||||
const float magnitude=magnitudeQ==0u?4.125f:(float)magnitudeQ*(1.0f/256.0f);
|
||||
const bool negative=packedSignOverride?packedRockSign:(density<=0.0f);
|
||||
density=negative?-magnitude:magnitude;
|
||||
if(position.x<shape.minVoxel[0]-6||position.x>shape.maxVoxel[0]+6
|
||||
||position.y<shape.minVoxel[1]-6||position.y>shape.maxVoxel[1]+6
|
||||
||position.z<shape.minVoxel[2]-6||position.z>shape.maxVoxel[2]+6)continue;
|
||||
float distance=VF_FieldPrimitiveDistance(shape,position.x,position.y,position.z);
|
||||
++distanceEvaluations;
|
||||
if((shape.flags&VF_FIELD_PRIMITIVE_HAS_FLOOR)!=0)
|
||||
{
|
||||
const float floorZ=VF_FieldPrimitiveFloorAt(shape,position.x,position.y);
|
||||
distance=VF_FieldSmoothMax(distance,floorZ-position.z,shape.floorBlendRadius);
|
||||
}
|
||||
cave=VF_FieldSmoothMin(cave,distance,shape.blendRadius);
|
||||
}
|
||||
else if(position.x>=shape.minVoxel[0]&&position.x<=shape.maxVoxel[0]
|
||||
&&position.y>=shape.minVoxel[1]&&position.y<=shape.maxVoxel[1]
|
||||
&&position.z>=shape.minVoxel[2]&&position.z<=shape.maxVoxel[2])
|
||||
{
|
||||
overlay=max(overlay,-VF_FieldPrimitiveDistance(shape,position.x,position.y,position.z));
|
||||
++distanceEvaluations;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const FarFieldSpatialBin range=FarFieldFindBin(position);
|
||||
float cave=100000.0f,overlay=-100000.0f;
|
||||
[loop]
|
||||
for(uint item=0;item<range.count;++item)
|
||||
{
|
||||
const VF_FieldPrimitive shape=FarShapes[FarSpatialBinShapeIds[range.offset+item]];
|
||||
if((shape.flags&VF_FIELD_PRIMITIVE_CARVE)!=0)
|
||||
{
|
||||
if(position.x<shape.minVoxel[0]-6||position.x>shape.maxVoxel[0]+6
|
||||
||position.y<shape.minVoxel[1]-6||position.y>shape.maxVoxel[1]+6
|
||||
||position.z<shape.minVoxel[2]-6||position.z>shape.maxVoxel[2]+6)continue;
|
||||
float distance=VF_FieldPrimitiveDistance(shape,position.x,position.y,position.z);
|
||||
++distanceEvaluations;
|
||||
if((shape.flags&VF_FIELD_PRIMITIVE_HAS_FLOOR)!=0)
|
||||
{
|
||||
const float floorZ=VF_FieldPrimitiveFloorAt(shape,position.x,position.y);
|
||||
distance=VF_FieldSmoothMax(distance,floorZ-position.z,shape.floorBlendRadius);
|
||||
}
|
||||
cave=VF_FieldSmoothMin(cave,distance,shape.blendRadius);
|
||||
}
|
||||
else if(position.x>=shape.minVoxel[0]&&position.x<=shape.maxVoxel[0]
|
||||
&&position.y>=shape.minVoxel[1]&&position.y<=shape.maxVoxel[1]
|
||||
&&position.z>=shape.minVoxel[2]&&position.z<=shape.maxVoxel[2])
|
||||
{
|
||||
overlay=max(overlay,-VF_FieldPrimitiveDistance(shape,position.x,position.y,position.z));
|
||||
++distanceEvaluations;
|
||||
}
|
||||
}
|
||||
const float base=min(position.z-FarStrataLo,FarStrataHi-position.z);
|
||||
const float rockDistance=VF_FieldSmoothMin(base,max(cave,overlay),FarStrataBlend);
|
||||
const float rawDensity=-rockDistance;
|
||||
const float magnitude=max(abs(rawDensity),0.05f);
|
||||
density=rockDistance>=0.0f?-magnitude:magnitude;
|
||||
}
|
||||
const float base=min(position.z-FarStrataLo,FarStrataHi-position.z);
|
||||
const float rockDistance=VF_FieldSmoothMin(base,max(cave,overlay),FarStrataBlend);
|
||||
const float rawDensity=-rockDistance;
|
||||
const float magnitude=max(abs(rawDensity),0.05f);
|
||||
density=rockDistance>=0.0f?-magnitude:magnitude;
|
||||
const uint protectedAir = (FarProtectedAir[index >> 5] >> (index & 31)) & 1;
|
||||
const uint protectedSolid = (FarProtectedSolid[index >> 5] >> (index & 31)) & 1;
|
||||
const float protectedMinimum=NearFieldMode!=0?1.0f/256.0f:0.05f;
|
||||
if(protectedAir!=0)density=max(abs(density),protectedMinimum);
|
||||
else if(protectedSolid!=0)density=-max(abs(density),protectedMinimum);
|
||||
if(protectedAir!=0)density=max(abs(density),0.05f);
|
||||
else if(protectedSolid!=0)density=-max(abs(density),0.05f);
|
||||
FarFieldDensity[index] = density;
|
||||
FarNearNormalDensityOutput[index]=nearNormalDensity;
|
||||
FarNearNormalDensityOutput[index]=0.0f;
|
||||
if (FarEvalCounterEnabled != 0) FarFieldEvalCounters[index] = distanceEvaluations;
|
||||
}
|
||||
|
||||
[numthreads(64,1,1)]
|
||||
void EvaluateNearFieldCS(uint3 dispatchId : SV_DispatchThreadID)
|
||||
{
|
||||
const uint index=dispatchId.x;
|
||||
if(index>=FarSampleCount)return;
|
||||
const uint x=index%SampleDim;
|
||||
const uint y=(index/SampleDim)%SampleDim;
|
||||
const uint z=index/(SampleDim*SampleDim);
|
||||
const float3 position=float3(OriginX,OriginY,OriginZ)
|
||||
+float3(int(x)-1,int(y)-1,int(z)-1)*StepVoxels;
|
||||
uint distanceEvaluations=0;
|
||||
const float nearNormalDensity=NearFieldDensityAt(position,0,distanceEvaluations);
|
||||
float density=nearNormalDensity;
|
||||
if(abs(density)<0.05f)
|
||||
density=density<0.0f?-0.05f:(density>0.0f?0.05f:-0.05f);
|
||||
const uint packedProxy=FarNearPackedProxy[index];
|
||||
if(packedProxy!=0xffffffffu)
|
||||
{
|
||||
// The CPU uploads sparse interpolation magnitudes. The GPU decides
|
||||
// ordinary signs, except for the one-quantum band where float sign
|
||||
// noise can flip an entire cell against the packed CPU cache.
|
||||
const bool packedSignOverride=(packedProxy&0x40000000u)!=0u;
|
||||
const bool packedRockSign=(packedProxy&0x80000000u)!=0u;
|
||||
const uint magnitudeQ=packedProxy&0x3fffffffu;
|
||||
const float magnitude=magnitudeQ==0u?4.125f:(float)magnitudeQ*(1.0f/256.0f);
|
||||
const bool negative=packedSignOverride?packedRockSign:(density<=0.0f);
|
||||
density=negative?-magnitude:magnitude;
|
||||
}
|
||||
const uint protectedAir=(FarProtectedAir[index>>5]>>(index&31))&1;
|
||||
const uint protectedSolid=(FarProtectedSolid[index>>5]>>(index&31))&1;
|
||||
if(protectedAir!=0)density=max(abs(density),1.0f/256.0f);
|
||||
else if(protectedSolid!=0)density=-max(abs(density),1.0f/256.0f);
|
||||
FarFieldDensity[index]=density;
|
||||
FarNearNormalDensityOutput[index]=nearNormalDensity;
|
||||
if(FarEvalCounterEnabled!=0)FarFieldEvalCounters[index]=distanceEvaluations;
|
||||
}
|
||||
|
||||
float FarRockDistanceAt(float3 position,int3 cachedBinCoord,FarFieldSpatialBin cachedRange)
|
||||
{
|
||||
float cave = 100000.0f;
|
||||
@@ -632,7 +644,7 @@ void FarSkirtClipTriangle(FarSkirtVertex a,FarSkirtVertex b,FarSkirtVertex c,
|
||||
{
|
||||
FarSkirtVertex input[3];input[0]=a;input[1]=b;input[2]=c;
|
||||
polygonCount=0;
|
||||
[unroll]
|
||||
[loop]
|
||||
for(uint edge=0;edge<3;++edge)
|
||||
{
|
||||
FarSkirtVertex start=input[edge];
|
||||
@@ -778,7 +790,7 @@ float FarConnectorRadius(float3 center, float3 direction, float nominalRadius)
|
||||
residual=FarRockDistanceAt(center+direction*radius,cachedBinCoord,cachedRange);
|
||||
converged=abs(residual)<=1.0f;
|
||||
}
|
||||
[unroll]
|
||||
[loop]
|
||||
for(uint refine=0;refine<2&&!converged;++refine)
|
||||
{
|
||||
const float distance=residual;
|
||||
@@ -807,7 +819,7 @@ float FarConnectorRadius(float3 center, float3 direction, float nominalRadius)
|
||||
{
|
||||
float lo=previous,hi=distance;
|
||||
const bool previousSolid=previousDistance>=0.0f;
|
||||
[unroll]
|
||||
[loop]
|
||||
for(uint refine=0;refine<8;++refine)
|
||||
{
|
||||
const float mid=(lo+hi)*0.5f;
|
||||
|
||||
Reference in new issue
Block a user