/// <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));
        }
Example #2
0
        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);
                }
Example #4
0
        /// <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;
        }
Example #5
0
        /// <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;
            }
Example #8
0
        /// <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);
                }
            }
        }
Example #9
0
        /// <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);
            }
        }
Example #10
0
        /// <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
        }
Example #11
0
 public void Execute()
 {
     NativeListUnsafeUtility.DeallocateList(List.m_ListData, List.m_Allocator);
 }