Removing clustering. Replaced by separation of axes
This commit is contained in:
@ -29,18 +29,18 @@ public class Player : MonoBehaviour
|
||||
|
||||
void Cast( ref VoxelRaycastGPU.BatchData[] batchData, int batchCount, int iIteration )
|
||||
{
|
||||
ComputeBuffer hitBuffer = new ComputeBuffer(rayCount * batchCount, Marshal.SizeOf(typeof(VoxelRaycastGPU.Hit)), ComputeBufferType.Append);
|
||||
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
totalCastDone += batchCount * rayCount;
|
||||
VoxelRaycastGPU.BatchData[] hits = voxelManager.CastGpuRay(in batchData, batchCount);
|
||||
|
||||
/*for( int i = 0; i < hits.Length; i++ )
|
||||
{
|
||||
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
||||
sphere.transform.position = hits[i].origin;
|
||||
sphere.transform.localScale = Vector3.one * 0.5f;
|
||||
}*/
|
||||
/**
|
||||
for( int i = 0; i < hits.Length; i++ )
|
||||
{
|
||||
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
||||
sphere.transform.position = hits[i].origin;
|
||||
sphere.transform.localScale = Vector3.one * 0.5f;
|
||||
}
|
||||
*/
|
||||
|
||||
sw.Stop();
|
||||
}
|
||||
|
||||
@ -15,10 +15,11 @@ public class VoxelRaycastGpuManager
|
||||
//--------------- RayCasts ------------------------------------------------------
|
||||
int kernel;
|
||||
|
||||
ComputeBuffer datasBuffer;
|
||||
ComputeBuffer datasBuffer = null;
|
||||
ComputeBuffer hitCounterBuffer = null;
|
||||
ComputeBuffer rayBuffer = null;
|
||||
ComputeBuffer hitBuffer;
|
||||
ComputeBuffer hitBuffer = null;
|
||||
ComputeBuffer countBuffer = null;
|
||||
|
||||
int raysPerBatch;
|
||||
|
||||
@ -27,12 +28,16 @@ public class VoxelRaycastGpuManager
|
||||
int groupsX;
|
||||
|
||||
int maxRaycastPerIteration;
|
||||
|
||||
int threadsY = 8;
|
||||
int maxGroupsY = 65535;
|
||||
|
||||
|
||||
//--------------- Clustering ------------------------------------------------------
|
||||
|
||||
ComputeShader clusteringShader;
|
||||
|
||||
int accumulationKernel;
|
||||
int reductionKernel;
|
||||
int gridSize;
|
||||
int threadCount = 64;
|
||||
int groupCountHits;
|
||||
@ -54,8 +59,6 @@ public class VoxelRaycastGpuManager
|
||||
|
||||
public VoxelRaycastGPU.BatchData[] Raycast(in VoxelRaycastGPU.BatchData[] batchData, int datasLenght)
|
||||
{
|
||||
ComputeBuffer countBuffer = new ComputeBuffer(1, sizeof(int), ComputeBufferType.Raw);
|
||||
|
||||
int iteration = 0;
|
||||
int currentCount = datasLenght;
|
||||
int previousCount = datasLenght;
|
||||
@ -71,60 +74,73 @@ public class VoxelRaycastGpuManager
|
||||
raycastShader.SetBuffer(kernel, "batchDatas", datasBuffer );
|
||||
raycastShader.SetBuffer(kernel, "hits", hitBuffer);
|
||||
|
||||
int threadsY = 8;
|
||||
/**
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
*/
|
||||
|
||||
for (int y = 0; y < currentCount; y += threadsY * maxGroupsY)
|
||||
{
|
||||
int remaining = currentCount - y;
|
||||
int dispatchGroupsY = Mathf.CeilToInt(Mathf.Min(remaining / (float)threadsY, maxGroupsY));
|
||||
raycastShader.SetInt("startIndexY", y);
|
||||
raycastShader.Dispatch(kernel, groupsX, dispatchGroupsY, 1);
|
||||
}
|
||||
|
||||
int groupsY = Mathf.CeilToInt((float)currentCount / threadsY);
|
||||
|
||||
Stopwatch sw = Stopwatch.StartNew();
|
||||
raycastShader.Dispatch(kernel, groupsX, groupsY, 1);
|
||||
|
||||
ComputeBuffer.CopyCount(hitBuffer, countBuffer, 0);
|
||||
int[] countArr = new int[1];
|
||||
countBuffer.GetData(countArr);
|
||||
currentCount = countArr[0];
|
||||
|
||||
sw.Stop();
|
||||
UnityEngine.Debug.Log($"Dispatch done in {sw.Elapsed.TotalMilliseconds}ms for {previousCount*raysPerBatch} casts retrieving {currentCount} hits");
|
||||
|
||||
if (currentCount > 0)
|
||||
{
|
||||
if (currentCount * raysPerBatch > maxRaycastPerIteration && iteration < 5)
|
||||
{
|
||||
sw = Stopwatch.StartNew();
|
||||
currentCount = Clustering(currentCount);
|
||||
sw.Stop();
|
||||
|
||||
UnityEngine.Debug.Log($"Clustering done in {sw.Elapsed.TotalMilliseconds}ms for {currentCount} casts");
|
||||
|
||||
|
||||
/**
|
||||
VoxelRaycastGPU.BatchData[] hits = new VoxelRaycastGPU.BatchData[currentCount];
|
||||
datasBuffer.GetData(hits, 0, 0, currentCount);
|
||||
|
||||
for (int i = 0; i < currentCount; i++)
|
||||
hitBuffer.GetData(hits, 0, 0, currentCount);
|
||||
for( int i = 0; i < hits.Length; i++ )
|
||||
{
|
||||
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
||||
sphere.transform.position = hits[i].origin;
|
||||
sphere.transform.localScale = Vector3.one * 0.5f;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
*/
|
||||
|
||||
datasBuffer = hitBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
sw.Stop();
|
||||
UnityEngine.Debug.Log($"Dispatch done in {sw.Elapsed.TotalMilliseconds}ms for {previousCount*raysPerBatch} casts retrieving {currentCount} hits");
|
||||
*/
|
||||
|
||||
iteration++;
|
||||
|
||||
if (currentCount > 0 && iteration < 5)
|
||||
{
|
||||
datasBuffer = hitBuffer;
|
||||
/**
|
||||
if (currentCount * raysPerBatch > maxRaycastPerIteration && iteration < 5)
|
||||
{
|
||||
sw = Stopwatch.StartNew();
|
||||
currentCount = Clustering( maxRaycastPerIteration / raysPerBatch);
|
||||
sw.Stop();
|
||||
|
||||
UnityEngine.Debug.Log($"Clustering done in {sw.Elapsed.TotalMilliseconds}ms for {currentCount} casts");
|
||||
|
||||
VoxelRaycastGPU.BatchData[] hits = new VoxelRaycastGPU.BatchData[currentCount];
|
||||
datasBuffer.GetData(hits, 0, 0, currentCount);
|
||||
|
||||
for (int i = 0; i < currentCount; i++)
|
||||
{
|
||||
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
||||
sphere.transform.position = hits[i].origin;
|
||||
sphere.transform.localScale = Vector3.one * 0.5f;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
VoxelRaycastGPU.BatchData[] result = new VoxelRaycastGPU.BatchData[previousCount];
|
||||
if (currentCount == 0)
|
||||
datasBuffer.GetData(result, 0, 0, previousCount);
|
||||
else
|
||||
hitBuffer.GetData(result, 0, 0, previousCount);
|
||||
|
||||
|
||||
countBuffer.Release();
|
||||
hitBuffer.GetData(result, 0, 0, previousCount);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -133,6 +149,8 @@ public class VoxelRaycastGpuManager
|
||||
{
|
||||
maxRaycastPerIteration = 1000000;
|
||||
raysPerBatch = nbRaysPerBatch;
|
||||
|
||||
countBuffer = new ComputeBuffer(1, sizeof(int), ComputeBufferType.Raw);
|
||||
|
||||
// Flatten octree
|
||||
linearTree = OctreeGpuHelpers.FlattenOctree(root);
|
||||
@ -152,7 +170,6 @@ public class VoxelRaycastGpuManager
|
||||
uint[] counterInit = { 0 };
|
||||
counterInit[0] = 0;
|
||||
hitCounterBuffer.SetData(counterInit);
|
||||
|
||||
kernel = raycastShader.FindKernel("CSMain");
|
||||
|
||||
raycastShader.SetBuffer(kernel, "nodes", nodeBuffer);
|
||||
@ -174,46 +191,72 @@ public class VoxelRaycastGpuManager
|
||||
cellClusteringSums = new ComputeBuffer(gridSize, sizeof(float) * 4);
|
||||
cellClusteringCounts = new ComputeBuffer(gridSize, sizeof(uint));
|
||||
clustered = new ComputeBuffer(gridSize, Marshal.SizeOf(typeof(VoxelRaycastGPU.BatchData)), ComputeBufferType.Append);
|
||||
|
||||
accumulationKernel = clusteringShader.FindKernel("Accumulate");
|
||||
reductionKernel = clusteringShader.FindKernel("Reduce");
|
||||
}
|
||||
|
||||
public int Clustering( int inputCount )
|
||||
public int Clustering( int targetGroupCount )
|
||||
{
|
||||
groupCountHits = Mathf.CeilToInt((float)inputCount / threadCount);
|
||||
int count = datasBuffer.count;
|
||||
|
||||
clustered.SetCounterValue(0);
|
||||
float[] zero4 = new float[gridSize * 4];
|
||||
uint[] zeroU = new uint[gridSize];
|
||||
cellClusteringSums.SetData(zero4);
|
||||
cellClusteringCounts.SetData(zeroU);
|
||||
// 1️⃣ Définir la résolution de la grille
|
||||
int cellsPerAxis = Mathf.CeilToInt(Mathf.Pow(targetGroupCount, 1f / 3f));
|
||||
Vector3 gridMin = new Vector3(-50, -50, -50);
|
||||
Vector3 gridMax = new Vector3(50, 50, 50);
|
||||
Vector3 cellSize = (gridMax - gridMin) / cellsPerAxis;
|
||||
|
||||
// Shader
|
||||
int kernelAcc = clusteringShader.FindKernel("AccumulateHits");
|
||||
int kernelMean = clusteringShader.FindKernel("ComputeMeans");
|
||||
int totalCells = cellsPerAxis * cellsPerAxis * cellsPerAxis;
|
||||
|
||||
clusteringShader.SetInt("inputCount", inputCount);
|
||||
clusteringShader.SetFloat("cellSize", 1.0f); // taille des cellules
|
||||
clusteringShader.SetVector("gridOrigin", Vector3.zero);
|
||||
// 2️⃣ Créer les buffers
|
||||
ComputeBuffer cellCount = new ComputeBuffer(totalCells, sizeof(uint));
|
||||
ComputeBuffer cellDistanceSum = new ComputeBuffer(totalCells, sizeof(float));
|
||||
ComputeBuffer resultBuffer = new ComputeBuffer(totalCells, sizeof(float) * 4, ComputeBufferType.Append);
|
||||
resultBuffer.SetCounterValue(0);
|
||||
|
||||
clusteringShader.SetBuffer(kernelAcc, "inputHits", hitBuffer);
|
||||
clusteringShader.SetBuffer(kernelAcc, "cellSums", cellClusteringSums);
|
||||
clusteringShader.SetBuffer(kernelAcc, "cellCounts", cellClusteringCounts);
|
||||
clusteringShader.Dispatch(kernelAcc, groupCountHits, 1, 1);
|
||||
clusteringShader.SetBuffer(accumulationKernel, "batchDatas", datasBuffer);
|
||||
clusteringShader.SetBuffer(accumulationKernel, "cellCount", cellCount);
|
||||
clusteringShader.SetBuffer(accumulationKernel, "cellDistanceSum", cellDistanceSum);
|
||||
|
||||
clusteringShader.SetBuffer(kernelMean, "cellSums", cellClusteringSums);
|
||||
clusteringShader.SetBuffer(kernelMean, "cellCounts", cellClusteringCounts);
|
||||
clusteringShader.SetBuffer(kernelMean, "clusteredHits", clustered);
|
||||
clusteringShader.Dispatch(kernelMean, groupCountGrid, 1, 1);
|
||||
clusteringShader.SetVector("gridMin", gridMin);
|
||||
clusteringShader.SetVector("gridMax", gridMax);
|
||||
clusteringShader.SetInts("gridResolution", cellsPerAxis, cellsPerAxis, cellsPerAxis);
|
||||
clusteringShader.SetVector("cellSize", cellSize);
|
||||
|
||||
// Lecture du résultat
|
||||
ComputeBuffer countBuffer = new ComputeBuffer(1, sizeof(int), ComputeBufferType.Raw);
|
||||
ComputeBuffer.CopyCount(clustered, countBuffer, 0);
|
||||
int[] countArr = new int[1];
|
||||
countBuffer.GetData(countArr);
|
||||
int clusterCount = countArr[0];
|
||||
int threadsPerGroup = 64;
|
||||
int maxThreadGroups = 65535;
|
||||
|
||||
datasBuffer = clustered;
|
||||
for (int i = 0; i < count; i += threadsPerGroup * maxThreadGroups)
|
||||
{
|
||||
int remaining = count - i;
|
||||
int groups = Mathf.CeilToInt(Mathf.Min(remaining / (float)threadsPerGroup, maxThreadGroups));
|
||||
clusteringShader.SetInt("startIndex", i);
|
||||
clusteringShader.Dispatch(accumulationKernel, groups, 1, 1);
|
||||
}
|
||||
|
||||
return clusterCount;
|
||||
// 4️⃣ Dispatch reduce
|
||||
clusteringShader.SetBuffer(reductionKernel, "cellCount", cellCount);
|
||||
clusteringShader.SetBuffer(reductionKernel, "cellDistanceSum", cellDistanceSum);
|
||||
clusteringShader.SetBuffer(reductionKernel, "clusteredBatches", resultBuffer);
|
||||
|
||||
int reduceGroups = Mathf.CeilToInt(totalCells / 64);
|
||||
clusteringShader.Dispatch(reductionKernel, reduceGroups, 1, 1);
|
||||
|
||||
// 5️⃣ Lire le résultat
|
||||
ComputeBuffer.CopyCount(resultBuffer, countBuffer, 0);
|
||||
int[] countArray = new int[1];
|
||||
countBuffer.GetData(countArray);
|
||||
int outputCount = countArray[0];
|
||||
|
||||
VoxelRaycastGPU.BatchData[] finalBatches = new VoxelRaycastGPU.BatchData[outputCount];
|
||||
resultBuffer.GetData(finalBatches, 0, 0, outputCount);
|
||||
|
||||
// 🔚 Cleanup
|
||||
cellCount.Release();
|
||||
cellDistanceSum.Release();
|
||||
resultBuffer.Release();
|
||||
|
||||
return outputCount;
|
||||
}
|
||||
|
||||
~VoxelRaycastGpuManager()
|
||||
@ -224,8 +267,14 @@ public class VoxelRaycastGpuManager
|
||||
if (rayBuffer != null)
|
||||
rayBuffer.Release();
|
||||
|
||||
hitBuffer.Release();
|
||||
datasBuffer.Release();
|
||||
if (hitBuffer != null)
|
||||
hitBuffer.Release();
|
||||
|
||||
if (datasBuffer != null)
|
||||
datasBuffer.Release();
|
||||
|
||||
if( countBuffer != null )
|
||||
countBuffer.Release();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user