From 4ef1b041568c01b19266ef78c2647360e92d0c38 Mon Sep 17 00:00:00 2001 From: blomios Date: Wed, 22 Oct 2025 23:03:33 +0200 Subject: [PATCH] Trying to add some optimization. Need to remove an intersection test now --- Assets/Assets/Shader/VoxelRaycast.compute | 36 ++++----- Assets/Scenes/SampleScene.unity | 16 +--- Assets/Scripts/Debug/Player.cs | 4 +- .../VoxelOctree/GPU/VoxelRaycastGpuManager.cs | 81 ++++++++----------- 4 files changed, 50 insertions(+), 87 deletions(-) diff --git a/Assets/Assets/Shader/VoxelRaycast.compute b/Assets/Assets/Shader/VoxelRaycast.compute index bd62448..33977e8 100644 --- a/Assets/Assets/Shader/VoxelRaycast.compute +++ b/Assets/Assets/Shader/VoxelRaycast.compute @@ -262,38 +262,30 @@ void CSMain(uint3 id : SV_DispatchThreadID) // push children in reverse order (so the nearest is popped first) if stack has room for (int c = childCount - 1; c >= 0; --c) { - //if (sp >= STACK_SIZE) break; // protect overflow - int cIndex = childIdx[c]; - - // compute child center (recompute bit pattern from cIndex relative? We need original i -> recompute mapping: - // We can recover i by searching bits in childMask; for clarity, recompute using same loop mapping: simpler: push center using known mapping - // But here we don't have i, so better to recompute using childIndex -> we need a deterministic mapping. - // For simplicity in this snippet, we recompute i by scanning parent children again — cost small (<=8), do it once: - // (implementation detail left to integrate carefully) - // --- simplified approach below assumes child center can be recomputed from cIndex via known ordering (keep same mapping as building) - // You must ensure mapping consistency between builder and shader. - // push - childEntry.nodeIndex = cIndex; - // recompute center from index i -> omitted here; in your real shader compute the offsetVec same as above - childEntry.center = childCenter[c]; // placeholder: replace with correct center compute + childEntry.nodeIndex = childIdx[c]; + childEntry.center = childCenter[c]; childEntry.halfSize = childHalf; stack[sp++] = childEntry; } - } // end while + } if (hasHit) { // commit heavy ops only now float tHit = outHit.maxDistance; - float3 hitPos = b.origin + r.direction * tHit; - // closest point - outHit.origin = ClosestPointOnAABB(hitPos, bestEntry.center, bestEntry.halfSize); + if( tHit > 0 ) + { + float3 hitPos = b.origin + r.direction * tHit; - outHit.origin += outHit.origin - bestEntry.center; - - // append final - hits.Append(outHit); + // closest point + outHit.origin = ClosestPointOnAABB(hitPos, bestEntry.center, bestEntry.halfSize); + + outHit.origin += outHit.origin - bestEntry.center; + + // append final + hits.Append(outHit); + } } } diff --git a/Assets/Scenes/SampleScene.unity b/Assets/Scenes/SampleScene.unity index 47d4770..5ca54a9 100644 --- a/Assets/Scenes/SampleScene.unity +++ b/Assets/Scenes/SampleScene.unity @@ -180,8 +180,6 @@ MeshRenderer: m_RayTracingAccelStructBuildFlagsOverride: 0 m_RayTracingAccelStructBuildFlags: 1 m_SmallMeshCulling: 1 - m_ForceMeshLod: -1 - m_MeshLodSelectionBias: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -203,7 +201,6 @@ MeshRenderer: m_AutoUVMaxDistance: 0.5 m_AutoUVMaxAngle: 89 m_LightmapParameters: {fileID: 0} - m_GlobalIlluminationMeshLod: 0 m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 @@ -295,7 +292,7 @@ MonoBehaviour: m_Bits: 8 voxelSize: 0.5 maxDepth: 7 - boundsSize: 100 + boundsSize: 200 computeShader: {fileID: 7200000, guid: beacc211952bec342847019386af6944, type: 3} clusteringShader: {fileID: 7200000, guid: 7b67ac486de90db48bc81c43fae83845, type: 3} --- !u!114 &464574967 @@ -635,8 +632,6 @@ MeshRenderer: m_RayTracingAccelStructBuildFlagsOverride: 0 m_RayTracingAccelStructBuildFlags: 1 m_SmallMeshCulling: 1 - m_ForceMeshLod: -1 - m_MeshLodSelectionBias: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -658,7 +653,6 @@ MeshRenderer: m_AutoUVMaxDistance: 0.5 m_AutoUVMaxAngle: 89 m_LightmapParameters: {fileID: 0} - m_GlobalIlluminationMeshLod: 0 m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 @@ -680,7 +674,7 @@ Transform: m_GameObject: {fileID: 1273284503} serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 18.52, y: 3.69, z: -9.47} + m_LocalPosition: {x: 24.81, y: 3.69, z: -4.07} m_LocalScale: {x: 11.138, y: 11.138, z: 11.138} m_ConstrainProportionsScale: 0 m_Children: [] @@ -760,8 +754,6 @@ MeshRenderer: m_RayTracingAccelStructBuildFlagsOverride: 0 m_RayTracingAccelStructBuildFlags: 1 m_SmallMeshCulling: 1 - m_ForceMeshLod: -1 - m_MeshLodSelectionBias: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -783,7 +775,6 @@ MeshRenderer: m_AutoUVMaxDistance: 0.5 m_AutoUVMaxAngle: 89 m_LightmapParameters: {fileID: 0} - m_GlobalIlluminationMeshLod: 0 m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 @@ -885,8 +876,6 @@ MeshRenderer: m_RayTracingAccelStructBuildFlagsOverride: 0 m_RayTracingAccelStructBuildFlags: 1 m_SmallMeshCulling: 1 - m_ForceMeshLod: -1 - m_MeshLodSelectionBias: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -908,7 +897,6 @@ MeshRenderer: m_AutoUVMaxDistance: 0.5 m_AutoUVMaxAngle: 89 m_LightmapParameters: {fileID: 0} - m_GlobalIlluminationMeshLod: 0 m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 diff --git a/Assets/Scripts/Debug/Player.cs b/Assets/Scripts/Debug/Player.cs index 81adc96..eb2aa67 100644 --- a/Assets/Scripts/Debug/Player.cs +++ b/Assets/Scripts/Debug/Player.cs @@ -24,7 +24,7 @@ public class Player : MonoBehaviour VoxelRaycastGPU.Ray[] rays = new VoxelRaycastGPU.Ray[rayCount]; FillRaysArray(rays); - voxelManager.gpuRayCaster.Init(rayCount, rays); + voxelManager.gpuRayCaster.Init(rayCount, rays, 3); } void Cast( ref VoxelRaycastGPU.BatchData[] batchData, int batchCount, int iIteration ) @@ -142,7 +142,7 @@ public class Player : MonoBehaviour VoxelRaycastGPU.BatchData[] batchDatas = new VoxelRaycastGPU.BatchData[1]; batchDatas[0].origin = origin; - batchDatas[0].maxDistance = 100; + batchDatas[0].maxDistance = 300; Cast(ref batchDatas, 1, 0); sw.Stop(); diff --git a/Assets/Scripts/VoxelOctree/GPU/VoxelRaycastGpuManager.cs b/Assets/Scripts/VoxelOctree/GPU/VoxelRaycastGpuManager.cs index 3f6863b..1c35b24 100644 --- a/Assets/Scripts/VoxelOctree/GPU/VoxelRaycastGpuManager.cs +++ b/Assets/Scripts/VoxelOctree/GPU/VoxelRaycastGpuManager.cs @@ -28,6 +28,7 @@ public class VoxelRaycastGpuManager int groupsX; int maxRaycastPerIteration; + int maxIterations = 3; int threadsY = 8; int maxGroupsY = 65535; @@ -59,25 +60,28 @@ public class VoxelRaycastGpuManager public VoxelRaycastGPU.BatchData[] Raycast(in VoxelRaycastGPU.BatchData[] batchData, int datasLenght) { - int iteration = 0; - int currentCount = datasLenght; - int previousCount = datasLenght; + int totalCastNumber = 0; + Stopwatch sw = Stopwatch.StartNew(); + + int iteration = 0; + int currentCount = batchData.Length; + int previousCount = currentCount; + + datasBuffer.SetCounterValue(0); datasBuffer.SetData(batchData, 0, 0, currentCount); - while (iteration < 5 && currentCount > 0) + while (iteration < maxIterations && currentCount > 0) { + totalCastNumber += currentCount; previousCount = currentCount; hitBuffer.SetCounterValue(0); + datasBuffer.SetCounterValue(0); raycastShader.SetBuffer(kernel, "batchDatas", datasBuffer ); raycastShader.SetBuffer(kernel, "hits", hitBuffer); - /** - Stopwatch sw = Stopwatch.StartNew(); - */ - for (int y = 0; y < currentCount; y += threadsY * maxGroupsY) { int remaining = currentCount - y; @@ -86,70 +90,49 @@ public class VoxelRaycastGpuManager raycastShader.Dispatch(kernel, groupsX, dispatchGroupsY, 1); } - ComputeBuffer.CopyCount(hitBuffer, countBuffer, 0); int[] countArr = new int[1]; countBuffer.GetData(countArr); currentCount = countArr[0]; - - /** - VoxelRaycastGPU.BatchData[] hits = new VoxelRaycastGPU.BatchData[currentCount]; - 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; - } - */ + sw.Stop(); + VoxelRaycastGPU.BatchData[] hits = new VoxelRaycastGPU.BatchData[currentCount]; + 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; + } - /** - sw.Stop(); - UnityEngine.Debug.Log($"Dispatch done in {sw.Elapsed.TotalMilliseconds}ms for {previousCount*raysPerBatch} casts retrieving {currentCount} hits"); - */ + sw.Start(); iteration++; - if (currentCount > 0 && iteration < 5) + if (currentCount > 0 && iteration < maxIterations ) { - 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; - } - } - */ + (datasBuffer,hitBuffer) = (hitBuffer,datasBuffer); } } + sw.Stop(); VoxelRaycastGPU.BatchData[] result = new VoxelRaycastGPU.BatchData[previousCount]; hitBuffer.GetData(result, 0, 0, previousCount); + + UnityEngine.Debug.Log($"Raycast done in {sw.Elapsed.TotalMilliseconds}ms for a total of {totalCastNumber} raycasts"); + return result; } - public void Init(int nbRaysPerBatch, in VoxelRaycastGPU.Ray[] rays) + public void Init(int nbRaysPerBatch, in VoxelRaycastGPU.Ray[] rays, int maxIterations) { maxRaycastPerIteration = 1000000; raysPerBatch = nbRaysPerBatch; - + this.maxIterations = maxIterations; + countBuffer = new ComputeBuffer(1, sizeof(int), ComputeBufferType.Raw); // Flatten octree @@ -157,7 +140,7 @@ public class VoxelRaycastGpuManager int nodeStride = Marshal.SizeOf(typeof(LinearNode)); // should be 64 hitBuffer = new ComputeBuffer(maxRaycastPerIteration * raysPerBatch, batchDataClassSize, ComputeBufferType.Append); - datasBuffer = new ComputeBuffer(maxRaycastPerIteration, batchDataClassSize, ComputeBufferType.Default); + datasBuffer = new ComputeBuffer(maxRaycastPerIteration, batchDataClassSize, ComputeBufferType.Append); rayBuffer = new ComputeBuffer(rays.Length, Marshal.SizeOf(typeof(VoxelRaycastGPU.Ray)), ComputeBufferType.Default); rayBuffer.SetData(rays, 0, 0, rays.Length);