void Initialize<U>(int initialCapacity, ref U allocator, int disposeSentinelStackDepth) where U : unmanaged, AllocatorManager.IAllocator { var totalSize = UnsafeUtility.SizeOf<T>() * (long)initialCapacity; #if ENABLE_UNITY_COLLECTIONS_CHECKS CheckAllocator((Allocator)allocator.Handle.Value); CheckInitialCapacity(initialCapacity); CollectionHelper.CheckIsUnmanaged<T>(); CheckTotalSize(initialCapacity, totalSize); DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, disposeSentinelStackDepth, (Allocator)allocator.Handle.Value); if (s_staticSafetyId.Data == 0) { CreateStaticSafetyId(); } AtomicSafetyHandle.SetStaticSafetyId(ref m_Safety, s_staticSafetyId.Data); m_SafetyIndexHint = (allocator.Handle).AddSafetyHandle(m_Safety); if(m_SafetyIndexHint != AllocatorManager.AllocatorHandle.InvalidChildSafetyHandleIndex) DisposeSentinel.Clear(ref m_DisposeSentinel); #endif m_ListData = UnsafeList.Create(UnsafeUtility.SizeOf<T>(), UnsafeUtility.AlignOf<T>(), initialCapacity, ref allocator); m_DeprecatedAllocator = (Allocator)allocator.Handle.Value; #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.SetBumpSecondaryVersionOnScheduleWrite(m_Safety, true); #endif }
private NativeRoutines(int initialCapacity, Allocator allocator, int disposeSentinelStackDepth) { var totalSize = (long)sizeof(T) * initialCapacity; #if ENABLE_UNITY_COLLECTIONS_CHECKS // Native allocation is only valid for Temp, Job and Persistent. if (allocator <= Allocator.None) { throw new ArgumentException("Allocator must be Temp, TempJob or Persistent", nameof(allocator)); } if (totalSize > int.MaxValue) { throw new ArgumentOutOfRangeException($"Capacity has exceeded {int.MaxValue.ToString()} bytes"); } DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, disposeSentinelStackDepth, allocator); #endif m_ListData = UnsafeList.Create(UnsafeUtility.SizeOf <T>(), UnsafeUtility.AlignOf <T>(), initialCapacity, allocator); m_AllocatorLabel = allocator; #if UNITY_2019_3_OR_NEWER && ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.SetBumpSecondaryVersionOnScheduleWrite(m_Safety, true); #endif }
public NativePriorityQueue(int initialCapacity, Allocator allocator) { var totalSize = UnsafeUtility.SizeOf <Node>() * (long)initialCapacity; #if ENABLE_UNITY_COLLECTIONS_CHECKS if (allocator <= Allocator.None) { throw new ArgumentException("Allocator must be Temp, TempJob, or Persistent", "allocator"); } if (initialCapacity < 0) { throw new ArgumentOutOfRangeException(nameof(initialCapacity), $"{nameof(initialCapacity)} must be >= 0"); } if (!UnsafeUtility.IsBlittable <T>()) { throw new ArgumentException($"{typeof(T)} used in {nameof(NativePriorityQueue<T>)} must be blittable"); } if (totalSize > int.MaxValue) { throw new ArgumentOutOfRangeException(nameof(initialCapacity), $"Capacity * sizeof(T) cannot exceed {int.MaxValue} bytes"); } DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 0, allocator); AtomicSafetyHandle.SetBumpSecondaryVersionOnScheduleWrite(m_Safety, true); #endif int nodeSize = UnsafeUtility.SizeOf <Node>(); int nodeAlign = UnsafeUtility.AlignOf <Node>(); _nodes = UnsafeList.Create(nodeSize, nodeAlign, initialCapacity, allocator); _nodes->Add <Node>(default); }
/// <summary> /// Safely disposes of this container and deallocates its memory when the jobs that use it have completed. /// </summary> /// <remarks>You can call this function dispose of the container immediately after scheduling the job. Pass /// the [JobHandle](https://docs.unity3d.com/ScriptReference/Unity.Jobs.JobHandle.html) returned by /// the [Job.Schedule](https://docs.unity3d.com/ScriptReference/Unity.Jobs.IJobExtensions.Schedule.html) /// method using the `jobHandle` parameter so the job scheduler can dispose the container after all jobs /// using it have run.</remarks> /// <param name="inputDeps">The job handle or handles for any scheduled jobs that use this container.</param> /// <returns>A new job handle containing the prior handles as well as the handle for the job that deletes /// the container.</returns> public JobHandle Dispose(JobHandle inputDeps) { #if ENABLE_UNITY_COLLECTIONS_CHECKS // [DeallocateOnJobCompletion] is not supported, but we want the deallocation // to happen in a thread. DisposeSentinel needs to be cleared on main thread. // AtomicSafetyHandle can be destroyed after the job was scheduled (Job scheduling // will check that no jobs are writing to the container). DisposeSentinel.Clear(ref m_DisposeSentinel); var jobHandle = new NativeListDisposeJob { Data = new NativeListDispose { m_ListData = m_ListData, m_Safety = m_Safety } }.Schedule(inputDeps); AtomicSafetyHandle.Release(m_Safety); #else var jobHandle = new NativeListDisposeJob { Data = new NativeListDispose { m_ListData = m_ListData } }.Schedule(inputDeps); #endif m_ListData = null; return(jobHandle); }
private static void CheckAllocated(UnsafeList *listData) { if (listData == null || !listData->IsCreated) { throw new Exception($"Expected {nameof(listData)} to be allocated."); } }
private static void CheckNull(UnsafeList *listData) { if (listData == null) { throw new Exception($"Expected {nameof(listData)} to not be null."); } }
HashedVertices(int vertexCapacity, int chainedIndicesCapacity, Allocator allocator, int disposeSentinelStackDepth) { #if ENABLE_UNITY_COLLECTIONS_CHECKS // Native allocation is only valid for Temp, Job and Persistent. CheckAllocator(allocator); CheckArgPositive(chainedIndicesCapacity); DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, disposeSentinelStackDepth, allocator); #if UNITY_2020_1_OR_NEWER if (s_staticSafetyId.Data == 0) { CreateStaticSafetyId(); } AtomicSafetyHandle.SetStaticSafetyId(ref m_Safety, s_staticSafetyId.Data); #endif #endif #if ENABLE_UNITY_COLLECTIONS_CHECKS DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 0, allocator); #endif m_AllocatorLabel = allocator; var hashTableMemSize = (ushort)(kHashTableSize + 1) * UnsafeUtility.SizeOf <ushort>(); m_HashTable = UnsafeUtility.Malloc(hashTableMemSize, UnsafeUtility.AlignOf <ushort>(), m_AllocatorLabel); UnsafeUtility.MemClear(m_HashTable, hashTableMemSize); m_Vertices = UnsafeList.Create(UnsafeUtility.SizeOf <float3>(), UnsafeUtility.AlignOf <float3>(), vertexCapacity, allocator); m_ChainedIndices = UnsafeList.Create(UnsafeUtility.SizeOf <ushort>(), UnsafeUtility.AlignOf <ushort>(), chainedIndicesCapacity, allocator); #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.SetBumpSecondaryVersionOnScheduleWrite(m_Safety, true); #endif }
NativeList(int initialCapacity, Allocator allocator, int disposeSentinelStackDepth) { var totalSize = UnsafeUtility.SizeOf <T>() * (long)initialCapacity; #if ENABLE_UNITY_COLLECTIONS_CHECKS // Native allocation is only valid for Temp, Job and Persistent. if (allocator <= Allocator.None) { throw new ArgumentException("Allocator must be Temp, TempJob or Persistent", nameof(allocator)); } if (initialCapacity < 0) { throw new ArgumentOutOfRangeException(nameof(initialCapacity), "Capacity must be >= 0"); } //CollectionHelper.CheckIsUnmanaged<T>(); // Make sure we cannot allocate more than int.MaxValue (2,147,483,647 bytes) // because the underlying UnsafeUtility.Malloc is expecting a int. // TODO: change UnsafeUtility.Malloc to accept a UIntPtr length instead to match C++ API if (totalSize > int.MaxValue) { throw new ArgumentOutOfRangeException(nameof(initialCapacity), $"Capacity * sizeof(T) cannot exceed {int.MaxValue} bytes"); } DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, disposeSentinelStackDepth, allocator); #endif m_ListData = UnsafeList.Create(UnsafeUtility.SizeOf <T>(), UnsafeUtility.AlignOf <T>(), initialCapacity, allocator); m_DeprecatedAllocator = allocator; #if UNITY_2019_3_OR_NEWER && ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.SetBumpSecondaryVersionOnScheduleWrite(m_Safety, true); #endif }
private static void CheckNotAllocated(UnsafeList *listData) { if (listData != null && listData->IsCreated) { throw new Exception($"Expected {nameof(listData)} to not be allocated."); } }
public static void CopyTo <T>(UnsafeList *list, void *destination, int destinationIndex) where T : unmanaged { if (destination == null) { throw new ArgumentNullException(nameof(destination)); } if (destinationIndex < 0) { throw new ArgumentOutOfRangeException(ThrowHelper.ArgumentOutOfRange_Index); } UDebug.Assert(list != null); UDebug.Assert(list->_items.Ptr != null); UDebug.Assert(typeof(T).TypeHandle.Value == list->_typeHandle); int numToCopy = list->_count; if (numToCopy == 0) { return; } UnsafeBuffer.CopyTo <T>(list->_items, 0, destination, destinationIndex, numToCopy); }
public JobHandle Dispose(JobHandle inputDeps) { #if ENABLE_UNITY_COLLECTIONS_CHECKS DisposeSentinel.Clear(ref m_DisposeSentinel); var jobHandle = new NativePriorityQueueDisposeJob { Data = new NativePriorityQueueDispose { m_ListData = _nodes, m_Safety = m_Safety } }.Schedule(inputDeps); AtomicSafetyHandle.Release(m_Safety); #else var jobHandle = new NativePriorityQueueDisposeJob { Data = new NativePriorityQueueDispose { m_ListData = _nodes } }.Schedule(inputDeps); #endif _nodes = null; return(jobHandle); }
public ConcurrentConnectionQueue(NativeList <int> queue) { #if ENABLE_UNITY_COLLECTIONS_CHECKS m_Safety = NativeListUnsafeUtility.GetAtomicSafetyHandle(ref queue); AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); #endif m_ConnectionEventHeadTail = (UnsafeList *)NativeListUnsafeUtility.GetInternalListDataPtrUnchecked(ref queue); }
public static Enumerator <T> GetEnumerator <T>(UnsafeList *list) where T : unmanaged { UDebug.Assert(list != null); UDebug.Assert(list->_items.Ptr != null); UDebug.Assert(typeof(T).TypeHandle.Value == list->_typeHandle); return(new Enumerator <T>(list->_items, 0, list->_count)); }
private unsafe static void CheckPtrInitialized(UnsafeList *ptr, int index) { if (ptr == null || !ptr->IsCreated) { throw new IndexOutOfRangeException($"Index {index} has not been initialized."); } }
/// <summary> /// Disposes of this container and deallocates its memory immediately. /// </summary> public void Dispose() { #if ENABLE_UNITY_COLLECTIONS_CHECKS DisposeSentinel.Dispose(ref m_Safety, ref m_DisposeSentinel); #endif UnsafeList.Destroy(m_ListData); m_ListData = null; }
public static int LastIndexOf <T>(UnsafeList *list, T item) where T : unmanaged, IEquatable <T> { UDebug.Assert(list != null); UDebug.Assert(list->_items.Ptr != null); UDebug.Assert(typeof(T).TypeHandle.Value == list->_typeHandle); return(UnsafeBuffer.LastIndexOf(list->_items, item, list->_count - 1, list->_count)); }
public static void SetCapacity(UnsafeList *list, int capacity) { Assert.Check(list != null); if (list->_items.Dynamic == false) { throw new InvalidOperationException(LIST_FIXED_CANT_CHANGE_CAPACITY); } // no change in capacity if (capacity == list->_items.Length) { return; } // tried to set to zero or negative, so free items if (capacity <= 0) { // have to make sure to set count to 0 list->_count = 0; // and clear memory for items if (list->_items.Ptr != null) { UnsafeBuffer.Free(&list->_items); } return; } // allocate new items UnsafeBuffer newItems = default; UnsafeBuffer.InitDynamic(&newItems, capacity, list->_items.Stride); // if have anything in list, copy it if (list->_count > 0) { // also make sure that count is // not larger than the new capacity if (list->_count > capacity) { list->_count = capacity; } // copy over elements UnsafeBuffer.Copy(list->_items, 0, newItems, 0, list->_count); } // if an existing buffer was here, free it if (list->_items.Ptr != null) { UnsafeBuffer.Free(&list->_items); } // assign new buffer list->_items = newItems; }
public BlocksOfSize(int dummy) { m_Blocks = (UnsafeList *)Memory.Unmanaged.Allocate( UnsafeUtility.SizeOf <UnsafeList>(), UnsafeUtility.AlignOf <UnsafeList>(), Allocator.Persistent); UnsafeUtility.MemClear(m_Blocks, UnsafeUtility.SizeOf <UnsafeList>()); m_Blocks->Allocator = Allocator.Persistent; }
// Add but make the assumption we're not growing any list public unsafe static ushort Add(ushort *hashTable, UnsafeList *chainedIndices, UnsafeList *vertices, float3 vertex) { var centerIndex = new int3((int)(vertex.x / HashedVertices.kCellSize), (int)(vertex.y / HashedVertices.kCellSize), (int)(vertex.z / HashedVertices.kCellSize)); var offsets = stackalloc int3[] { new int3(-1, -1, -1), new int3(-1, -1, 0), new int3(-1, -1, +1), new int3(-1, 0, -1), new int3(-1, 0, 0), new int3(-1, 0, +1), new int3(-1, +1, -1), new int3(-1, +1, 0), new int3(-1, +1, +1), new int3(0, -1, -1), new int3(0, -1, 0), new int3(0, -1, +1), new int3(0, 0, -1), new int3(0, 0, 0), new int3(0, 0, +1), new int3(0, +1, -1), new int3(0, +1, 0), new int3(0, +1, +1), new int3(+1, -1, -1), new int3(+1, -1, 0), new int3(+1, -1, +1), new int3(+1, 0, -1), new int3(+1, 0, 0), new int3(+1, 0, +1), new int3(+1, +1, -1), new int3(+1, +1, 0), new int3(+1, +1, +1) }; float3 *verticesPtr = (float3 *)vertices->Ptr; ushort closestVertexIndex = ushort.MaxValue; for (int i = 0; i < 3 * 3 * 3; i++) { var index = centerIndex + offsets[i]; var chainIndex = ((int)hashTable[GetHash(index)]) - 1; { float closestDistance = CSGConstants.kSqrVertexEqualEpsilon; while (chainIndex != -1) { var nextChainIndex = ((int)((ushort *)chainedIndices->Ptr)[chainIndex]) - 1; var sqrDistance = math.lengthsq(verticesPtr[chainIndex] - vertex); if (sqrDistance < closestDistance) { closestVertexIndex = (ushort)chainIndex; closestDistance = sqrDistance; } chainIndex = nextChainIndex; } } } if (closestVertexIndex != ushort.MaxValue) { return(closestVertexIndex); } // Add Unique vertex { var hashCode = GetHash(centerIndex); var prevChainIndex = hashTable[hashCode]; var newChainIndex = chainedIndices->Length; vertices->Add(vertex); chainedIndices->Add((ushort)prevChainIndex); hashTable[(int)hashCode] = (ushort)(newChainIndex + 1); return((ushort)newChainIndex); } }
public void AddComponents(UnsafeList *sortedEntityBatchList, ref ComponentTypes types) { Assert.IsFalse(types.ChunkComponentCount > 0); // Reverse order so that batch indices do not change while iterating. for (int i = sortedEntityBatchList->Length - 1; i >= 0; i--) { AddComponents(((EntityBatchInChunk *)sortedEntityBatchList->Ptr)[i], types); } }
public void RemoveComponent(UnsafeList *sortedEntityBatchList, ComponentType type) { Assert.IsFalse(type.IsChunkComponent); // Reverse order so that batch indices do not change while iterating. for (int i = sortedEntityBatchList->Length - 1; i >= 0; i--) { RemoveComponent(((EntityBatchInChunk *)sortedEntityBatchList->Ptr)[i], type); } }
public void Dispose() { #if ENABLE_UNITY_COLLECTIONS_CHECKS DisposeSentinel.Dispose(ref m_Safety, ref m_DisposeSentinel); #endif UnsafeList.Destroy(m_Vertices); m_Vertices = null; UnsafeList.Destroy(m_ChainedIndices); m_ChainedIndices = null; UnsafeUtility.Free(m_HashTable, m_AllocatorLabel); }
public void Dispose() { UnsafeList.Destroy(elements); elements = null; UnsafeList.Destroy(lookup); lookup = null; UnsafeList.Destroy(nodes); nodes = null; #if ENABLE_UNITY_COLLECTIONS_CHECKS DisposeSentinel.Dispose(ref safetyHandle, ref disposeSentinel); #endif }
/// <summary> /// Destroys list. /// </summary> public static void Destroy(UnsafeList *listData) { #if ENABLE_UNITY_COLLECTIONS_CHECKS if (listData == null) { throw new Exception("UnsafeList has yet to be created or has been destroyed!"); } #endif var allocator = listData->Allocator; listData->Dispose(); UnsafeUtility.Free(listData, allocator); }
public static bool RemoveUnordered <T>(UnsafeList *list, T item) where T : unmanaged, IEquatable <T> { int index = IndexOf(list, item); if (index < 0) { return(false); } RemoveAtUnordered(list, index); return(true); }
HashedVertices(int vertexCapacity, int chainedIndicesCapacity, Allocator allocator = Allocator.Persistent) { #if ENABLE_UNITY_COLLECTIONS_CHECKS DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 0, allocator); #endif m_AllocatorLabel = allocator; var hashTableMemSize = (ushort)(kHashTableSize + 1) * UnsafeUtility.SizeOf <ushort>(); m_HashTable = UnsafeUtility.Malloc(hashTableMemSize, UnsafeUtility.AlignOf <ushort>(), m_AllocatorLabel); UnsafeUtility.MemClear(m_HashTable, hashTableMemSize); m_Vertices = UnsafeList.Create(UnsafeUtility.SizeOf <float3>(), UnsafeUtility.AlignOf <float3>(), vertexCapacity, allocator); m_ChainedIndices = UnsafeList.Create(UnsafeUtility.SizeOf <ushort>(), UnsafeUtility.AlignOf <ushort>(), chainedIndicesCapacity, allocator); }
public void Query(NativeOctree <T> tree, AABB bounds, NativeList <OctElement <T> > results) { this.tree = tree; this.bounds = bounds; count = 0; // Get pointer to inner list data for faster writing fastResults = (UnsafeList *)NativeListUnsafeUtility.GetInternalListDataPtrUnchecked(ref results); RecursiveRangeQuery(tree.bounds, false, 1, 1); fastResults->Length = count; }
public static bool Remove <T>(UnsafeList *list, T item) where T : unmanaged, IEquatable <T> { Assert.Check(list != null); int index = IndexOf <T>(list, item); if (index < 0) { return(false); } RemoveAt(list, index); return(true); }
public static T *GetPtr <T>(UnsafeList *list, int index) where T : unmanaged { Assert.Check(list != null); // cast to uint trick, which eliminates < 0 check if ((uint)index >= (uint)list->_count) { throw new IndexOutOfRangeException(); } var items = list->_items; return((T *)UnsafeBuffer.Element(items.Ptr, index, items.Stride)); }
public unsafe static void ReplaceIfExists(ushort *hashTable, UnsafeList *chainedIndices, UnsafeList *vertices, float3 vertex) { var centerIndex = new int3((int)(vertex.x / HashedVertices.kCellSize), (int)(vertex.y / HashedVertices.kCellSize), (int)(vertex.z / HashedVertices.kCellSize)); var offsets = stackalloc int3[] { new int3(-1, -1, -1), new int3(-1, -1, 0), new int3(-1, -1, +1), new int3(-1, 0, -1), new int3(-1, 0, 0), new int3(-1, 0, +1), new int3(-1, +1, -1), new int3(-1, +1, 0), new int3(-1, +1, +1), new int3(0, -1, -1), new int3(0, -1, 0), new int3(0, -1, +1), new int3(0, 0, -1), new int3(0, 0, 0), new int3(0, 0, +1), new int3(0, +1, -1), new int3(0, +1, 0), new int3(0, +1, +1), new int3(+1, -1, -1), new int3(+1, -1, 0), new int3(+1, -1, +1), new int3(+1, 0, -1), new int3(+1, 0, 0), new int3(+1, 0, +1), new int3(+1, +1, -1), new int3(+1, +1, 0), new int3(+1, +1, +1) }; float3 *verticesPtr = (float3 *)vertices->Ptr; ushort closestVertexIndex = ushort.MaxValue; for (int i = 0; i < 3 * 3 * 3; i++) { var index = centerIndex + offsets[i]; var chainIndex = ((int)hashTable[GetHash(index)]) - 1; { float closestDistance = CSGConstants.kSqrVertexEqualEpsilon; while (chainIndex != -1) { var nextChainIndex = ((int)((ushort *)chainedIndices->Ptr)[chainIndex]) - 1; var sqrDistance = math.lengthsq(verticesPtr[chainIndex] - vertex); if (sqrDistance < closestDistance) { closestVertexIndex = (ushort)chainIndex; closestDistance = sqrDistance; } chainIndex = nextChainIndex; } } } if (closestVertexIndex == ushort.MaxValue) { return; } verticesPtr[closestVertexIndex] = vertex; }