wip(standalone): GPU step 3 -- GPU decides far rock/air, sparse CPU exceptions, hybrid viewer (H)
1,114 of 1,266 far tiles meshed on the GPU; vs CPU and vs WARP: 0 sign/topology differences, including the protected/thin exception audit; max symmetric vertex distance 0.125 cm; repeat RX runs identical; GPU field+mesh 0.029 ms/tile average. Strata survival 7,200/7,200, but connector survival fails (GPU lacks the connector repair panels). Hybrid cold clipmap 5.74 s vs CPU 2.23 s: dispatch and readback overhead, not compute (~33 ms of GPU work in total). 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
b61ccff549
commit
782f195bdb
15 files changed
+1018
-173
No files matched your search
@@ -130,9 +130,10 @@ struct FarFieldSampleRange { uint offset; uint count; };
|
||||
StructuredBuffer<VF_FieldPrimitive> FarShapes : register(t10);
|
||||
StructuredBuffer<FarFieldSampleRange> FarSampleShapeRanges : register(t11);
|
||||
StructuredBuffer<uint> FarSampleShapeIds : register(t12);
|
||||
StructuredBuffer<uint> FarRockAirSigns : register(t13);
|
||||
StructuredBuffer<uint> FarProtectedAir : register(t14);
|
||||
StructuredBuffer<uint> FarProtectedAir : register(t13);
|
||||
StructuredBuffer<uint> FarProtectedSolid : register(t14);
|
||||
RWStructuredBuffer<float> FarFieldDensity : register(u7);
|
||||
StructuredBuffer<float> GpuSignDensity : register(t15);
|
||||
|
||||
cbuffer FarFieldConstants : register(b1)
|
||||
{
|
||||
@@ -186,31 +187,22 @@ void EvaluateFarFieldCS(uint3 dispatchId : SV_DispatchThreadID)
|
||||
const float base = min(position.z - FarStrataLo, FarStrataHi - position.z);
|
||||
float rockDistance = VF_FieldSmoothMin(base, max(cave, overlay), FarStrataBlend);
|
||||
const uint protectedAir = (FarProtectedAir[index >> 5] >> (index & 31)) & 1;
|
||||
if (protectedAir != 0) rockDistance = min(rockDistance, -0.0625f);
|
||||
const uint protectedSolid = (FarProtectedSolid[index >> 5] >> (index & 31)) & 1;
|
||||
const float rawDensity = -rockDistance;
|
||||
const uint air = (FarRockAirSigns[index >> 5] >> (index & 31)) & 1;
|
||||
const float magnitude = max(abs(rawDensity), 0.05f);
|
||||
FarFieldDensity[index] = air != 0 ? magnitude : -magnitude;
|
||||
float density = rockDistance >= 0.0f ? -magnitude : magnitude;
|
||||
if (protectedAir != 0) density = magnitude;
|
||||
else if (protectedSolid != 0) density = -magnitude;
|
||||
FarFieldDensity[index] = density;
|
||||
}
|
||||
|
||||
groupshared uint ScanValues[256];
|
||||
|
||||
[numthreads(256,1,1)]
|
||||
void ClassifyCS(uint3 dispatchId : SV_DispatchThreadID,
|
||||
uint3 groupId : SV_GroupID,
|
||||
uint3 groupThreadId : SV_GroupThreadID)
|
||||
void ClassifyAndScan(uint index, uint3 groupId, uint3 groupThreadId, uint caseIndex)
|
||||
{
|
||||
const uint index = dispatchId.x;
|
||||
uint vertexCount = 0;
|
||||
uint caseIndex = 0;
|
||||
if (index < CellCount)
|
||||
{
|
||||
const uint3 c = uint3(index % CellsPerAxis,
|
||||
(index / CellsPerAxis) % CellsPerAxis,
|
||||
index / (CellsPerAxis * CellsPerAxis));
|
||||
[unroll]
|
||||
for (uint corner = 0; corner < 8; ++corner)
|
||||
caseIndex |= LatticeSign(Signs, int3(c) + CornerOffset[corner]) << corner;
|
||||
[unroll]
|
||||
for (uint slot = 0; slot < 15; ++slot)
|
||||
{
|
||||
@@ -235,6 +227,49 @@ void ClassifyCS(uint3 dispatchId : SV_DispatchThreadID,
|
||||
GroupVertexCounts[groupId.x] = ScanValues[255];
|
||||
}
|
||||
|
||||
[numthreads(256,1,1)]
|
||||
void ClassifyCS(uint3 dispatchId : SV_DispatchThreadID,
|
||||
uint3 groupId : SV_GroupID,
|
||||
uint3 groupThreadId : SV_GroupThreadID)
|
||||
{
|
||||
const uint index = dispatchId.x;
|
||||
uint caseIndex = 0;
|
||||
if (index < CellCount)
|
||||
{
|
||||
const uint3 c = uint3(index % CellsPerAxis,
|
||||
(index / CellsPerAxis) % CellsPerAxis,
|
||||
index / (CellsPerAxis * CellsPerAxis));
|
||||
[unroll]
|
||||
for (uint corner = 0; corner < 8; ++corner)
|
||||
caseIndex |= LatticeSign(Signs, int3(c) + CornerOffset[corner]) << corner;
|
||||
}
|
||||
ClassifyAndScan(index, groupId, groupThreadId, caseIndex);
|
||||
}
|
||||
|
||||
uint GpuLatticeSign(int3 p)
|
||||
{
|
||||
return GpuSignDensity[SampleIndex(p)] >= 0.0f ? 1 : 0;
|
||||
}
|
||||
|
||||
[numthreads(256,1,1)]
|
||||
void ClassifyFarCS(uint3 dispatchId : SV_DispatchThreadID,
|
||||
uint3 groupId : SV_GroupID,
|
||||
uint3 groupThreadId : SV_GroupThreadID)
|
||||
{
|
||||
const uint index = dispatchId.x;
|
||||
uint caseIndex = 0;
|
||||
if (index < CellCount)
|
||||
{
|
||||
const uint3 c = uint3(index % CellsPerAxis,
|
||||
(index / CellsPerAxis) % CellsPerAxis,
|
||||
index / (CellsPerAxis * CellsPerAxis));
|
||||
[unroll]
|
||||
for (uint corner = 0; corner < 8; ++corner)
|
||||
caseIndex |= GpuLatticeSign(int3(c) + CornerOffset[corner]) << corner;
|
||||
}
|
||||
ClassifyAndScan(index, groupId, groupThreadId, caseIndex);
|
||||
}
|
||||
|
||||
StructuredBuffer<uint> InputGroupVertexCounts : register(t8);
|
||||
RWStructuredBuffer<uint> GroupOffsets : register(u3);
|
||||
RWByteAddressBuffer DrawArgs : register(u4);
|
||||
|
||||
Reference in new issue
Block a user