unsafe void Refine(int workerIndex) { var spareNodes = new QuickList <int>(Pool, 8); var subtreeReferences = new QuickList <int>(Pool, BufferPool <int> .GetPoolIndex(MaximumSubtrees)); var treeletInternalNodes = new QuickList <int>(Pool, BufferPool <int> .GetPoolIndex(MaximumSubtrees)); int[] buffer; MemoryRegion region; BinnedResources resources; CreateBinnedResources(Pool, MaximumSubtrees, out buffer, out region, out resources); int refineIndex; while ((refineIndex = Interlocked.Increment(ref RefineIndex)) < RefinementTargets.Count) { subtreeReferences.Count = 0; treeletInternalNodes.Count = 0; bool nodesInvalidated; Tree.BinnedRefine(RefinementTargets.Elements[refineIndex], ref subtreeReferences, MaximumSubtrees, ref treeletInternalNodes, ref spareNodes, ref resources, out nodesInvalidated); //Allow other refines to traverse this node. Tree.nodes[RefinementTargets.Elements[refineIndex]].RefineFlag = 0; } Tree.RemoveUnusedInternalNodes(ref spareNodes); region.Dispose(); Pool.GiveBack(buffer); spareNodes.Dispose(); subtreeReferences.Count = 0; subtreeReferences.Dispose(); treeletInternalNodes.Count = 0; treeletInternalNodes.Dispose(); }
/// <summary> /// Clears and returns the list's buffers. /// </summary> public void Dispose() { Clear(); pool.GiveBack(Elements, poolIndex); #if DEBUG pool = null; #endif }
/// <summary> /// Clears and returns the set's buffers to the pools. /// </summary> public void Dispose() { //We must clean out the table before returning it to the pool. Clear(); tablePool.GiveBack(table, tablePoolIndex); elementPool.GiveBack(Elements, elementPoolIndex); #if DEBUG table = null; #endif }
/// <summary> /// Clears and returns the set's buffers to the pools. /// </summary> public void Dispose() { //We must clean out the table before returning it to the pool. Clear(); tablePool.GiveBack(table, tablePoolIndex); keyPool.GiveBack(Keys, pairPoolIndex); valuePool.GiveBack(Values, pairPoolIndex); #if DEBUG table = null; #endif }
/// <summary> /// Clears and returns the set's buffers to the pools. /// </summary> public void Dispose() { //We must clean out the table before returning it to the pool in case the array contains reference types which would otherwise leak. //The user may have already manually cleared it. To avoid doing redundant work, check the count first. //The user may have chosen to leave reference types in the list if they did a fast clear, but that's not for us to worry about. if (Count > 0) { Clear(); } tablePool.GiveBack(table, tablePoolIndex); elementPool.GiveBack(Elements, elementPoolIndex); #if DEBUG table = null; #endif }
public unsafe void SweepBuild(int[] leafIds, BoundingBox[] leafBounds, int start = 0, int length = -1, BufferPool <int> intPool = null, BufferPool <float> floatPool = null) { if (leafIds.Length != leafBounds.Length) { throw new ArgumentException("leafIds and leafBounds lengths must be equal."); } if (start + length > leafIds.Length) { throw new ArgumentException("Start + length must be smaller than the leaves array length."); } if (start < 0) { throw new ArgumentException("Start must be nonnegative."); } if (length == 0) { throw new ArgumentException("Length must be positive."); } if (length < 0) { length = leafIds.Length; } if (nodes[0].ChildCount != 0) { throw new InvalidOperationException("Cannot build a tree that already contains nodes."); } //The tree is built with an empty node at the root to make insertion work more easily. //As long as that is the case (and as long as this is not a constructor), //we must clear it out. nodeCount = 0; //Guarantee that no resizes will occur during the build. if (LeafCapacity < leafBounds.Length) { LeafCapacity = leafBounds.Length; } var preallocatedNodeCount = leafBounds.Length * 2 - 1; if (NodeCapacity < preallocatedNodeCount) { NodeCapacity = preallocatedNodeCount; } //Gather necessary information and put it into a convenient format. var indexMap = intPool == null ? new int[leafIds.Length] : intPool.Take(leafIds.Length); var indexMapX = intPool == null ? new int[leafIds.Length] : intPool.Take(leafIds.Length); var indexMapY = intPool == null ? new int[leafIds.Length] : intPool.Take(leafIds.Length); var indexMapZ = intPool == null ? new int[leafIds.Length] : intPool.Take(leafIds.Length); var centroidsX = floatPool == null ? new float[leafIds.Length] : floatPool.Take(leafIds.Length); var centroidsY = floatPool == null ? new float[leafIds.Length] : floatPool.Take(leafIds.Length); var centroidsZ = floatPool == null ? new float[leafIds.Length] : floatPool.Take(leafIds.Length); var mergedSize = leafIds.Length * (sizeof(BoundingBox) / sizeof(float)); var merged = floatPool == null ? new float[mergedSize] : floatPool.Take(mergedSize); fixed(BoundingBox *leafBoundsPointer = leafBounds) fixed(int *leafIdsPointer = leafIds) fixed(int *indexMapPointer = indexMap) fixed(int *indexMapXPointer = indexMapX) fixed(int *indexMapYPointer = indexMapY) fixed(int *indexMapZPointer = indexMapZ) fixed(float *centroidsXPointer = centroidsX) fixed(float *centroidsYPointer = centroidsY) fixed(float *centroidsZPointer = centroidsZ) fixed(float *mergedPointer = merged) { SweepResources leaves; leaves.Bounds = leafBoundsPointer; leaves.Ids = leafIdsPointer; leaves.IndexMap = indexMapPointer; leaves.IndexMapX = indexMapXPointer; leaves.IndexMapY = indexMapYPointer; leaves.IndexMapZ = indexMapZPointer; leaves.CentroidsX = centroidsXPointer; leaves.CentroidsY = centroidsYPointer; leaves.CentroidsZ = centroidsZPointer; leaves.Merged = (BoundingBox *)mergedPointer; for (int i = 0; i < leafIds.Length; ++i) { var bounds = leaves.Bounds[i]; leaves.IndexMap[i] = i; //Per-axis index maps don't need to be initialized here. They're filled in at the time of use. var centroid = bounds.Min + bounds.Max; centroidsX[i] = centroid.X; centroidsY[i] = centroid.Y; centroidsZ[i] = centroid.Z; } //Now perform a top-down sweep build. CreateSweepBuilderNode(-1, -1, ref leaves, 0, leafIds.Length); } //Return resources. if (floatPool != null) { Array.Clear(centroidsX, 0, leafIds.Length); Array.Clear(centroidsY, 0, leafIds.Length); Array.Clear(centroidsZ, 0, leafIds.Length); Array.Clear(merged, 0, mergedSize); floatPool.GiveBack(centroidsX); floatPool.GiveBack(centroidsY); floatPool.GiveBack(centroidsZ); floatPool.GiveBack(merged); } if (intPool != null) { Array.Clear(indexMap, 0, leafIds.Length); Array.Clear(indexMapX, 0, leafIds.Length); Array.Clear(indexMapY, 0, leafIds.Length); Array.Clear(indexMapZ, 0, leafIds.Length); intPool.GiveBack(indexMap); intPool.GiveBack(indexMapX); intPool.GiveBack(indexMapY); intPool.GiveBack(indexMapZ); } }
public unsafe void SweepBuild(int[] leafIds, BoundingBox[] leafBounds, int start = 0, int length = -1, BufferPool<int> intPool = null, BufferPool<float> floatPool = null) { if (leafIds.Length != leafBounds.Length) throw new ArgumentException("leafIds and leafBounds lengths must be equal."); if (start + length > leafIds.Length) throw new ArgumentException("Start + length must be smaller than the leaves array length."); if (start < 0) throw new ArgumentException("Start must be nonnegative."); if (length == 0) throw new ArgumentException("Length must be positive."); if (length < 0) length = leafIds.Length; if (nodes[0].ChildCount != 0) throw new InvalidOperationException("Cannot build a tree that already contains nodes."); //The tree is built with an empty node at the root to make insertion work more easily. //As long as that is the case (and as long as this is not a constructor), //we must clear it out. nodeCount = 0; //Guarantee that no resizes will occur during the build. if (LeafCapacity < leafBounds.Length) { LeafCapacity = leafBounds.Length; } var preallocatedNodeCount = leafBounds.Length * 2 - 1; if (NodeCapacity < preallocatedNodeCount) { NodeCapacity = preallocatedNodeCount; } //Gather necessary information and put it into a convenient format. var indexMap = intPool == null ? new int[leafIds.Length] : intPool.Take(leafIds.Length); var indexMapX = intPool == null ? new int[leafIds.Length] : intPool.Take(leafIds.Length); var indexMapY = intPool == null ? new int[leafIds.Length] : intPool.Take(leafIds.Length); var indexMapZ = intPool == null ? new int[leafIds.Length] : intPool.Take(leafIds.Length); var centroidsX = floatPool == null ? new float[leafIds.Length] : floatPool.Take(leafIds.Length); var centroidsY = floatPool == null ? new float[leafIds.Length] : floatPool.Take(leafIds.Length); var centroidsZ = floatPool == null ? new float[leafIds.Length] : floatPool.Take(leafIds.Length); var mergedSize = leafIds.Length * (sizeof(BoundingBox) / sizeof(float)); var merged = floatPool == null ? new float[mergedSize] : floatPool.Take(mergedSize); fixed (BoundingBox* leafBoundsPointer = leafBounds) fixed (int* leafIdsPointer = leafIds) fixed (int* indexMapPointer = indexMap) fixed (int* indexMapXPointer = indexMapX) fixed (int* indexMapYPointer = indexMapY) fixed (int* indexMapZPointer = indexMapZ) fixed (float* centroidsXPointer = centroidsX) fixed (float* centroidsYPointer = centroidsY) fixed (float* centroidsZPointer = centroidsZ) fixed (float* mergedPointer = merged) { SweepResources leaves; leaves.Bounds = leafBoundsPointer; leaves.Ids = leafIdsPointer; leaves.IndexMap = indexMapPointer; leaves.IndexMapX = indexMapXPointer; leaves.IndexMapY = indexMapYPointer; leaves.IndexMapZ = indexMapZPointer; leaves.CentroidsX = centroidsXPointer; leaves.CentroidsY = centroidsYPointer; leaves.CentroidsZ = centroidsZPointer; leaves.Merged = (BoundingBox*)mergedPointer; for (int i = 0; i < leafIds.Length; ++i) { var bounds = leaves.Bounds[i]; leaves.IndexMap[i] = i; //Per-axis index maps don't need to be initialized here. They're filled in at the time of use. var centroid = bounds.Min + bounds.Max; centroidsX[i] = centroid.X; centroidsY[i] = centroid.Y; centroidsZ[i] = centroid.Z; } //Now perform a top-down sweep build. CreateSweepBuilderNode(-1, -1, ref leaves, 0, leafIds.Length); } //Return resources. if (floatPool != null) { Array.Clear(centroidsX, 0, leafIds.Length); Array.Clear(centroidsY, 0, leafIds.Length); Array.Clear(centroidsZ, 0, leafIds.Length); Array.Clear(merged, 0, mergedSize); floatPool.GiveBack(centroidsX); floatPool.GiveBack(centroidsY); floatPool.GiveBack(centroidsZ); floatPool.GiveBack(merged); } if (intPool != null) { Array.Clear(indexMap, 0, leafIds.Length); Array.Clear(indexMapX, 0, leafIds.Length); Array.Clear(indexMapY, 0, leafIds.Length); Array.Clear(indexMapZ, 0, leafIds.Length); intPool.GiveBack(indexMap); intPool.GiveBack(indexMapX); intPool.GiveBack(indexMapY); intPool.GiveBack(indexMapZ); } }