wip(standalone): GPU step 8 partial -- GPU skirts, first-present hold; remote gap open

Luna's session ended on an API "Bad Request" before a final report; state is
unverified by me. In the log: GPU clipped-skirt emitter (count/scan/emit,
protected signs and critical air honoured), exposed-skirt audit passing at
the end; first-present stall reproduced on every launch (2.36-2.59 s, not
exe identity/idle/CPU run) and hidden by holding the CPU-ready frame until
GPU residency. Remote LOD3-4 band still differs from CPU; draw ranges and the
one inspected LOD3 tile match, cause not yet found (one-tile probe mid-fix).

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 02:19:38 +02:00
1 parent 90421d0655
commit f2de8fe9c6
42 files changed
+1381 -59

No files matched your search

@@ -60,7 +60,9 @@ cbuffer FarConnectorConstants : register(b2)
uint FarConnectorVertexCount;
uint FarConnectorPanelVertexCapacity;
uint FarShapeCount;
uint3 FarConnectorPadding;
uint FarSkirtFaceMask;
float FarSkirtDepthVoxels;
uint FarConnectorPadding;
};
static const int3 CornerOffset[8] = {
@@ -230,6 +232,8 @@ RWStructuredBuffer<FarConnectorRing> FarConnectorRingOutput : register(u7);
RWByteAddressBuffer FarConnectorDrawArgs : register(u4);
RWByteAddressBuffer FarConnectorVertexBytes : register(u5);
RWByteAddressBuffer FarConnectorIndexBytes : register(u6);
RWStructuredBuffer<uint> FarSkirtScratch : register(u0);
ByteAddressBuffer FarSurfaceVertexInput : register(t19);
RWStructuredBuffer<uint> FarFieldEvalCounters : register(u6);
@@ -510,6 +514,7 @@ float FarRockDistanceAt(float3 position,int3 cachedBinCoord,FarFieldSpatialBin c
{
float cave = 100000.0f;
float overlay = -100000.0f;
bool criticalAir=false;
const int3 positionBinCoord=int3(floor(position/max(1.0f,(float)FarSpatialBinSize)));
FarFieldSpatialBin range;
if(all(positionBinCoord==cachedBinCoord))range=cachedRange;
@@ -520,6 +525,25 @@ float FarRockDistanceAt(float3 position,int3 cachedBinCoord,FarFieldSpatialBin c
const VF_FieldPrimitive shape = FarShapes[FarSpatialBinShapeIds[range.offset + item]];
if ((shape.flags & VF_FIELD_PRIMITIVE_CARVE) != 0)
{
// The CPU field forces critical passage air at arbitrary skirt
// probes using the containing integer voxel. Match that decided
// exception here; the ordinary smooth field remains GPU-evaluated.
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)
@@ -541,7 +565,174 @@ float FarRockDistanceAt(float3 position,int3 cachedBinCoord,FarFieldSpatialBin c
}
}
const float base = min(position.z - FarStrataLo, FarStrataHi - position.z);
return VF_FieldSmoothMin(base, max(cave, overlay), FarStrataBlend);
float rockDistance=VF_FieldSmoothMin(base,max(cave,overlay),FarStrataBlend);
if(criticalAir)rockDistance=min(rockDistance,-1.0f/16.0f);
return rockDistance;
}
struct FarSkirtVertex
{
float3 position;
float3 normal;
float density;
};
float FarSkirtDensityAtVoxel(float3 position)
{
const int3 binCoord=int3(floor(position/max(1.0f,(float)FarSpatialBinSize)));
const FarFieldSpatialBin range=FarFieldFindBin(position);
const float rockDistance=FarRockDistanceAt(position,binCoord,range);
float density=-rockDistance;
// ShapeWorld clamps arbitrary (off-lattice) density magnitudes near the
// surface to 0.05 voxel. Skirt clipping uses those values for edge-root
// interpolation, so matching only their signs can move a clipped edge.
if(abs(density)<0.05f)density=rockDistance>=0.0f?-0.05f:0.05f;
return density;
}
float FarSkirtDensityAtCm(float3 positionCm)
{
return FarSkirtDensityAtVoxel(positionCm/VoxelSizeCm);
}
FarSkirtVertex FarSkirtInterpolate(FarSkirtVertex a,FarSkirtVertex b,float t)
{
if(t<=1.0e-6f)return a;
if(t>=1.0f-1.0e-6f)return b;
FarSkirtVertex result;
result.position=lerp(a.position,b.position,t);
result.normal=normalize(lerp(a.normal,b.normal,t));
result.density=FarSkirtDensityAtCm(result.position);
return result;
}
void FarSkirtClipTriangle(FarSkirtVertex a,FarSkirtVertex b,FarSkirtVertex c,
out FarSkirtVertex polygon[5],out uint polygonCount)
{
FarSkirtVertex input[3];input[0]=a;input[1]=b;input[2]=c;
polygonCount=0;
[unroll]
for(uint edge=0;edge<3;++edge)
{
FarSkirtVertex start=input[edge];
FarSkirtVertex end=input[(edge+1)%3];
const bool startSolid=start.density<=0.0f;
const bool endSolid=end.density<=0.0f;
if(startSolid!=endSolid)
{
const float denominator=start.density-end.density;
const float t=abs(denominator)>1.0e-8f
?clamp(start.density/denominator,0.0f,1.0f):0.5f;
polygon[polygonCount++]=FarSkirtInterpolate(start,end,t);
}
if(endSolid)polygon[polygonCount++]=end;
}
}
uint FarSkirtSourceTriangleOutputCount(FarSkirtVertex a,FarSkirtVertex b,FarSkirtVertex c)
{
FarSkirtVertex polygon[5];uint polygonCount=0;
FarSkirtClipTriangle(a,b,c,polygon,polygonCount);
if(polygonCount<3)return 0;
uint vertexCount=0;
[loop]
for(uint fan=1;fan+1<polygonCount;++fan)
{
const float3 centerVoxel=(polygon[0].position+polygon[fan].position
+polygon[fan+1].position)/(3.0f*VoxelSizeCm);
if(FarSkirtDensityAtVoxel(centerVoxel)<=0.0f)vertexCount+=6;
}
return vertexCount;
}
uint FarSkirtBoundaryFaceMask(float3 a,float3 b)
{
const float3 tileMin=float3(OriginX,OriginY,OriginZ)*VoxelSizeCm;
const float3 tileMax=(float3(OriginX,OriginY,OriginZ)
+float(CellsPerAxis*StepVoxels))*VoxelSizeCm;
uint mask=0;
if(a.x==tileMin.x&&b.x==tileMin.x)mask|=1u<<0;
if(a.x==tileMax.x&&b.x==tileMax.x)mask|=1u<<1;
if(a.y==tileMin.y&&b.y==tileMin.y)mask|=1u<<2;
if(a.y==tileMax.y&&b.y==tileMax.y)mask|=1u<<3;
if(a.z==tileMin.z&&b.z==tileMin.z)mask|=1u<<4;
if(a.z==tileMax.z&&b.z==tileMax.z)mask|=1u<<5;
return mask;
}
FarSkirtVertex FarSkirtSurfaceVertex(uint vertexId)
{
const uint byteAddress=(OutputBaseVertex+vertexId)*32;
FarSkirtVertex vertex;
vertex.position=asfloat(FarSurfaceVertexInput.Load3(byteAddress));
vertex.normal=asfloat(FarSurfaceVertexInput.Load3(byteAddress+12));
vertex.density=0.0f;
return vertex;
}
FarSkirtVertex FarSkirtExtrudedVertex(FarSkirtVertex source)
{
FarSkirtVertex vertex=source;
vertex.position-=source.normal*(max(1.0f,FarSkirtDepthVoxels)*VoxelSizeCm);
vertex.density=FarSkirtDensityAtCm(vertex.position);
return vertex;
}
uint FarSkirtEdgeOutputCount(uint edgeVertexId)
{
const uint surfaceVertexCount=min(FarConnectorDrawArgs.Load(OutputArgsByteOffset),OutputVertexCapacity);
if(edgeVertexId>=surfaceVertexCount)return 0;
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 0;
const FarSkirtVertex a2=FarSkirtExtrudedVertex(a);
const FarSkirtVertex b2=FarSkirtExtrudedVertex(b);
return FarSkirtSourceTriangleOutputCount(a,b,b2)
+FarSkirtSourceTriangleOutputCount(a,b2,a2);
}
void FarSkirtStoreVertex(uint outputId,FarSkirtVertex vertex,uint panelBaseVertex)
{
GpuVertex output;
output.position=vertex.position;
output.normal=vertex.normal;
output.uv=vertex.position.xy/VoxelSizeCm;
const uint index=panelBaseVertex+outputId;
const uint byteAddress=index*32;
FarConnectorVertexBytes.Store3(byteAddress,asuint(output.position));
FarConnectorVertexBytes.Store3(byteAddress+12,asuint(output.normal));
FarConnectorVertexBytes.Store2(byteAddress+24,asuint(output.uv));
FarConnectorIndexBytes.Store(index*4,index);
}
void FarSkirtEmitTriangle(FarSkirtVertex a,FarSkirtVertex b,FarSkirtVertex c,
uint panelBaseVertex,uint edgeBase,inout uint edgeCursor)
{
FarSkirtStoreVertex(edgeBase+edgeCursor++,a,panelBaseVertex);
FarSkirtStoreVertex(edgeBase+edgeCursor++,b,panelBaseVertex);
FarSkirtStoreVertex(edgeBase+edgeCursor++,c,panelBaseVertex);
FarSkirtStoreVertex(edgeBase+edgeCursor++,a,panelBaseVertex);
FarSkirtStoreVertex(edgeBase+edgeCursor++,c,panelBaseVertex);
FarSkirtStoreVertex(edgeBase+edgeCursor++,b,panelBaseVertex);
}
void FarSkirtEmitSourceTriangle(FarSkirtVertex a,FarSkirtVertex b,FarSkirtVertex c,
uint panelBaseVertex,uint edgeBase,inout uint edgeCursor)
{
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)
{
const float3 centerVoxel=(polygon[0].position+polygon[fan].position
+polygon[fan+1].position)/(3.0f*VoxelSizeCm);
if(FarSkirtDensityAtVoxel(centerVoxel)<=0.0f)
FarSkirtEmitTriangle(polygon[0],polygon[fan],polygon[fan+1],
panelBaseVertex,edgeBase,edgeCursor);
}
}
float FarConnectorRadius(float3 center, float3 direction, float nominalRadius)
@@ -704,6 +895,7 @@ void BuildFarConnectorRingsCS(uint3 groupId : SV_GroupID,
FarConnectorDrawArgs.Store(OutputArgsByteOffset + 28, panelBaseVertex);
FarConnectorDrawArgs.Store(OutputArgsByteOffset + 32, 0);
FarConnectorDrawArgs.Store(OutputArgsByteOffset + 36, 0);
FarConnectorDrawArgs.Store(OutputArgsByteOffset + 40, 0);
}
}
GroupMemoryBarrierWithGroupSync();
@@ -880,6 +1072,7 @@ void ScanGroupsCS(uint3 dispatchId : SV_DispatchThreadID)
DrawArgs.Store(OutputArgsByteOffset + 28, 0);
DrawArgs.Store(OutputArgsByteOffset + 32, 0);
DrawArgs.Store(OutputArgsByteOffset + 36, 0);
DrawArgs.Store(OutputArgsByteOffset + 40, 0);
}
StructuredBuffer<float> Density : register(t2);
@@ -927,6 +1120,63 @@ void EmitCS(uint3 dispatchId : SV_DispatchThreadID)
}
}
[numthreads(64,1,1)]
void ClassifyFarSkirtsCS(uint3 dispatchId : SV_DispatchThreadID)
{
const uint edgeVertexId=dispatchId.x;
if(edgeVertexId>=OutputVertexCapacity)return;
FarSkirtScratch[edgeVertexId]=FarSkirtEdgeOutputCount(edgeVertexId);
}
[numthreads(1,1,1)]
void ScanFarSkirtsCS(uint3 dispatchId : SV_DispatchThreadID)
{
const uint surfaceVertexCount=min(FarConnectorDrawArgs.Load(OutputArgsByteOffset),
OutputVertexCapacity);
uint totalSkirtVertices=0;
[loop]
for(uint edgeVertexId=0;edgeVertexId<surfaceVertexCount;++edgeVertexId)
{
const uint count=FarSkirtScratch[edgeVertexId];
FarSkirtScratch[edgeVertexId]=totalSkirtVertices;
totalSkirtVertices+=count;
}
const uint panelVertexCount=FarConnectorDrawArgs.Load(OutputArgsByteOffset+20);
if(panelVertexCount+totalSkirtVertices>FarConnectorPanelVertexCapacity)
{
FarConnectorDrawArgs.Store(OutputArgsByteOffset+40,1);
return;
}
FarConnectorDrawArgs.Store(OutputArgsByteOffset+40,0);
FarConnectorDrawArgs.Store(OutputArgsByteOffset+20,panelVertexCount+totalSkirtVertices);
FarConnectorDrawArgs.Store(OutputArgsByteOffset+24,
panelVertexCount+totalSkirtVertices>0?1:0);
}
[numthreads(64,1,1)]
void EmitFarSkirtsCS(uint3 dispatchId : SV_DispatchThreadID)
{
const uint edgeVertexId=dispatchId.x;
if(edgeVertexId>=OutputVertexCapacity||FarSkirtFaceMask==0
||FarConnectorDrawArgs.Load(OutputArgsByteOffset+40)!=0)return;
const uint surfaceVertexCount=min(FarConnectorDrawArgs.Load(OutputArgsByteOffset),
OutputVertexCapacity);
if(edgeVertexId>=surfaceVertexCount)return;
if(FarSkirtEdgeOutputCount(edgeVertexId)==0)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 FarSkirtVertex a2=FarSkirtExtrudedVertex(a);
const FarSkirtVertex b2=FarSkirtExtrudedVertex(b);
const uint panelBaseVertex=FarConnectorDrawArgs.Load(OutputArgsByteOffset+28);
const uint edgeBase=FarConnectorVertexCount+FarSkirtScratch[edgeVertexId];
uint edgeCursor=0;
FarSkirtEmitSourceTriangle(a,b,b2,panelBaseVertex,edgeBase,edgeCursor);
FarSkirtEmitSourceTriangle(a,b2,a2,panelBaseVertex,edgeBase,edgeCursor);
}
// Smoke probe for the dual-language noise path. This is intentionally separate from the mesh
// dispatch until shape records can be exported from the exact CPU layout compiler.
struct NoiseProbeInput { float3 position; uint seed; };