///<summary> /// Constructs a new contact manifold. ///</summary> protected TriangleMeshConvexContactManifold() { contacts = new RawList <Contact>(4); unusedContacts = new UnsafeResourcePool <Contact>(4); contactIndicesToRemove = new RawList <int>(4); activePairTesters = new QuickDictionary <TriangleIndices, TrianglePairTester>(BufferPools <TriangleIndices> .Locking, BufferPools <TrianglePairTester> .Locking, BufferPools <int> .Locking, 3); }
/// <summary> /// Creates a new memory pool. /// </summary> /// <param name="memoryPoolSize">Size of the pool in elements.</param> public Allocator(long memoryPoolSize, int allocationCountEstimate = 128) { this.Capacity = memoryPoolSize; QuickDictionary <ulong, Allocation, Array <ulong>, Array <Allocation>, Array <int>, PrimitiveComparer <ulong> > .Create( new PassthroughArrayPool <ulong>(), new PassthroughArrayPool <Allocation>(), new PassthroughArrayPool <int>(), SpanHelper.GetContainingPowerOf2(allocationCountEstimate), 3, out allocations); }
public override void Update(double dt) { RigidTransform transform = new RigidTransform(mesh.Position); RigidTransform convexTransform = convex.WorldTransform; ContactRefresher.ContactRefresh(contacts, supplementData, ref convexTransform, ref transform, contactIndicesToRemove); RemoveQueuedContacts(); var overlaps = new QuickList <Vector3i>(BufferPools <Vector3i> .Thread); mesh.ChunkShape.GetOverlaps(mesh.Position, convex.BoundingBox, ref overlaps); var candidatesToAdd = new QuickList <ContactData>(BufferPools <ContactData> .Thread, BufferPool <int> .GetPoolIndex(overlaps.Count)); for (int i = 0; i < overlaps.Count; i++) { if (!ActivePairs.TryGetValue(overlaps.Elements[i], out GeneralConvexPairTester manifold)) { manifold = GetPair(ref overlaps.Elements[i]); } else { ActivePairs.FastRemove(overlaps.Elements[i]); } activePairsBackBuffer.Add(overlaps.Elements[i], manifold); if (manifold.GenerateContactCandidate(out ContactData contactCandidate)) { candidatesToAdd.Add(ref contactCandidate); } } overlaps.Dispose(); for (int i = ActivePairs.Count - 1; i >= 0; i--) { ReturnPair(ActivePairs.Values[i]); ActivePairs.FastRemove(ActivePairs.Keys[i]); } var temp = ActivePairs; ActivePairs = activePairsBackBuffer; activePairsBackBuffer = temp; if (contacts.Count + candidatesToAdd.Count > 4) { var reducedCandidates = new QuickList <ContactData>(BufferPools <ContactData> .Thread, 3); ContactReducer.ReduceContacts(contacts, ref candidatesToAdd, contactIndicesToRemove, ref reducedCandidates); RemoveQueuedContacts(); for (int i = reducedCandidates.Count - 1; i >= 0; i--) { Add(ref reducedCandidates.Elements[i]); reducedCandidates.RemoveAt(i); } reducedCandidates.Dispose(); } else if (candidatesToAdd.Count > 0) { for (int i = 0; i < candidatesToAdd.Count; i++) { Add(ref candidatesToAdd.Elements[i]); } } candidatesToAdd.Dispose(); }
public SimulationProfiler(int initialStageCount = 8) { QuickDictionary <object, double, Array <object>, Array <double>, Array <int>, ReferenceComparer <object> > .Create( objectPool, doublePool, intPool, SpanHelper.GetContainingPowerOf2(initialStageCount), 3, out stages); QuickDictionary <object, long, Array <object>, Array <long>, Array <int>, ReferenceComparer <object> > .Create( objectPool, longPool, intPool, SpanHelper.GetContainingPowerOf2(initialStageCount), 3, out startTimeStamps); }
public ContactEvents(TEventHandler eventHandler, BufferPool pool, IThreadDispatcher threadDispatcher, int initialListenerCapacity = 32) { this.EventHandler = eventHandler; this.pool = pool; this.threadDispatcher = threadDispatcher; pendingWorkerAdds = new QuickList <PendingNewEntry> [threadDispatcher == null ? 1: threadDispatcher.ThreadCount]; listeners = new QuickDictionary <CollidableReference, QuickList <PreviousCollisionData>, CollidableReferenceComparer>(initialListenerCapacity, pool); }
public Crafter() { id = new QuickDictionary <Item>(); itemPool = new Dictionary <Item, int>(); cheapest = new Dictionary <Item, int>(); Recipes = new List <Recipe>(); }
public DefaultPoseIntegratorCallbacks(IUnmanagedMemoryPool pool, Vector3?gravity = null, float linearDamping = .03f, float angularDamping = .03f) : this() { Gravity = gravity ?? new Vector3(0, -9.81f, 0); LinearDamping = linearDamping; AngularDamping = angularDamping; _angularDampingDictionary = new QuickDictionary <int, float, IntComparer>(1, pool); _linearDampingDictionary = new QuickDictionary <int, float, IntComparer>(1, pool); _linearDampingDictionary.Add(-1, LinearDamping, pool); _angularDampingDictionary.Add(-1, AngularDamping, pool); }
public unsafe void Render(DeviceContext context, Camera camera, Int2 screenResolution, Span <MeshInstance> instances, int start, int count) { //Examine the set of instances and batch them into groups using the same mesh data. var batches = new QuickDictionary <ulong, QuickList <MeshInstance>, PrimitiveComparer <ulong> >(16, meshCache.Pool); var end = start + count; for (int i = start; i < end; ++i) { ref var instance = ref instances[i]; ref var id = ref Unsafe.As <int, ulong>(ref instance.VertexStart);
/// <summary> /// Creates a new memory pool. /// </summary> /// <param name="memoryPoolSize">Size of the pool in elements.</param> /// <param name="idBufferPool">Buffer pool to use in the allocator. If null, the allocator picks.</param> /// <param name="allocationBufferPool">Buffer pool to use in the allocator. If null, the allocator picks.</param> /// <param name="tableBufferPool">Buffer pool to use in the allocator. If null, the allocator picks.</param> public Allocator(long memoryPoolSize, BufferPool<ulong> idBufferPool = null, BufferPool<Allocation> allocationBufferPool = null, BufferPool<int> tableBufferPool = null) { this.memoryPoolSize = memoryPoolSize; if (idBufferPool == null) idBufferPool = BufferPools<ulong>.Locking; if (allocationBufferPool == null) allocationBufferPool = BufferPools<Allocation>.Locking; if (tableBufferPool == null) tableBufferPool = BufferPools<int>.Locking; allocations = new QuickDictionary<ulong, Allocation>(idBufferPool, allocationBufferPool, tableBufferPool); }
///<summary> /// Cleans up the manifold. ///</summary> public override void CleanUp() { supplementData.Clear(); convex = null; for (int i = activePairTesters.Count - 1; i >= 0; --i) { activePairTesters.Values[i].CleanUp(); GiveBackTester(activePairTesters.Values[i]); } activePairTesters.Dispose(); activePairTesters = new QuickDictionary <TriangleIndices, TrianglePairTester>(BufferPools <TriangleIndices> .Locking, BufferPools <TrianglePairTester> .Locking, BufferPools <int> .Locking, 3); CleanUpOverlappingTriangles(); base.CleanUp(); }
public override void Initialize(Collidable newCollidableA, Collidable newCollidableB) { convex = newCollidableA as ConvexCollidable; mesh = newCollidableB as FullChunkObject; if (convex == null || mesh == null) { convex = newCollidableB as ConvexCollidable; mesh = newCollidableA as FullChunkObject; if (convex == null || mesh == null) { throw new ArgumentException("Inappropriate types used to initialize contact manifold."); } } ActivePairs = new QuickDictionary <Vector3i, GeneralConvexPairTester>(BufferPools <Vector3i> .Locking, BufferPools <GeneralConvexPairTester> .Locking, BufferPools <int> .Locking, 3); activePairsBackBuffer = new QuickDictionary <Vector3i, GeneralConvexPairTester>(BufferPools <Vector3i> .Locking, BufferPools <GeneralConvexPairTester> .Locking, BufferPools <int> .Locking, 3); }
public static void TestDictionaryResizing <TSpan, TPool>(TPool pool) where TSpan : ISpan <int> where TPool : IMemoryPool <int, TSpan> { Random random = new Random(5); QuickDictionary <int, int, TSpan, TSpan, TSpan, PrimitiveComparer <int> > .Create(pool, pool, pool, 2, 3, out var dictionary); Dictionary <int, int> controlDictionary = new Dictionary <int, int>(); for (int iterationIndex = 0; iterationIndex < 100000; ++iterationIndex) { if (random.NextDouble() < 0.7) { dictionary.Add(iterationIndex, iterationIndex, pool, pool, pool); controlDictionary.Add(iterationIndex, iterationIndex); } if (random.NextDouble() < 0.2) { var indexToRemove = random.Next(dictionary.Count); var toRemove = dictionary.Keys[indexToRemove]; dictionary.FastRemove(toRemove); controlDictionary.Remove(toRemove); } if (iterationIndex % 1000 == 0) { dictionary.EnsureCapacity(dictionary.Count * 3, pool, pool, pool); } else if (iterationIndex % 7777 == 0) { dictionary.Compact(pool, pool, pool); } } Debug.Assert(dictionary.Count == controlDictionary.Count); for (int i = 0; i < dictionary.Count; ++i) { Debug.Assert(controlDictionary.ContainsKey(dictionary.Keys[i])); } foreach (var element in controlDictionary.Keys) { Debug.Assert(dictionary.ContainsKey(element)); } dictionary.Dispose(pool, pool, pool); }
public override void Initialize(Collidable newCollidableA, Collidable newCollidableB) { convex = newCollidableA as ConvexCollidable; voxelGrid = newCollidableB as VoxelGrid; if (convex == null || voxelGrid == null) { convex = newCollidableB as ConvexCollidable; voxelGrid = newCollidableA as VoxelGrid; if (convex == null || voxelGrid == null) { throw new ArgumentException("Inappropriate types used to initialize contact manifold."); } } ActivePairs = new QuickDictionary <Int3, GeneralConvexPairTester>(BufferPools <Int3> .Locking, BufferPools <GeneralConvexPairTester> .Locking, BufferPools <int> .Locking, 3); activePairsBackBuffer = new QuickDictionary <Int3, GeneralConvexPairTester>(BufferPools <Int3> .Locking, BufferPools <GeneralConvexPairTester> .Locking, BufferPools <int> .Locking, 3); }
/// <summary> /// Creates a new memory pool. /// </summary> /// <param name="memoryPoolSize">Size of the pool in elements.</param> /// <param name="idBufferPool">Buffer pool to use in the allocator. If null, the allocator picks.</param> /// <param name="allocationBufferPool">Buffer pool to use in the allocator. If null, the allocator picks.</param> /// <param name="tableBufferPool">Buffer pool to use in the allocator. If null, the allocator picks.</param> public Allocator(long memoryPoolSize, BufferPool <ulong> idBufferPool = null, BufferPool <Allocation> allocationBufferPool = null, BufferPool <int> tableBufferPool = null) { this.memoryPoolSize = memoryPoolSize; if (idBufferPool == null) { idBufferPool = BufferPools <ulong> .Locking; } if (allocationBufferPool == null) { allocationBufferPool = BufferPools <Allocation> .Locking; } if (tableBufferPool == null) { tableBufferPool = BufferPools <int> .Locking; } allocations = new QuickDictionary <ulong, Allocation>(idBufferPool, allocationBufferPool, tableBufferPool); }
public static void TestDictionaryResizing() { Random random = new Random(5); UnsafeBufferPool<int> pool = new UnsafeBufferPool<int>(); QuickDictionary<int, int> dictionary = new QuickDictionary<int, int>(pool, pool, pool); Dictionary<int, int> controlDictionary = new Dictionary<int, int>(); for (int iterationIndex = 0; iterationIndex < 100000; ++iterationIndex) { if (random.NextDouble() < 0.7) { dictionary.Add(iterationIndex, iterationIndex); controlDictionary.Add(iterationIndex, iterationIndex); } if (random.NextDouble() < 0.2) { var indexToRemove = random.Next(dictionary.Count); var toRemove = dictionary.Keys[indexToRemove]; dictionary.FastRemove(toRemove); controlDictionary.Remove(toRemove); } if (iterationIndex % 1000 == 0) { dictionary.EnsureCapacity(dictionary.Count * 3); } else if (iterationIndex % 7777 == 0) { dictionary.Compact(); } } Assert.IsTrue(dictionary.Count == controlDictionary.Count); for (int i = 0; i < dictionary.Count; ++i) { Assert.IsTrue(controlDictionary.ContainsKey(dictionary.Keys[i])); } foreach (var element in controlDictionary.Keys) { Assert.IsTrue(dictionary.ContainsKey(element)); } }
public static void TestDictionaryResizing() { Random random = new Random(5); UnsafeBufferPool <int> pool = new UnsafeBufferPool <int>(); QuickDictionary <int, int> dictionary = new QuickDictionary <int, int>(pool, pool, pool); Dictionary <int, int> controlDictionary = new Dictionary <int, int>(); for (int iterationIndex = 0; iterationIndex < 100000; ++iterationIndex) { if (random.NextDouble() < 0.7) { dictionary.Add(iterationIndex, iterationIndex); controlDictionary.Add(iterationIndex, iterationIndex); } if (random.NextDouble() < 0.2) { var indexToRemove = random.Next(dictionary.Count); var toRemove = dictionary.Keys[indexToRemove]; dictionary.FastRemove(toRemove); controlDictionary.Remove(toRemove); } if (iterationIndex % 1000 == 0) { dictionary.EnsureCapacity(dictionary.Count * 3); } else if (iterationIndex % 7777 == 0) { dictionary.Compact(); } } Assert.IsTrue(dictionary.Count == controlDictionary.Count); for (int i = 0; i < dictionary.Count; ++i) { Assert.IsTrue(controlDictionary.ContainsKey(dictionary.Keys[i])); } foreach (var element in controlDictionary.Keys) { Assert.IsTrue(dictionary.ContainsKey(element)); } }
public unsafe void Render(DeviceContext context, Camera camera, Int2 screenResolution, MeshInstance[] instances, int start, int count) { //Examine the set of instances and batch them into groups using the same mesh data. var keyPool = meshCache.Pool.SpecializeFor <ulong>(); var valuePool = meshCache.Pool.SpecializeFor <QuickList <MeshInstance, Buffer <MeshInstance> > >(); var tablePool = meshCache.Pool.SpecializeFor <int>(); var instancePool = meshCache.Pool.SpecializeFor <MeshInstance>(); //(but is this ENOUGH generics?) QuickDictionary < ulong, QuickList <MeshInstance, Buffer <MeshInstance> >, Buffer <ulong>, Buffer <QuickList <MeshInstance, Buffer <MeshInstance> > >, Buffer <int>, PrimitiveComparer <ulong> > .Create(keyPool, valuePool, tablePool, 4, 3, out var batches); var end = start + count; for (int i = start; i < end; ++i) { ref var instance = ref instances[i]; ref var id = ref Unsafe.As <int, ulong>(ref instance.VertexStart);
public override void Update(double dt) { RigidTransform transform = new RigidTransform(mesh.Position); RigidTransform convexTransform = convex.WorldTransform; ContactRefresher.ContactRefresh(contacts, supplementData, ref convexTransform, ref transform, contactIndicesToRemove); RemoveQueuedContacts(); var overlaps = new QuickList<Vector3i>(BufferPools<Vector3i>.Thread); mesh.ChunkShape.GetOverlaps(mesh.Position, convex.BoundingBox, ref overlaps); var candidatesToAdd = new QuickList<ContactData>(BufferPools<ContactData>.Thread, BufferPool<int>.GetPoolIndex(overlaps.Count)); for (int i = 0; i < overlaps.Count; i++) { GeneralConvexPairTester manifold; if (!ActivePairs.TryGetValue(overlaps.Elements[i], out manifold)) { manifold = GetPair(ref overlaps.Elements[i]); } else { ActivePairs.FastRemove(overlaps.Elements[i]); } activePairsBackBuffer.Add(overlaps.Elements[i], manifold); ContactData contactCandidate; if (manifold.GenerateContactCandidate(out contactCandidate)) { candidatesToAdd.Add(ref contactCandidate); } } overlaps.Dispose(); for (int i = ActivePairs.Count - 1; i >= 0; i--) { ReturnPair(ActivePairs.Values[i]); ActivePairs.FastRemove(ActivePairs.Keys[i]); } var temp = ActivePairs; ActivePairs = activePairsBackBuffer; activePairsBackBuffer = temp; if (contacts.Count + candidatesToAdd.Count > 4) { var reducedCandidates = new QuickList<ContactData>(BufferPools<ContactData>.Thread, 3); ContactReducer.ReduceContacts(contacts, ref candidatesToAdd, contactIndicesToRemove, ref reducedCandidates); RemoveQueuedContacts(); for (int i = reducedCandidates.Count - 1; i >= 0; i--) { Add(ref reducedCandidates.Elements[i]); reducedCandidates.RemoveAt(i); } reducedCandidates.Dispose(); } else if (candidatesToAdd.Count > 0) { for (int i = 0; i < candidatesToAdd.Count; i++) { Add(ref candidatesToAdd.Elements[i]); } } candidatesToAdd.Dispose(); }
/// <summary> /// Creates a new allocator. /// </summary> /// <param name="capacity">Size of the memory handled by the allocator in elements.</param> /// <param name="initialAllocationCapacity">Estimated number of allocations to allocate room for in the internal structures.</param> /// <param name="pool">Pool to pull internal resources from.</param> public Allocator(long capacity, BufferPool pool, int initialAllocationCapacity = 128) { this.pool = pool; this.Capacity = capacity; allocations = new QuickDictionary <ulong, Allocation, PrimitiveComparer <ulong> >(initialAllocationCapacity, 2, pool); }
public override void Initialize(Collidable newCollidableA, Collidable newCollidableB) { convex = newCollidableA as ConvexCollidable; mesh = newCollidableB as FullChunkObject; if (convex == null || mesh == null) { convex = newCollidableB as ConvexCollidable; mesh = newCollidableA as FullChunkObject; if (convex == null || mesh == null) { throw new ArgumentException("Inappropriate types used to initialize contact manifold."); } } ActivePairs = new QuickDictionary<Vector3i, GeneralConvexPairTester>(BufferPools<Vector3i>.Locking, BufferPools<GeneralConvexPairTester>.Locking, BufferPools<int>.Locking, 3); activePairsBackBuffer = new QuickDictionary<Vector3i, GeneralConvexPairTester>(BufferPools<Vector3i>.Locking, BufferPools<GeneralConvexPairTester>.Locking, BufferPools<int>.Locking, 3); }
public Maker() { currentItems = new QuickDictionary <Item>(); craftJobs = new CraftJobs <Recipe>(); }
public override void Update( float dt ) { //Refresh the contact manifold for this frame. var transform = new RigidTransform( voxelBlob.Position ); var convexTransform = convex.WorldTransform; ContactRefresher.ContactRefresh( contacts, supplementData, ref convexTransform, ref transform, contactIndicesToRemove ); RemoveQueuedContacts(); //Collect the set of overlapped cell indices. //Not the fastest way to do this, but it's relatively simple and easy. var overlaps = new QuickList<Int3>( BufferPools<Int3>.Thread ); voxelBlob.Shape.GetOverlaps( voxelBlob.Position, convex.BoundingBox, ref overlaps ); var candidatesToAdd = new QuickList<ContactData>( BufferPools<ContactData>.Thread, BufferPool<int>.GetPoolIndex( overlaps.Count ) ); for( int i = 0; i < overlaps.Count; ++i ) { GeneralConvexPairTester manifold; if( !ActivePairs.TryGetValue( overlaps.Elements[i], out manifold ) ) { //This manifold did not previously exist. manifold = GetPair( ref overlaps.Elements[i] ); } else { //It did previously exist. ActivePairs.FastRemove( overlaps.Elements[i] ); } activePairsBackBuffer.Add( overlaps.Elements[i], manifold ); ContactData contactCandidate; if( manifold.GenerateContactCandidate( out contactCandidate ) ) { candidatesToAdd.Add( ref contactCandidate ); } } overlaps.Dispose(); //Any pairs remaining in the activePairs set no longer exist. Clean them up. for( int i = ActivePairs.Count - 1; i >= 0; --i ) { ReturnPair( ActivePairs.Values[i] ); ActivePairs.FastRemove( ActivePairs.Keys[i] ); } //Swap the pair sets. var temp = ActivePairs; ActivePairs = activePairsBackBuffer; activePairsBackBuffer = temp; //Check if adding the new contacts would overflow the manifold. if( contacts.Count + candidatesToAdd.Count > 4 ) { //Adding all the contacts would overflow the manifold. Reduce to the best subset. var reducedCandidates = new QuickList<ContactData>( BufferPools<ContactData>.Thread, 3 ); ContactReducer.ReduceContacts( contacts, ref candidatesToAdd, contactIndicesToRemove, ref reducedCandidates ); RemoveQueuedContacts(); for( int i = reducedCandidates.Count - 1; i >= 0; i-- ) { Add( ref reducedCandidates.Elements[i] ); reducedCandidates.RemoveAt( i ); } reducedCandidates.Dispose(); } else if( candidatesToAdd.Count > 0 ) { //Won't overflow the manifold, so just toss it in. for( int i = 0; i < candidatesToAdd.Count; i++ ) { Add( ref candidatesToAdd.Elements[i] ); } } candidatesToAdd.Dispose(); }
public override void Initialize( Collidable newCollidableA, Collidable newCollidableB ) { convex = newCollidableA as ConvexCollidable; voxelBlob = newCollidableB as VoxelBlob; if( convex == null || voxelBlob == null ) { convex = newCollidableB as ConvexCollidable; voxelBlob = newCollidableA as VoxelBlob; if( convex == null || voxelBlob == null ) throw new ArgumentException( "Inappropriate types used to initialize contact manifold." ); } ActivePairs = new QuickDictionary<Int3, GeneralConvexPairTester>( BufferPools<Int3>.Locking, BufferPools<GeneralConvexPairTester>.Locking, BufferPools<int>.Locking, 3 ); activePairsBackBuffer = new QuickDictionary<Int3, GeneralConvexPairTester>( BufferPools<Int3>.Locking, BufferPools<GeneralConvexPairTester>.Locking, BufferPools<int>.Locking, 3 ); }
public static void Test() { //var random = new Random(5); //var comparer = new CollidablePairComparer(); //for (int i = 0; i < 10000; ++i) //{ // var a = new CollidableReference((CollidableMobility)random.Next(3), random.Next(1 << 30)); // var b = new CollidableReference((CollidableMobility)random.Next(3), random.Next(1 << 30)); // var pair1 = new CollidablePair(a, b); // var pair2 = new CollidablePair(b, a); // Debug.Assert(comparer.Hash(ref pair1) == comparer.Hash(ref pair2)); // Debug.Assert(comparer.Equals(ref pair1, ref pair2)); //} //for (int i = 0; i < 10000; ++i) //{ // var a = new CollidableReference((CollidableMobility)random.Next(3), random.Next(1 << 30)); // var b = new CollidableReference((CollidableMobility)random.Next(3), random.Next(1 << 30)); // var pair1 = new CollidablePair(a, b); // CollidablePair pair2; // do // { // var a2 = new CollidableReference((CollidableMobility)random.Next(3), random.Next(1 << 30)); // var b2 = new CollidableReference((CollidableMobility)random.Next(3), random.Next(1 << 30)); // pair2 = new CollidablePair(a2, b2); // } while ( // (pair2.A.Packed == pair1.A.Packed && pair2.B.Packed == pair1.B.Packed) || // (pair2.B.Packed == pair1.A.Packed && pair2.A.Packed == pair1.B.Packed)); // Debug.Assert(!comparer.Equals(ref pair1, ref pair2)); //} const int iterationCount = 1000; const int perLayerCollidableCount = 900; const int layerCount = 10; int[] creationRemap = new int[perLayerCollidableCount * (layerCount - 1)]; int[] lookupRemap = new int[creationRemap.Length]; for (int i = 0; i < creationRemap.Length; ++i) { creationRemap[i] = i; lookupRemap[i] = i; } BufferPool pool = new BufferPool(); var dictionary = new QuickDictionary <CollidablePair, int, CollidablePairComparer>(creationRemap.Length, 1, pool); var random = new Random(5); for (int i = 0; i < creationRemap.Length - 1; ++i) { { var temp = creationRemap[i]; var swapTarget = random.Next(i + 1, creationRemap.Length); creationRemap[i] = creationRemap[swapTarget]; creationRemap[swapTarget] = temp; } { var temp = lookupRemap[i]; var swapTarget = random.Next(i + 1, lookupRemap.Length); lookupRemap[i] = lookupRemap[swapTarget]; lookupRemap[swapTarget] = temp; } } int accumulator = 0; double totalTime = 0; const int warmupIterations = 128; for (int iterationIndex = 0; iterationIndex < iterationCount + warmupIterations; ++iterationIndex) { dictionary.Clear(); for (int i = 0; i < creationRemap.Length; ++i) { var index = creationRemap[i]; var pair = new CollidablePair { A = new CollidableReference(CollidableMobility.Kinematic, index), B = new CollidableReference(CollidableMobility.Dynamic, index + perLayerCollidableCount) }; dictionary.AddUnsafely(ref pair, index); } CacheBlaster.Blast(); //Prewarm the remap into cache to more closely mirror the behavior in the narrow phase. for (int i = 0; i < lookupRemap.Length; ++i) { accumulator += lookupRemap[i]; } var start = Stopwatch.GetTimestamp(); for (int i = 0; i < lookupRemap.Length; ++i) { var collidableIndex = lookupRemap[i]; var pair = new CollidablePair { A = new CollidableReference(CollidableMobility.Kinematic, collidableIndex), B = new CollidableReference(CollidableMobility.Dynamic, collidableIndex + perLayerCollidableCount) }; var dictionaryIndex = dictionary.IndexOf(ref pair); accumulator += dictionaryIndex; } var end = Stopwatch.GetTimestamp(); if (iterationIndex >= warmupIterations) { totalTime += (end - start) / (double)Stopwatch.Frequency; } } Console.WriteLine($"Time per lookup (ns): {1e9 * totalTime / (iterationCount * creationRemap.Length)}, acc{accumulator}"); pool.Clear(); }
public override void Update(float dt) { //Refresh the contact manifold for this frame. var transform = new RigidTransform(voxelGrid.Position); var convexTransform = convex.WorldTransform; ContactRefresher.ContactRefresh(contacts, supplementData, ref convexTransform, ref transform, contactIndicesToRemove); RemoveQueuedContacts(); //Collect the set of overlapped cell indices. //Not the fastest way to do this, but it's relatively simple and easy. var overlaps = new QuickList <Int3>(BufferPools <Int3> .Thread); voxelGrid.Shape.GetOverlaps(voxelGrid.Position, convex.BoundingBox, ref overlaps); var candidatesToAdd = new QuickList <ContactData>(BufferPools <ContactData> .Thread, BufferPool <int> .GetPoolIndex(overlaps.Count)); for (int i = 0; i < overlaps.Count; ++i) { GeneralConvexPairTester manifold; if (!ActivePairs.TryGetValue(overlaps.Elements[i], out manifold)) { //This manifold did not previously exist. manifold = GetPair(ref overlaps.Elements[i]); } else { //It did previously exist. ActivePairs.FastRemove(overlaps.Elements[i]); } activePairsBackBuffer.Add(overlaps.Elements[i], manifold); ContactData contactCandidate; if (manifold.GenerateContactCandidate(out contactCandidate)) { candidatesToAdd.Add(ref contactCandidate); } } overlaps.Dispose(); //Any pairs remaining in the activePairs set no longer exist. Clean them up. for (int i = ActivePairs.Count - 1; i >= 0; --i) { ReturnPair(ActivePairs.Values[i]); ActivePairs.FastRemove(ActivePairs.Keys[i]); } //Swap the pair sets. var temp = ActivePairs; ActivePairs = activePairsBackBuffer; activePairsBackBuffer = temp; //Check if adding the new contacts would overflow the manifold. if (contacts.Count + candidatesToAdd.Count > 4) { //Adding all the contacts would overflow the manifold. Reduce to the best subset. var reducedCandidates = new QuickList <ContactData>(BufferPools <ContactData> .Thread, 3); ContactReducer.ReduceContacts(contacts, ref candidatesToAdd, contactIndicesToRemove, ref reducedCandidates); RemoveQueuedContacts(); for (int i = reducedCandidates.Count - 1; i >= 0; i--) { Add(ref reducedCandidates.Elements[i]); reducedCandidates.RemoveAt(i); } reducedCandidates.Dispose(); } else if (candidatesToAdd.Count > 0) { //Won't overflow the manifold, so just toss it in. for (int i = 0; i < candidatesToAdd.Count; i++) { Add(ref candidatesToAdd.Elements[i]); } } candidatesToAdd.Dispose(); }