wip(standalone): GPU step 28 -- skirted near tiles on GPU (correct, but SLOWER); 16 shape workers
Luna: near skirts were CPU-only by implementation gap, not correctness. Ported with
near-resolution refinement and overflow fallback; near-probe preparation split out so
the skirt kernels no longer inline the near field (first attempt: two fxc /O3 compiles
ran 10.5 h and were stopped). Shape compile proven identical at W1/W8/W16.
-SkipCpuDetailBand retired (154/640 skirt audit failures, +174 ms planning).
Audits: hashes W1/W8/W16, walk 5,642/5,642, whole-near 960 tiles + 640 skirt faces
0 sign/topology diffs (one 0.001 cm vertex-key delta), far/thin 0 diffs, both
survivals pass with 2,074 candidates at 7.00 / 7.02 GiB (was ~6.2), ten captures pass.
My runs outside the sandbox (Step28.exe). NOTE the machine was ~25% slower than last
night for every build (step 27 CPU full machine 0.97-1.02 s at night, 1.22-1.29 s now):
0xFF00: CPU 1.337 / 1.291 / 1.295 s; GPU miss 1.337 s;
GPU cached 1.663 / 1.424 / 1.617 s (GPU tiles 1,427 / 2,072 / 1,222)
0xFFFF: CPU 1.221 / 1.231 / 1.236 s (step 27 same session 1.285 / 1.222 s)
GPU cached 1.582 / 1.550 / 1.416, 1.635 / 1.441 / 1.470 / 1.445 s
(GPU tiles vary 593-2,074; timestamps up to ~470 ms)
=> GPU route now slower than the CPU route measured alongside it. Step 27 GPU control
was not clean (both exes load the same precompiled .cso files).
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
7d1808fdf2
commit
5aa285c3ef
26 files changed
+1536
-400
No files matched your search
@@ -32,6 +32,11 @@ cbuffer TileConstants : register(b0)
|
||||
uint3 TileConstantsPadding;
|
||||
};
|
||||
|
||||
uint FarSkirtNearProbeSurfaceCapacity()
|
||||
{
|
||||
return TileConstantsPadding.x;
|
||||
}
|
||||
|
||||
cbuffer FarFieldConstants : register(b1)
|
||||
{
|
||||
float FarStrataLo;
|
||||
@@ -62,7 +67,7 @@ cbuffer FarConnectorConstants : register(b2)
|
||||
uint FarShapeCount;
|
||||
uint FarSkirtFaceMask;
|
||||
float FarSkirtDepthVoxels;
|
||||
uint FarConnectorPadding;
|
||||
uint FarConnectorOutputBaseVertex;
|
||||
};
|
||||
|
||||
static const int3 CornerOffset[8] = {
|
||||
@@ -448,6 +453,7 @@ NearFieldBaseData NearFieldBaseAt(float3 position,out uint distanceEvaluations)
|
||||
const FarFieldSpatialBin range=FarFieldFindBin(position);
|
||||
float cave=100000.0f,overlay=-100000.0f;
|
||||
float caveFloorInfluence=0.0f,cavePassageInfluence=0.0f;
|
||||
bool criticalAir=false;
|
||||
distanceEvaluations=0;
|
||||
[loop]
|
||||
for(uint item=0;item<range.count;++item)
|
||||
@@ -455,6 +461,22 @@ NearFieldBaseData NearFieldBaseAt(float3 position,out uint distanceEvaluations)
|
||||
const VF_FieldPrimitive shape=FarShapes[FarSpatialBinShapeIds[range.offset+item]];
|
||||
if((shape.flags&VF_FIELD_PRIMITIVE_CARVE)!=0)
|
||||
{
|
||||
if((shape.flags&VF_FIELD_PRIMITIVE_CRITICAL)!=0
|
||||
&&all(position>=float3(shape.minVoxel[0],shape.minVoxel[1],shape.minVoxel[2]))
|
||||
&&all(position<=float3(shape.maxVoxel[0],shape.maxVoxel[1],shape.maxVoxel[2])))
|
||||
{
|
||||
const int3 decidedPosition=int3(position);
|
||||
float decidedDistance=VF_FieldPrimitiveDistance(shape,
|
||||
(float)decidedPosition.x,(float)decidedPosition.y,(float)decidedPosition.z);
|
||||
if((shape.flags&VF_FIELD_PRIMITIVE_HAS_FLOOR)!=0)
|
||||
{
|
||||
const float decidedFloor=VF_FieldPrimitiveFloorAt(shape,
|
||||
(float)decidedPosition.x,(float)decidedPosition.y);
|
||||
decidedDistance=VF_FieldSmoothMax(decidedDistance,
|
||||
decidedFloor-(float)decidedPosition.z,shape.floorBlendRadius);
|
||||
}
|
||||
criticalAir=criticalAir||decidedDistance<=0.0f;
|
||||
}
|
||||
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;
|
||||
@@ -495,7 +517,7 @@ NearFieldBaseData NearFieldBaseAt(float3 position,out uint distanceEvaluations)
|
||||
const float rockDistance=VF_FieldSmoothMin(base,carveOrOverlay,FarStrataBlend);
|
||||
NearFieldBaseData result;
|
||||
result.geometry=float4(rockDistance,surfaceSdf,caveInfluence,floorInfluence);
|
||||
result.influences=float4(passageInfluence,0,0,0);
|
||||
result.influences=float4(passageInfluence,criticalAir?1.0f:0.0f,0,0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -567,10 +589,12 @@ float NearFieldDetailRockDistance(float3 position,NearFieldBaseData baseData)
|
||||
return rockDistance;
|
||||
}
|
||||
|
||||
[noinline]
|
||||
float NearFieldDensityAt(float3 position,uint clampNearZero,out uint distanceEvaluations)
|
||||
{
|
||||
const NearFieldBaseData baseData=NearFieldBaseAt(position,distanceEvaluations);
|
||||
const float rockDistance=NearFieldDetailRockDistance(position,baseData);
|
||||
float rockDistance=NearFieldDetailRockDistance(position,baseData);
|
||||
if(baseData.influences.y!=0.0f)rockDistance=min(rockDistance,-1.0f/16.0f);
|
||||
float density=-rockDistance;
|
||||
if(clampNearZero!=0&&abs(density)<0.05f)
|
||||
density=rockDistance>=0.0f?-0.05f:0.05f;
|
||||
@@ -757,6 +781,48 @@ struct FarSkirtCachedSamples
|
||||
|
||||
StructuredBuffer<FarSkirtCachedSamples> FarSkirtCachedProbeInput : register(t21);
|
||||
RWStructuredBuffer<FarSkirtCachedSamples> FarSkirtCachedProbeOutput : register(u2);
|
||||
StructuredBuffer<float4> FarSkirtNearProbeInput : register(t22);
|
||||
ByteAddressBuffer FarSkirtNearProbeCounterInput : register(t23);
|
||||
RWStructuredBuffer<float4> FarSkirtNearProbeOutput : register(u3);
|
||||
RWByteAddressBuffer FarSkirtNearProbeCounter : register(u5);
|
||||
RWByteAddressBuffer FarSkirtNearProbeDispatchArgs : register(u6);
|
||||
|
||||
static const uint FarSkirtNearRootProbeStride=11u;
|
||||
static const uint FarSkirtNearChildProbeFanStride=4u;
|
||||
static const uint FarSkirtNearChildProbeFanLimit=8u;
|
||||
static const uint FarSkirtNearRootLimit=6u;
|
||||
static const uint FarSkirtNearProbeStride=FarSkirtNearRootProbeStride
|
||||
+FarSkirtNearChildProbeFanStride*FarSkirtNearChildProbeFanLimit;
|
||||
static const float FarSkirtUnusedNearProbeDensity=-3.402823e+38f;
|
||||
|
||||
[noinline]
|
||||
float NearSkirtDensityAtVoxel(float3 position)
|
||||
{
|
||||
uint ignoredEvaluations=0;
|
||||
float density=NearFieldDensityAt(position,1,ignoredEvaluations);
|
||||
const float3 latticePosition=(position-float3(OriginX,OriginY,OriginZ))/StepVoxels;
|
||||
const int3 lattice=int3(round(latticePosition));
|
||||
if(all(abs(latticePosition-float3(lattice))<=1.0e-4f)
|
||||
&&all(lattice>=-1)&&all(lattice<=int(CellsPerAxis)+1))
|
||||
{
|
||||
const uint sample=SampleIndex(lattice);
|
||||
const uint packedProxy=FarNearPackedProxy[sample];
|
||||
if(packedProxy!=0xffffffffu)
|
||||
{
|
||||
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[sample>>5]>>(sample&31u))&1u;
|
||||
const uint protectedSolid=(FarProtectedSolid[sample>>5]>>(sample&31u))&1u;
|
||||
if(protectedAir!=0u)density=max(abs(density),1.0f/256.0f);
|
||||
else if(protectedSolid!=0u)density=-max(abs(density),1.0f/256.0f);
|
||||
}
|
||||
return density;
|
||||
}
|
||||
|
||||
float FarSkirtDensityAtVoxel(float3 position)
|
||||
{
|
||||
@@ -783,8 +849,8 @@ FarSkirtVertex FarSkirtInterpolate(FarSkirtVertex a,FarSkirtVertex b,float t)
|
||||
FarSkirtVertex result;
|
||||
result.position=lerp(a.position,b.position,t);
|
||||
result.normal=normalize(lerp(a.normal,b.normal,t));
|
||||
// Clipping only uses the interpolated position and normal after insertion.
|
||||
// Its density is never fed back into an edge decision or emitted vertex.
|
||||
// Clipping uses the interpolated density only to find this root. Later near
|
||||
// refinement reads its exact probe from FarSkirtNearProbeInput.
|
||||
result.density=lerp(a.density,b.density,t);
|
||||
return result;
|
||||
}
|
||||
@@ -812,8 +878,221 @@ void FarSkirtClipTriangle(FarSkirtVertex a,FarSkirtVertex b,FarSkirtVertex c,
|
||||
}
|
||||
}
|
||||
|
||||
void FarSkirtStoreNearRootProbePositions(FarSkirtVertex a,FarSkirtVertex b,
|
||||
FarSkirtVertex c,uint probeBase)
|
||||
{
|
||||
const FarSkirtVertex midpoint01=FarSkirtInterpolate(a,b,0.5f);
|
||||
const FarSkirtVertex midpoint12=FarSkirtInterpolate(b,c,0.5f);
|
||||
const FarSkirtVertex midpoint20=FarSkirtInterpolate(c,a,0.5f);
|
||||
FarSkirtNearProbeOutput[probeBase]=float4(a.position/VoxelSizeCm,0.0f);
|
||||
FarSkirtNearProbeOutput[probeBase+1]=float4(b.position/VoxelSizeCm,0.0f);
|
||||
FarSkirtNearProbeOutput[probeBase+2]=float4(c.position/VoxelSizeCm,0.0f);
|
||||
FarSkirtNearProbeOutput[probeBase+3]=float4(
|
||||
(a.position+b.position+c.position)/(3.0f*VoxelSizeCm),0.0f);
|
||||
FarSkirtNearProbeOutput[probeBase+4]=float4(midpoint01.position/VoxelSizeCm,0.0f);
|
||||
FarSkirtNearProbeOutput[probeBase+5]=float4(midpoint12.position/VoxelSizeCm,0.0f);
|
||||
FarSkirtNearProbeOutput[probeBase+6]=float4(midpoint20.position/VoxelSizeCm,0.0f);
|
||||
FarSkirtNearProbeOutput[probeBase+7]=float4(
|
||||
(a.position+midpoint01.position+midpoint20.position)/(3.0f*VoxelSizeCm),0.0f);
|
||||
FarSkirtNearProbeOutput[probeBase+8]=float4(
|
||||
(midpoint01.position+b.position+midpoint12.position)/(3.0f*VoxelSizeCm),0.0f);
|
||||
FarSkirtNearProbeOutput[probeBase+9]=float4(
|
||||
(midpoint20.position+midpoint12.position+c.position)/(3.0f*VoxelSizeCm),0.0f);
|
||||
FarSkirtNearProbeOutput[probeBase+10]=float4(
|
||||
(midpoint01.position+midpoint12.position+midpoint20.position)/(3.0f*VoxelSizeCm),0.0f);
|
||||
[unroll]
|
||||
for(uint childProbe=FarSkirtNearRootProbeStride;
|
||||
childProbe<FarSkirtNearProbeStride;++childProbe)
|
||||
FarSkirtNearProbeOutput[probeBase+childProbe]=float4(0.0f,0.0f,0.0f,
|
||||
FarSkirtUnusedNearProbeDensity);
|
||||
}
|
||||
|
||||
void FarSkirtPrepareNearSourceTriangle(FarSkirtVertex a,FarSkirtVertex b,
|
||||
FarSkirtVertex c,uint probeBase,inout uint rootIndex)
|
||||
{
|
||||
FarSkirtVertex polygon[5];uint polygonCount=0;
|
||||
FarSkirtClipTriangle(a,b,c,polygon,polygonCount);
|
||||
if(polygonCount<3)return;
|
||||
[loop]
|
||||
for(uint fan=1;fan+1<polygonCount;++fan)
|
||||
{
|
||||
if(rootIndex<FarSkirtNearRootLimit)
|
||||
FarSkirtStoreNearRootProbePositions(polygon[0],polygon[fan],polygon[fan+1],
|
||||
probeBase+rootIndex*FarSkirtNearProbeStride);
|
||||
++rootIndex;
|
||||
}
|
||||
}
|
||||
|
||||
FarSkirtVertex FarSkirtNearRootVertex(FarSkirtVertex vertex,float exactDensity,
|
||||
FarSkirtVertex sourceA,FarSkirtVertex sourceB)
|
||||
{
|
||||
vertex.density=all(vertex.position==sourceA.position)||all(vertex.position==sourceB.position)
|
||||
?0.0f:exactDensity;
|
||||
return vertex;
|
||||
}
|
||||
|
||||
void FarSkirtNearBuildChildTriangleOutput(FarSkirtVertex a,FarSkirtVertex b,
|
||||
FarSkirtVertex c,uint probeBase,uint rootIndex,FarSkirtVertex sourceA,
|
||||
FarSkirtVertex sourceB,uint childIndex,out FarSkirtVertex childA,
|
||||
out FarSkirtVertex childB,out FarSkirtVertex childC)
|
||||
{
|
||||
const uint base=probeBase+rootIndex*FarSkirtNearProbeStride;
|
||||
a=FarSkirtNearRootVertex(a,FarSkirtNearProbeOutput[base].w,sourceA,sourceB);
|
||||
b=FarSkirtNearRootVertex(b,FarSkirtNearProbeOutput[base+1].w,sourceA,sourceB);
|
||||
c=FarSkirtNearRootVertex(c,FarSkirtNearProbeOutput[base+2].w,sourceA,sourceB);
|
||||
FarSkirtVertex midpoint01=FarSkirtInterpolate(a,b,0.5f);
|
||||
FarSkirtVertex midpoint12=FarSkirtInterpolate(b,c,0.5f);
|
||||
FarSkirtVertex midpoint20=FarSkirtInterpolate(c,a,0.5f);
|
||||
midpoint01.density=FarSkirtNearProbeOutput[base+4].w;
|
||||
midpoint12.density=FarSkirtNearProbeOutput[base+5].w;
|
||||
midpoint20.density=FarSkirtNearProbeOutput[base+6].w;
|
||||
if(childIndex==0){childA=a;childB=midpoint01;childC=midpoint20;}
|
||||
else if(childIndex==1){childA=midpoint01;childB=b;childC=midpoint12;}
|
||||
else if(childIndex==2){childA=midpoint20;childB=midpoint12;childC=c;}
|
||||
else {childA=midpoint01;childB=midpoint12;childC=midpoint20;}
|
||||
}
|
||||
|
||||
void FarSkirtStoreNearChildFanProbePositions(FarSkirtVertex a,FarSkirtVertex b,
|
||||
FarSkirtVertex c,uint probeBase,uint rootIndex,uint childFanIndex)
|
||||
{
|
||||
const uint base=probeBase+rootIndex*FarSkirtNearProbeStride
|
||||
+FarSkirtNearRootProbeStride+childFanIndex*FarSkirtNearChildProbeFanStride;
|
||||
FarSkirtNearProbeOutput[base]=float4(a.position/VoxelSizeCm,0.0f);
|
||||
FarSkirtNearProbeOutput[base+1]=float4(b.position/VoxelSizeCm,0.0f);
|
||||
FarSkirtNearProbeOutput[base+2]=float4(c.position/VoxelSizeCm,0.0f);
|
||||
FarSkirtNearProbeOutput[base+3]=float4(
|
||||
(a.position+b.position+c.position)/(3.0f*VoxelSizeCm),0.0f);
|
||||
}
|
||||
|
||||
float FarSkirtNearRootMaximumOutput(uint probeBase,uint rootIndex)
|
||||
{
|
||||
const uint base=probeBase+rootIndex*FarSkirtNearProbeStride;
|
||||
float maximumDensity=FarSkirtNearProbeOutput[base].w;
|
||||
maximumDensity=max(maximumDensity,FarSkirtNearProbeOutput[base+1].w);
|
||||
maximumDensity=max(maximumDensity,FarSkirtNearProbeOutput[base+2].w);
|
||||
maximumDensity=max(maximumDensity,FarSkirtNearProbeOutput[base+3].w);
|
||||
maximumDensity=max(maximumDensity,FarSkirtNearProbeOutput[base+4].w);
|
||||
maximumDensity=max(maximumDensity,FarSkirtNearProbeOutput[base+5].w);
|
||||
maximumDensity=max(maximumDensity,FarSkirtNearProbeOutput[base+6].w);
|
||||
return maximumDensity;
|
||||
}
|
||||
|
||||
void FarSkirtPrepareNearChildRoot(FarSkirtVertex a,FarSkirtVertex b,FarSkirtVertex c,
|
||||
uint probeBase,uint rootIndex,FarSkirtVertex sourceA,FarSkirtVertex sourceB)
|
||||
{
|
||||
if(FarSkirtNearRootMaximumOutput(probeBase,rootIndex)<=0.25f)return;
|
||||
uint childFanIndex=0;
|
||||
[unroll]
|
||||
for(uint child=0;child<4;++child)
|
||||
{
|
||||
FarSkirtVertex childA,childB,childC;
|
||||
FarSkirtNearBuildChildTriangleOutput(a,b,c,probeBase,rootIndex,sourceA,sourceB,
|
||||
child,childA,childB,childC);
|
||||
FarSkirtVertex polygon[5];uint polygonCount=0;
|
||||
FarSkirtClipTriangle(childA,childB,childC,polygon,polygonCount);
|
||||
if(polygonCount<3)continue;
|
||||
[loop]
|
||||
for(uint fan=1;fan+1<polygonCount;++fan)
|
||||
FarSkirtStoreNearChildFanProbePositions(polygon[0],polygon[fan],polygon[fan+1],
|
||||
probeBase,rootIndex,childFanIndex++);
|
||||
}
|
||||
}
|
||||
|
||||
void FarSkirtPrepareNearChildSourceTriangle(FarSkirtVertex a,FarSkirtVertex b,
|
||||
FarSkirtVertex c,FarSkirtVertex sourceA,FarSkirtVertex sourceB,uint probeBase,
|
||||
inout uint rootIndex)
|
||||
{
|
||||
FarSkirtVertex polygon[5];uint polygonCount=0;
|
||||
FarSkirtClipTriangle(a,b,c,polygon,polygonCount);
|
||||
if(polygonCount<3)return;
|
||||
[loop]
|
||||
for(uint fan=1;fan+1<polygonCount;++fan)
|
||||
{
|
||||
if(rootIndex<FarSkirtNearRootLimit)
|
||||
FarSkirtPrepareNearChildRoot(polygon[0],polygon[fan],polygon[fan+1],
|
||||
probeBase,rootIndex,sourceA,sourceB);
|
||||
++rootIndex;
|
||||
}
|
||||
}
|
||||
|
||||
uint FarSkirtCountNearSourceTriangleRoots(FarSkirtVertex a,FarSkirtVertex b,
|
||||
FarSkirtVertex c)
|
||||
{
|
||||
FarSkirtVertex polygon[5];uint polygonCount=0;
|
||||
FarSkirtClipTriangle(a,b,c,polygon,polygonCount);
|
||||
return polygonCount<3?0:polygonCount-2;
|
||||
}
|
||||
|
||||
float FarSkirtNearRootMaximum(uint probeBase,uint rootIndex)
|
||||
{
|
||||
const uint base=probeBase+rootIndex*FarSkirtNearProbeStride;
|
||||
float maximumDensity=FarSkirtNearProbeInput[base].w;
|
||||
maximumDensity=max(maximumDensity,FarSkirtNearProbeInput[base+1].w);
|
||||
maximumDensity=max(maximumDensity,FarSkirtNearProbeInput[base+2].w);
|
||||
maximumDensity=max(maximumDensity,FarSkirtNearProbeInput[base+3].w);
|
||||
maximumDensity=max(maximumDensity,FarSkirtNearProbeInput[base+4].w);
|
||||
maximumDensity=max(maximumDensity,FarSkirtNearProbeInput[base+5].w);
|
||||
maximumDensity=max(maximumDensity,FarSkirtNearProbeInput[base+6].w);
|
||||
return maximumDensity;
|
||||
}
|
||||
|
||||
void FarSkirtNearBuildChildTriangle(FarSkirtVertex a,FarSkirtVertex b,FarSkirtVertex c,
|
||||
uint probeBase,uint rootIndex,FarSkirtVertex sourceA,FarSkirtVertex sourceB,
|
||||
uint childIndex,out FarSkirtVertex childA,out FarSkirtVertex childB,
|
||||
out FarSkirtVertex childC)
|
||||
{
|
||||
const uint base=probeBase+rootIndex*FarSkirtNearProbeStride;
|
||||
a=FarSkirtNearRootVertex(a,FarSkirtNearProbeInput[base].w,sourceA,sourceB);
|
||||
b=FarSkirtNearRootVertex(b,FarSkirtNearProbeInput[base+1].w,sourceA,sourceB);
|
||||
c=FarSkirtNearRootVertex(c,FarSkirtNearProbeInput[base+2].w,sourceA,sourceB);
|
||||
FarSkirtVertex midpoint01=FarSkirtInterpolate(a,b,0.5f);
|
||||
FarSkirtVertex midpoint12=FarSkirtInterpolate(b,c,0.5f);
|
||||
FarSkirtVertex midpoint20=FarSkirtInterpolate(c,a,0.5f);
|
||||
midpoint01.density=FarSkirtNearProbeInput[base+4].w;
|
||||
midpoint12.density=FarSkirtNearProbeInput[base+5].w;
|
||||
midpoint20.density=FarSkirtNearProbeInput[base+6].w;
|
||||
if(childIndex==0){childA=a;childB=midpoint01;childC=midpoint20;}
|
||||
else if(childIndex==1){childA=midpoint01;childB=b;childC=midpoint12;}
|
||||
else if(childIndex==2){childA=midpoint20;childB=midpoint12;childC=c;}
|
||||
else {childA=midpoint01;childB=midpoint12;childC=midpoint20;}
|
||||
}
|
||||
|
||||
uint FarSkirtNearChildFanOutputCount(uint probeBase,uint rootIndex,uint childFanIndex)
|
||||
{
|
||||
const uint base=probeBase+rootIndex*FarSkirtNearProbeStride
|
||||
+FarSkirtNearRootProbeStride+childFanIndex*FarSkirtNearChildProbeFanStride;
|
||||
float maximumDensity=FarSkirtNearProbeInput[base].w;
|
||||
maximumDensity=max(maximumDensity,FarSkirtNearProbeInput[base+1].w);
|
||||
maximumDensity=max(maximumDensity,FarSkirtNearProbeInput[base+2].w);
|
||||
maximumDensity=max(maximumDensity,FarSkirtNearProbeInput[base+3].w);
|
||||
return maximumDensity<=0.25f?6u:0u;
|
||||
}
|
||||
|
||||
uint FarSkirtNearResolutionTriangleOutputCount(FarSkirtVertex a,FarSkirtVertex b,
|
||||
FarSkirtVertex c,uint probeBase,uint rootIndex,FarSkirtVertex sourceA,
|
||||
FarSkirtVertex sourceB)
|
||||
{
|
||||
if(FarSkirtNearRootMaximum(probeBase,rootIndex)<=0.25f)return 6;
|
||||
uint vertexCount=0,childFanIndex=0;
|
||||
[unroll]
|
||||
for(uint child=0;child<4;++child)
|
||||
{
|
||||
FarSkirtVertex childA,childB,childC;
|
||||
FarSkirtNearBuildChildTriangle(a,b,c,probeBase,rootIndex,sourceA,sourceB,
|
||||
child,childA,childB,childC);
|
||||
FarSkirtVertex polygon[5];uint polygonCount=0;
|
||||
FarSkirtClipTriangle(childA,childB,childC,polygon,polygonCount);
|
||||
if(polygonCount<3)continue;
|
||||
[loop]
|
||||
for(uint fan=1;fan+1<polygonCount;++fan)
|
||||
vertexCount+=FarSkirtNearChildFanOutputCount(probeBase,rootIndex,childFanIndex++);
|
||||
}
|
||||
return vertexCount;
|
||||
}
|
||||
|
||||
uint FarSkirtSourceTriangleOutputCount(FarSkirtVertex a,FarSkirtVertex b,FarSkirtVertex c,
|
||||
inout FarSkirtCachedSamples cached)
|
||||
inout FarSkirtCachedSamples cached,uint nearProbeBase,inout uint nearRootIndex,
|
||||
FarSkirtVertex sourceA,FarSkirtVertex sourceB)
|
||||
{
|
||||
FarSkirtVertex polygon[5];uint polygonCount=0;
|
||||
FarSkirtClipTriangle(a,b,c,polygon,polygonCount);
|
||||
@@ -822,6 +1101,14 @@ uint FarSkirtSourceTriangleOutputCount(FarSkirtVertex a,FarSkirtVertex b,FarSkir
|
||||
[loop]
|
||||
for(uint fan=1;fan+1<polygonCount;++fan)
|
||||
{
|
||||
if(StepVoxels<=2)
|
||||
{
|
||||
if(nearRootIndex<FarSkirtNearRootLimit)
|
||||
vertexCount+=FarSkirtNearResolutionTriangleOutputCount(polygon[0],
|
||||
polygon[fan],polygon[fan+1],nearProbeBase,nearRootIndex,sourceA,sourceB);
|
||||
++nearRootIndex;
|
||||
continue;
|
||||
}
|
||||
const float3 centerVoxel=(polygon[0].position+polygon[fan].position
|
||||
+polygon[fan+1].position)/(3.0f*VoxelSizeCm);
|
||||
const float centerDensity=FarSkirtDensityAtVoxel(centerVoxel);
|
||||
@@ -878,9 +1165,15 @@ FarSkirtVertex FarSkirtExtrudedVertexCached(FarSkirtVertex source,float density)
|
||||
|
||||
uint FarSkirtEdgeOutputCount(uint edgeVertexId,out FarSkirtCachedSamples cached)
|
||||
{
|
||||
cached.endpointDensities=0.0f;
|
||||
cached.centerDensities=0.0f;
|
||||
cached.metadata=0;
|
||||
if(StepVoxels<=2)
|
||||
cached=FarSkirtCachedProbeInput[edgeVertexId];
|
||||
else
|
||||
{
|
||||
cached.endpointDensities=0.0f;
|
||||
cached.centerDensities=0.0f;
|
||||
cached.metadata=0;
|
||||
}
|
||||
if(StepVoxels<=2&&cached.metadata.w!=0u)return 0;
|
||||
const uint surfaceVertexCount=min(FarConnectorDrawArgs.Load(OutputArgsByteOffset),OutputVertexCapacity);
|
||||
if(edgeVertexId>=surfaceVertexCount)return 0;
|
||||
const uint triangleBase=edgeVertexId-(edgeVertexId%3);
|
||||
@@ -888,11 +1181,21 @@ uint FarSkirtEdgeOutputCount(uint edgeVertexId,out FarSkirtCachedSamples cached)
|
||||
const FarSkirtVertex a=FarSkirtSurfaceVertex(triangleBase+edge);
|
||||
const FarSkirtVertex b=FarSkirtSurfaceVertex(triangleBase+(edge+1)%3);
|
||||
if((FarSkirtBoundaryFaceMask(a.position,b.position)&FarSkirtFaceMask)==0)return 0;
|
||||
const FarSkirtVertex a2=FarSkirtExtrudedVertex(a);
|
||||
const FarSkirtVertex b2=FarSkirtExtrudedVertex(b);
|
||||
cached.endpointDensities=float2(a2.density,b2.density);
|
||||
return FarSkirtSourceTriangleOutputCount(a,b,b2,cached)
|
||||
+FarSkirtSourceTriangleOutputCount(a,b2,a2,cached);
|
||||
FarSkirtVertex a2,b2;
|
||||
if(StepVoxels<=2)
|
||||
{
|
||||
a2=FarSkirtExtrudedVertexCached(a,cached.endpointDensities.x);
|
||||
b2=FarSkirtExtrudedVertexCached(b,cached.endpointDensities.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
a2=FarSkirtExtrudedVertex(a);
|
||||
b2=FarSkirtExtrudedVertex(b);
|
||||
cached.endpointDensities=float2(a2.density,b2.density);
|
||||
}
|
||||
uint nearRootIndex=0;
|
||||
return FarSkirtSourceTriangleOutputCount(a,b,b2,cached,cached.metadata.y,nearRootIndex,a,b)
|
||||
+FarSkirtSourceTriangleOutputCount(a,b2,a2,cached,cached.metadata.y,nearRootIndex,a,b);
|
||||
}
|
||||
|
||||
void FarSkirtStoreVertex(uint outputId,FarSkirtVertex vertex,uint panelBaseVertex)
|
||||
@@ -920,9 +1223,40 @@ void FarSkirtEmitTriangle(FarSkirtVertex a,FarSkirtVertex b,FarSkirtVertex c,
|
||||
FarSkirtStoreVertex(edgeBase+edgeCursor++,b,panelBaseVertex);
|
||||
}
|
||||
|
||||
void FarSkirtEmitNearResolutionTriangle(FarSkirtVertex a,FarSkirtVertex b,
|
||||
FarSkirtVertex c,FarSkirtVertex sourceA,FarSkirtVertex sourceB,uint probeBase,
|
||||
uint rootIndex,uint panelBaseVertex,uint edgeBase,inout uint edgeCursor)
|
||||
{
|
||||
if(FarSkirtNearRootMaximum(probeBase,rootIndex)<=0.25f)
|
||||
{
|
||||
FarSkirtEmitTriangle(a,b,c,panelBaseVertex,edgeBase,edgeCursor);
|
||||
return;
|
||||
}
|
||||
uint childFanIndex=0;
|
||||
[unroll]
|
||||
for(uint child=0;child<4;++child)
|
||||
{
|
||||
FarSkirtVertex childA,childB,childC;
|
||||
FarSkirtNearBuildChildTriangle(a,b,c,probeBase,rootIndex,sourceA,sourceB,
|
||||
child,childA,childB,childC);
|
||||
FarSkirtVertex polygon[5];uint polygonCount=0;
|
||||
FarSkirtClipTriangle(childA,childB,childC,polygon,polygonCount);
|
||||
if(polygonCount<3)continue;
|
||||
[loop]
|
||||
for(uint fan=1;fan+1<polygonCount;++fan)
|
||||
{
|
||||
if(FarSkirtNearChildFanOutputCount(probeBase,rootIndex,childFanIndex)!=0)
|
||||
FarSkirtEmitTriangle(polygon[0],polygon[fan],polygon[fan+1],
|
||||
panelBaseVertex,edgeBase,edgeCursor);
|
||||
++childFanIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FarSkirtEmitSourceTriangle(FarSkirtVertex a,FarSkirtVertex b,FarSkirtVertex c,
|
||||
float4 centerDensities,inout uint centerIndex,
|
||||
uint panelBaseVertex,uint edgeBase,inout uint edgeCursor)
|
||||
float4 centerDensities,inout uint centerIndex,uint nearProbeBase,inout uint nearRootIndex,
|
||||
FarSkirtVertex sourceA,FarSkirtVertex sourceB,uint panelBaseVertex,uint edgeBase,
|
||||
inout uint edgeCursor)
|
||||
{
|
||||
FarSkirtVertex polygon[5];uint polygonCount=0;
|
||||
FarSkirtClipTriangle(a,b,c,polygon,polygonCount);
|
||||
@@ -930,6 +1264,14 @@ void FarSkirtEmitSourceTriangle(FarSkirtVertex a,FarSkirtVertex b,FarSkirtVertex
|
||||
[loop]
|
||||
for(uint fan=1;fan+1<polygonCount;++fan)
|
||||
{
|
||||
if(StepVoxels<=2)
|
||||
{
|
||||
if(nearRootIndex<FarSkirtNearRootLimit)
|
||||
FarSkirtEmitNearResolutionTriangle(polygon[0],polygon[fan],polygon[fan+1],
|
||||
sourceA,sourceB,nearProbeBase,nearRootIndex,panelBaseVertex,edgeBase,edgeCursor);
|
||||
++nearRootIndex;
|
||||
continue;
|
||||
}
|
||||
const uint index=centerIndex++;
|
||||
const float centerDensity=index==0?centerDensities.x:index==1?centerDensities.y:
|
||||
index==2?centerDensities.z:centerDensities.w;
|
||||
@@ -939,6 +1281,142 @@ void FarSkirtEmitSourceTriangle(FarSkirtVertex a,FarSkirtVertex b,FarSkirtVertex
|
||||
}
|
||||
}
|
||||
|
||||
[numthreads(64,1,1)]
|
||||
void EvaluateFarSkirtEndpointsCS(uint3 dispatchId : SV_DispatchThreadID)
|
||||
{
|
||||
const uint edgeVertexId=dispatchId.x;
|
||||
if(edgeVertexId>=OutputVertexCapacity||StepVoxels>2)return;
|
||||
const uint surfaceVertexCount=min(FarConnectorDrawArgs.Load(OutputArgsByteOffset),
|
||||
OutputVertexCapacity);
|
||||
FarSkirtCachedSamples cached;
|
||||
cached.endpointDensities=0.0f;cached.centerDensities=0.0f;cached.metadata=0;
|
||||
if(edgeVertexId<surfaceVertexCount)
|
||||
{
|
||||
const uint triangleBase=edgeVertexId-(edgeVertexId%3);
|
||||
const uint edge=edgeVertexId%3;
|
||||
const FarSkirtVertex a=FarSkirtSurfaceVertex(triangleBase+edge);
|
||||
const FarSkirtVertex b=FarSkirtSurfaceVertex(triangleBase+(edge+1)%3);
|
||||
if((FarSkirtBoundaryFaceMask(a.position,b.position)&FarSkirtFaceMask)!=0)
|
||||
{
|
||||
const FarSkirtVertex a2=FarSkirtExtrudedVertexCached(a,0.0f);
|
||||
const FarSkirtVertex b2=FarSkirtExtrudedVertexCached(b,0.0f);
|
||||
float endpointDensities[2];
|
||||
[loop]
|
||||
for(uint endpoint=0;endpoint<2;++endpoint)
|
||||
{
|
||||
const float3 position=endpoint==0?a2.position:b2.position;
|
||||
endpointDensities[endpoint]=NearSkirtDensityAtVoxel(position/VoxelSizeCm);
|
||||
}
|
||||
cached.endpointDensities=float2(endpointDensities[0],endpointDensities[1]);
|
||||
}
|
||||
}
|
||||
FarSkirtCachedProbeOutput[edgeVertexId]=cached;
|
||||
}
|
||||
|
||||
[numthreads(64,1,1)]
|
||||
void PrepareFarSkirtNearProbesCS(uint3 dispatchId : SV_DispatchThreadID)
|
||||
{
|
||||
const uint edgeVertexId=dispatchId.x;
|
||||
if(edgeVertexId>=OutputVertexCapacity||StepVoxels>2)return;
|
||||
FarSkirtCachedSamples cached;
|
||||
cached.endpointDensities=0.0f;cached.centerDensities=0.0f;cached.metadata=0;
|
||||
const uint surfaceVertexCount=min(FarConnectorDrawArgs.Load(OutputArgsByteOffset),
|
||||
OutputVertexCapacity);
|
||||
if(edgeVertexId>=surfaceVertexCount)
|
||||
{
|
||||
FarSkirtCachedProbeOutput[edgeVertexId]=cached;
|
||||
return;
|
||||
}
|
||||
if(edgeVertexId>=FarSkirtNearProbeSurfaceCapacity())
|
||||
{
|
||||
cached.metadata.w=1u;
|
||||
uint previousStatus=0u;
|
||||
FarConnectorDrawArgs.InterlockedOr(OutputArgsByteOffset+40,1u,previousStatus);
|
||||
FarSkirtCachedProbeOutput[edgeVertexId]=cached;
|
||||
return;
|
||||
}
|
||||
const uint triangleBase=edgeVertexId-(edgeVertexId%3);
|
||||
const uint edge=edgeVertexId%3;
|
||||
const FarSkirtVertex a=FarSkirtSurfaceVertex(triangleBase+edge);
|
||||
const FarSkirtVertex b=FarSkirtSurfaceVertex(triangleBase+(edge+1)%3);
|
||||
if((FarSkirtBoundaryFaceMask(a.position,b.position)&FarSkirtFaceMask)==0)
|
||||
{
|
||||
FarSkirtCachedProbeOutput[edgeVertexId]=cached;
|
||||
return;
|
||||
}
|
||||
const FarSkirtCachedSamples endpoints=FarSkirtCachedProbeInput[edgeVertexId];
|
||||
cached.endpointDensities=endpoints.endpointDensities;
|
||||
const FarSkirtVertex a2=FarSkirtExtrudedVertexCached(a,cached.endpointDensities.x);
|
||||
const FarSkirtVertex b2=FarSkirtExtrudedVertexCached(b,cached.endpointDensities.y);
|
||||
const uint rootCount=FarSkirtCountNearSourceTriangleRoots(a,b,b2)
|
||||
+FarSkirtCountNearSourceTriangleRoots(a,b2,a2);
|
||||
uint probeBase=0;
|
||||
if(rootCount!=0)
|
||||
FarSkirtNearProbeCounter.InterlockedAdd(0,rootCount*FarSkirtNearProbeStride,probeBase);
|
||||
uint rootIndex=0;
|
||||
FarSkirtPrepareNearSourceTriangle(a,b,b2,probeBase,rootIndex);
|
||||
FarSkirtPrepareNearSourceTriangle(a,b2,a2,probeBase,rootIndex);
|
||||
cached.metadata.y=probeBase;
|
||||
cached.metadata.z=rootIndex;
|
||||
FarSkirtCachedProbeOutput[edgeVertexId]=cached;
|
||||
}
|
||||
|
||||
[numthreads(1,1,1)]
|
||||
void FinalizeFarSkirtNearProbeDispatchCS(uint3 dispatchId : SV_DispatchThreadID)
|
||||
{
|
||||
const uint probeCount=FarSkirtNearProbeCounterInput.Load(0);
|
||||
FarSkirtNearProbeDispatchArgs.Store(0,(probeCount+63u)/64u);
|
||||
FarSkirtNearProbeDispatchArgs.Store(4,1u);
|
||||
FarSkirtNearProbeDispatchArgs.Store(8,1u);
|
||||
}
|
||||
|
||||
[numthreads(64,1,1)]
|
||||
void EvaluateFarSkirtNearProbesCS(uint3 dispatchId : SV_DispatchThreadID)
|
||||
{
|
||||
const uint probeIndex=dispatchId.x;
|
||||
if(probeIndex>=FarSkirtNearProbeCounterInput.Load(0))return;
|
||||
if(probeIndex%FarSkirtNearProbeStride>=FarSkirtNearRootProbeStride)return;
|
||||
float4 probe=FarSkirtNearProbeOutput[probeIndex];
|
||||
probe.w=NearSkirtDensityAtVoxel(probe.xyz);
|
||||
FarSkirtNearProbeOutput[probeIndex]=probe;
|
||||
}
|
||||
|
||||
[numthreads(64,1,1)]
|
||||
void PrepareFarSkirtNearChildProbesCS(uint3 dispatchId : SV_DispatchThreadID)
|
||||
{
|
||||
const uint edgeVertexId=dispatchId.x;
|
||||
if(edgeVertexId>=OutputVertexCapacity||StepVoxels>2)return;
|
||||
const uint surfaceVertexCount=min(FarConnectorDrawArgs.Load(OutputArgsByteOffset),
|
||||
OutputVertexCapacity);
|
||||
if(edgeVertexId==0u)FarSkirtNearProbeOutput[0].z=(float)surfaceVertexCount;
|
||||
if(edgeVertexId>=surfaceVertexCount)return;
|
||||
const uint triangleBase=edgeVertexId-(edgeVertexId%3);
|
||||
const uint edge=edgeVertexId%3;
|
||||
const FarSkirtVertex a=FarSkirtSurfaceVertex(triangleBase+edge);
|
||||
const FarSkirtVertex b=FarSkirtSurfaceVertex(triangleBase+(edge+1)%3);
|
||||
if((FarSkirtBoundaryFaceMask(a.position,b.position)&FarSkirtFaceMask)==0)return;
|
||||
const FarSkirtCachedSamples cached=FarSkirtCachedProbeInput[edgeVertexId];
|
||||
if(cached.metadata.w!=0u)return;
|
||||
const FarSkirtVertex a2=FarSkirtExtrudedVertexCached(a,cached.endpointDensities.x);
|
||||
const FarSkirtVertex b2=FarSkirtExtrudedVertexCached(b,cached.endpointDensities.y);
|
||||
uint rootIndex=0;
|
||||
FarSkirtPrepareNearChildSourceTriangle(a,b,b2,a,b,cached.metadata.y,rootIndex);
|
||||
FarSkirtPrepareNearChildSourceTriangle(a,b2,a2,a,b,cached.metadata.y,rootIndex);
|
||||
}
|
||||
|
||||
[numthreads(64,1,1)]
|
||||
void EvaluateFarSkirtNearChildProbesCS(uint3 dispatchId : SV_DispatchThreadID)
|
||||
{
|
||||
const uint probeIndex=dispatchId.x;
|
||||
if(probeIndex>=FarSkirtNearProbeCounterInput.Load(0))return;
|
||||
const uint probeInRoot=probeIndex%FarSkirtNearProbeStride;
|
||||
if(probeInRoot<FarSkirtNearRootProbeStride)return;
|
||||
float4 probe=FarSkirtNearProbeOutput[probeIndex];
|
||||
if(probe.w< -1.0e30f)return;
|
||||
probe.w=NearSkirtDensityAtVoxel(probe.xyz);
|
||||
FarSkirtNearProbeOutput[probeIndex]=probe;
|
||||
}
|
||||
|
||||
float FarConnectorRadius(float3 center, float3 direction, float nominalRadius)
|
||||
{
|
||||
const float3 nominalPosition=center+direction*nominalRadius;
|
||||
@@ -1097,9 +1575,7 @@ void BuildFarConnectorRingsCS(uint3 groupId : SV_GroupID,
|
||||
}
|
||||
if (ringId == 0)
|
||||
{
|
||||
const uint slot = OutputVertexCapacity > 0
|
||||
? OutputBaseVertex / OutputVertexCapacity : 0;
|
||||
const uint panelBaseVertex = slot * FarConnectorPanelVertexCapacity;
|
||||
const uint panelBaseVertex = FarConnectorOutputBaseVertex;
|
||||
FarConnectorDrawArgs.Store(OutputArgsByteOffset + 20, FarConnectorVertexCount);
|
||||
FarConnectorDrawArgs.Store(OutputArgsByteOffset + 24, FarConnectorVertexCount > 0 ? 1 : 0);
|
||||
FarConnectorDrawArgs.Store(OutputArgsByteOffset + 28, panelBaseVertex);
|
||||
@@ -1175,9 +1651,7 @@ void EmitFarConnectorPanelsCS(uint3 dispatchId : SV_DispatchThreadID)
|
||||
vertex.normal = ring.normals[cornerIndex].xyz;
|
||||
const float connectorLength = length(connector.end - connector.start);
|
||||
vertex.uv = float2(ring.t * connectorLength / 256.0f, (float)side / 4.0f);
|
||||
const uint slot = OutputVertexCapacity > 0
|
||||
? OutputBaseVertex / OutputVertexCapacity : 0;
|
||||
const uint base = slot * FarConnectorPanelVertexCapacity;
|
||||
const uint base = FarConnectorOutputBaseVertex;
|
||||
const uint byteAddress = (base + vertexId) * 32;
|
||||
FarConnectorVertexBytes.Store3(byteAddress, asuint(vertex.position));
|
||||
FarConnectorVertexBytes.Store3(byteAddress + 12, asuint(vertex.normal));
|
||||
@@ -1382,6 +1856,7 @@ void ClassifyFarSkirtsCS(uint3 dispatchId : SV_DispatchThreadID)
|
||||
[numthreads(1,1,1)]
|
||||
void ScanFarSkirtsCS(uint3 dispatchId : SV_DispatchThreadID)
|
||||
{
|
||||
if(FarConnectorDrawArgs.Load(OutputArgsByteOffset+40)!=0u)return;
|
||||
const uint surfaceVertexCount=min(FarConnectorDrawArgs.Load(OutputArgsByteOffset),
|
||||
OutputVertexCapacity);
|
||||
uint totalSkirtVertices=0;
|
||||
@@ -1419,14 +1894,18 @@ void EmitFarSkirtsCS(uint3 dispatchId : SV_DispatchThreadID)
|
||||
const FarSkirtVertex b=FarSkirtSurfaceVertex(triangleBase+(edge+1)%3);
|
||||
if((FarSkirtBoundaryFaceMask(a.position,b.position)&FarSkirtFaceMask)==0)return;
|
||||
const FarSkirtCachedSamples cached=FarSkirtCachedProbeInput[edgeVertexId];
|
||||
if(cached.metadata.w!=0u)return;
|
||||
const FarSkirtVertex a2=FarSkirtExtrudedVertexCached(a,cached.endpointDensities.x);
|
||||
const FarSkirtVertex b2=FarSkirtExtrudedVertexCached(b,cached.endpointDensities.y);
|
||||
const uint panelBaseVertex=FarConnectorDrawArgs.Load(OutputArgsByteOffset+28);
|
||||
const uint edgeBase=FarConnectorVertexCount+FarSkirtScratch[edgeVertexId];
|
||||
uint edgeCursor=0,centerIndex=0;
|
||||
uint nearRootIndex=0;
|
||||
FarSkirtEmitSourceTriangle(a,b,b2,cached.centerDensities,centerIndex,
|
||||
cached.metadata.y,nearRootIndex,a,b,
|
||||
panelBaseVertex,edgeBase,edgeCursor);
|
||||
FarSkirtEmitSourceTriangle(a,b2,a2,cached.centerDensities,centerIndex,
|
||||
cached.metadata.y,nearRootIndex,a,b,
|
||||
panelBaseVertex,edgeBase,edgeCursor);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user