/// <summary> /// Schedule the job for execution on worker threads. /// list.Length is used as the iteration count. /// Note that it is required to embed the list on the job struct as well. /// </summary> /// <param name="jobData">The job and data to schedule.</param> /// <param name="list">list.Length is used as the iteration count.</param> /// <param name="innerloopBatchCount">Granularity in which workstealing is performed. A value of 32, means the job queue will steal 32 iterations and then perform them in an efficient inner loop.</param> /// <param name="dependsOn">Dependencies are used to ensure that a job executes on workerthreads after the dependency has completed execution. Making sure that two jobs reading or writing to same data do not run in parallel.</param> /// <returns>JobHandle The handle identifying the scheduled job. Can be used as a dependency for a later job or ensure completion on the main thread.</returns> public static unsafe JobHandle Schedule <T, U>(this T jobData, NativeList <U> list, int innerloopBatchCount, JobHandle dependsOn = new JobHandle()) where T : struct, IJobParallelForDefer where U : struct { void *atomicSafetyHandlePtr = null; // Calculate the deferred atomic safety handle before constructing JobScheduleParameters so // DOTS Runtime can validate the deferred list statically similar to the reflection based // validation in Big Unity. #if ENABLE_UNITY_COLLECTIONS_CHECKS var safety = NativeListUnsafeUtility.GetAtomicSafetyHandle(ref list); atomicSafetyHandlePtr = UnsafeUtility.AddressOf(ref safety); #endif var scheduleParams = new JobsUtility.JobScheduleParameters( UnsafeUtility.AddressOf(ref jobData), JobParallelForDeferProducer <T> .Initialize(), dependsOn, #if UNITY_2020_2_OR_NEWER ScheduleMode.Parallel #else ScheduleMode.Batched #endif ); return(JobsUtility.ScheduleParallelForDeferArraySize(ref scheduleParams, innerloopBatchCount, NativeListUnsafeUtility.GetInternalListDataPtrUnchecked(ref list), atomicSafetyHandlePtr)); }
public void RangeQuery(AABB bounds, NativeList <OctElement <T> > results) { var targetBounds = new Aabb { Min = bounds.Min, Max = bounds.Max }; var outputResults = (UnsafeList *)NativeListUnsafeUtility.GetInternalListDataPtrUnchecked(ref results); if (Data->TotalElements > outputResults->Capacity) { // todo: find out why its possible to return more elements than exists // should be able to use 'TotalElements' for capacity here. 10/100 work, // but 1000 yields 1012-1018 elements... outputResults->Resize <OctElement <T> >(Data->TotalElements * 2); } var resultsPtr = (byte *)outputResults->Ptr; var nodesPtr = (byte *)Data->Nodes->Ptr; var elementPtr = (byte *)Data->Elements->Ptr; var quadPtr = (byte *)Data->Quads->Ptr; var quadCount = Data->Quads->Length; var maxLeaves = quadCount * 16 * Data->TotalDepth; int resultCount = 0; int containCount = 0; int overlapCount = 0; // Work around c# enforcing use of Span<T>. var useStack = maxLeaves <= 256; var size = useStack ? sizeof(int) * maxLeaves : 1; var ptr1 = stackalloc int[size]; var ptr2 = stackalloc int[size]; size = sizeof(int) * maxLeaves; var containOffsets = useStack ? ptr1 : (int *)UnsafeUtility.Malloc(size, sizeof(int), Allocator.Temp); var overlapOffsets = useStack ? ptr2 : (int *)UnsafeUtility.Malloc(size, sizeof(int), Allocator.Temp); for (int i = 0; i < quadCount; i++) { QuadGroup quad = *(QuadGroup *)(quadPtr + i * sizeof(QuadGroup)); bool4 isContainedA = quad.Bounds.ContainedBy(targetBounds); bool4 isOverlapA = quad.Bounds.OverlappedBy(targetBounds); bool4 skipMaskA = !isContainedA & !isOverlapA; bool4 containedLeafMaskA = !skipMaskA & isContainedA; bool4 intersectedMaskA = !containedLeafMaskA & isOverlapA; containCount = compress(containOffsets, containCount, quad.Offsets, containedLeafMaskA); overlapCount = compress(overlapOffsets, overlapCount, quad.Offsets, intersectedMaskA); } for (int i = 0; i < containCount; i++) { ref var node = ref UnsafeUtilityEx.ArrayElementAsRef <OctNode>(nodesPtr, containOffsets[i]); var src = elementPtr + node.firstChildIndex * UnsafeUtility.SizeOf <OctElement <T> >(); var dst = resultsPtr + resultCount * UnsafeUtility.SizeOf <OctElement <T> >(); UnsafeUtility.MemCpy(dst, src, node.count * UnsafeUtility.SizeOf <OctElement <T> >()); resultCount += node.count; }
public ConcurrentConnectionQueue(NativeList <int> queue) { #if ENABLE_UNITY_COLLECTIONS_CHECKS m_Safety = NativeListUnsafeUtility.GetAtomicSafetyHandle(ref queue); AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); #endif m_ConnectionEventHeadTail = (ListData *)NativeListUnsafeUtility.GetInternalListDataPtrUnchecked(ref queue); }
/// <summary> /// Disposes of this list and deallocates its memory immediately. /// </summary> public void Dispose() { #if ENABLE_UNITY_COLLECTIONS_CHECKS DisposeSentinel.Dispose(ref m_Safety, ref m_DisposeSentinel); #endif NativeListUnsafeUtility.DeallocateList(m_ListData, m_Allocator); m_ListData = null; }
/// <summary> /// Returns parallel writer instance. /// </summary> /// <returns>Parallel writer instance.</returns> public unsafe static ParallelWriterExt <T> AsParallelWriterExt <T>(this NativeList <T> list) where T : struct { #if ENABLE_UNITY_COLLECTIONS_CHECKS var m_Safety = NativeListUnsafeUtility.GetAtomicSafetyHandle(ref list); var m_ListData = list.GetUnsafeList(); return(new ParallelWriterExt <T>(m_ListData->Ptr, m_ListData, ref m_Safety)); #else return(new ParallelWriterExt <T>(m_ListData->Ptr, m_ListData)); #endif }
unsafe public static JobHandle Schedule <T, U>(this T jobData, NativeList <U> list, int innerloopBatchCount, JobHandle dependsOn = new JobHandle()) where T : struct, IJobParallelFor where U : struct { var scheduleParams = new JobsUtility.JobScheduleParameters(UnsafeUtility.AddressOf(ref jobData), ParallelForJobStruct <T> .Initialize(), dependsOn, ScheduleMode.Batched); void *atomicSafetyHandlePtr = null; #if ENABLE_UNITY_COLLECTIONS_CHECKS var safety = NativeListUnsafeUtility.GetAtomicSafetyHandle(ref list); atomicSafetyHandlePtr = UnsafeUtility.AddressOf(ref safety); #endif return(JobsUtility.ScheduleParallelForDeferArraySize(ref scheduleParams, innerloopBatchCount, NativeListUnsafeUtility.GetInternalListDataPtrUnchecked(ref list), atomicSafetyHandlePtr)); }
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; }
/// <summary> /// Reads a native list from the buffer. /// </summary> public static unsafe void ReadFromStream <T>(this NativeList <T> nativeList, Buffer buffer) where T : struct { int numElements = buffer.Read32(); nativeList.ResizeUninitialized(numElements); if (numElements > 0) { var numBytes = numElements * UnsafeUtility.SizeOf <T>(); var byteArray = buffer.ReadBytes(numBytes); fixed(byte *src = &byteArray[0]) { UnsafeUtility.MemCpy( NativeListUnsafeUtility.GetUnsafePtr(nativeList), src, byteArray.Length); } } }
/// <summary> /// Writes a native list to the buffer. /// </summary> public static unsafe void WriteToStream <T>(this NativeList <T> nativeList, Buffer buffer) where T : struct { int numElements = nativeList.Length; buffer.Write(numElements); if (numElements > 0) { var numBytes = numElements * UnsafeUtility.SizeOf <T>(); var byteArray = new byte[numBytes]; fixed(byte *dst = &byteArray[0]) { UnsafeUtility.MemCpy(dst, NativeListUnsafeUtility.GetUnsafePtr(nativeList), byteArray.Length); } buffer.Write(byteArray); } }
/// <summary> /// Schedule the job for execution on worker threads. /// list.Length is used as the iteration count. /// Note that it is required to embed the list on the job struct as well. /// </summary> /// <param name="jobData">The job and data to schedule.</param> /// <param name="list">list.Length is used as the iteration count.</param> /// <param name="innerloopBatchCount">Granularity in which workstealing is performed. A value of 32, means the job queue will steal 32 iterations and then perform them in an efficient inner loop.</param> /// <param name="dependsOn">Dependencies are used to ensure that a job executes on workerthreads after the dependency has completed execution. Making sure that two jobs reading or writing to same data do not run in parallel.</param> /// <returns>JobHandle The handle identifying the scheduled job. Can be used as a dependency for a later job or ensure completion on the main thread.</returns> public static unsafe JobHandle Schedule <T, U>(this T jobData, NativeList <U> list, int innerloopBatchCount, JobHandle dependsOn = new JobHandle()) where T : struct, IJobParallelForDefer where U : struct { void *atomicSafetyHandlePtr = null; #if ENABLE_UNITY_COLLECTIONS_CHECKS var safety = NativeListUnsafeUtility.GetAtomicSafetyHandle(ref list); atomicSafetyHandlePtr = UnsafeUtility.AddressOf(ref safety); #endif #if UNITY_AVOID_REFLECTION var listPtr = (UnsafeList *)NativeListUnsafeUtility.GetInternalListDataPtrUnchecked(ref list); var arrayLengthPtr = &listPtr->Length; return(Schedule(ref jobData, new IntPtr(arrayLengthPtr), innerloopBatchCount, dependsOn)); #else var scheduleParams = new JobsUtility.JobScheduleParameters(UnsafeUtility.AddressOf(ref jobData), JobStructDefer <T> .Initialize(), dependsOn, ScheduleMode.Batched); return(JobsUtility.ScheduleParallelForDeferArraySize(ref scheduleParams, innerloopBatchCount, NativeListUnsafeUtility.GetInternalListDataPtrUnchecked(ref list), atomicSafetyHandlePtr)); #endif }
public void Execute() { NativeListUnsafeUtility.DeallocateList(List.m_ListData, List.m_Allocator); }