コード例 #1
0
        public NativePerThreadCounter(Allocator label)
        {
            // This check is redundant since we always use an int which is blittable.
            // It is here as an example of how to check for type correctness for generic types.
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            if (!UnsafeUtility.IsBlittable <int>())
            {
                throw new ArgumentException(string.Format("{0} used in NativeQueue<{0}> must be blittable", typeof(int)));
            }
#endif
            this.m_AllocatorLabel = label;

            // One full cache line (integers per cacheline * size of integer) for each potential worker index, JobsUtility.MaxJobThreadCount
            this.m_Counter = (int *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <int>() * IntsPerCacheLine * JobsUtility.MaxJobThreadCount, 4, label);

            // Create a dispose sentinel to track memory leaks. This also creates the AtomicSafetyHandle
#if ENABLE_UNITY_COLLECTIONS_CHECKS
#if UNITY_2018_3_OR_NEWER
            DisposeSentinel.Create(out this.m_Safety, out this.m_DisposeSentinel, 0, label);
#else
            DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 0);
#endif
#endif
            // Initialize the count to 0 to avoid uninitialized data
            this.Count = 0;
        }
コード例 #2
0
    // Main constructor logic that takes an element and a label
    public NativeElement(T element, Allocator label)
    {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
        // Blittable check
        if (!UnsafeUtility.IsBlittable <T>())
        {
            throw new ArgumentException(typeof(T) + " used in NativeElement must be blittable");
        }

        // Label check
        if (label <= Allocator.None)
        {
            throw new ArgumentException("NativeElement must be allocated using Job, TempJob or Persistent");
        }
#endif

        // Label set
        m_AllocatorLabel = label;

        // Allocate memory for a single T
        m_ptr = UnsafeUtility.Malloc(UnsafeUtility.SizeOf <T>(), 1, label);

#if ENABLE_UNITY_COLLECTIONS_CHECKS
        // Create DisposeSentinel and AtomicSafetyHandle
        DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 0);
#endif

        // Create element to avoid unitialised data
        Element = element;
    }
コード例 #3
0
        private void requestMeshForLoD(int lod, Action <Mesh> callback)
        {
            if (_lodMeshes[lod] == null)
            {
                var result = new NativeArray <MeshData>(1, Allocator.TempJob);
                UnsafeUtility.IsBlittable(result.GetType());


                Action cacheAndCallback = () => {
                    var mesh = result[0].generateMesh();
                    mesh.RecalculateNormals();
                    _lodMeshes[lod] = mesh;
                    callback(mesh);
                };
                var meshJob = new MeshJob(_heightMap,
                                          _settings,
                                          lod,
                                          cacheAndCallback,
                                          result);
                meshJob.Schedule();
            }
            else
            {
                callback(_lodMeshes[lod]);
            }
        }
コード例 #4
0
    public NativeValue(Allocator allocator, Op valueOperator = default(Op))
    {
        // Safety checks
#if ENABLE_UNITY_COLLECTIONS_CHECKS
        if (allocator <= Allocator.None)
        {
            throw new ArgumentException("Allocator must be Temp, TempJob or Persistent", nameof(allocator));
        }

        if (!UnsafeUtility.IsBlittable <T>())
        {
            throw new ArgumentException(string.Format("{0} used in NativeValue<{0}, {1}> must be blittable", typeof(T), typeof(Op)));
        }

        if (UnsafeUtility.SizeOf <T>() > JobsUtility.CacheLineSize)
        {
            throw new ArgumentException(string.Format("{0} used in NativeValue<{0}, {1}> had a size of {2} which is greater than the maximum size of {3}", typeof(T), typeof(Op), UnsafeUtility.SizeOf <T>(), JobsUtility.CacheLineSize));
        }

        if (UnsafeUtility.SizeOf <Op>() > 1)
        {
            throw new ArgumentException(string.Format("{0} used in NativeValue<{1}, {0}> had a size of {2} which is greater than 1. Access to {0} is not thread safe and can therefor not contain any member variables", typeof(Op), typeof(T), UnsafeUtility.SizeOf <Op>(), JobsUtility.CacheLineSize));
        }

        DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 0, allocator);
#endif

        // Allocate a cache line for each worker thread.
        m_Buffer         = UnsafeUtility.Malloc(JobsUtility.CacheLineSize * JobsUtility.MaxJobThreadCount, JobsUtility.CacheLineSize, allocator);
        m_AllocatorLabel = allocator;
        m_Operator       = valueOperator;

        Value = m_Operator.getIdentity();
    }
コード例 #5
0
 internal static void IsBlittableAndThrow()
 {
     if (!UnsafeUtility.IsBlittable <T>())
     {
         throw new InvalidOperationException(string.Format("{0} used in NativeArray2<{1}> must be blittable.", (object)typeof(T), (object)typeof(T)));
     }
 }
コード例 #6
0
        public NativeListImpl(int capacity, Allocator allocatorLabel)
#endif
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            this.sentinel = sentinel;
            m_ListData    = null;

            if (!UnsafeUtility.IsBlittable <T>())
            {
                this.sentinel.Dispose();
                throw new ArgumentException(string.Format("{0} used in NativeList<{0}> must be blittable", typeof(T)));
            }
#endif
            m_MemoryAllocator = default(TMemManager);
            m_ListData        = (NativeListData *)m_MemoryAllocator.Init(UnsafeUtility.SizeOf <NativeListData>(), UnsafeUtility.AlignOf <NativeListData>(), allocatorLabel);

            var elementSize = UnsafeUtility.SizeOf <T>();

            //@TODO: Find out why this is needed?
            capacity           = Math.Max(1, capacity);
            m_ListData->buffer = UnsafeUtility.Malloc(capacity * elementSize, UnsafeUtility.AlignOf <T>(), allocatorLabel);

            m_ListData->length   = 0;
            m_ListData->capacity = capacity;
        }
コード例 #7
0
            public static void IntrospectiveSort <T>(NativeArray <T> array, int startIndex, int length) where T : struct, IComparable <T>
#endif
            {
                if (length < 0 || length > array.Length)
                {
                    throw new ArgumentOutOfRangeException("length should be in the range [0, array.Length].");
                }
                if (startIndex < 0 || startIndex > length - 1)
                {
                    throw new ArgumentOutOfRangeException("startIndex should in the range [0, length).");
                }

#if !NET_4_6
                if (!UnsafeUtility.IsBlittable <T>())
                {
                    throw new ArgumentException(string.Format("Type: {0}, must be a blittable type.", typeof(T).Name));
                }
#endif
                if (length < 2)
                {
                    return;
                }

                unsafe
                {
                    NativeArrayData <T> data = new NativeArrayData <T>((byte *)array.GetUnsafePtr());
                    IntroSortInternal(ref data, startIndex, length + startIndex - 1, GetMaxDepth(array.Length), GetPartitionThreshold());
                }
            }
コード例 #8
0
        unsafe private NativeList(int capacity, Allocator i_label, int stackDepth)
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            if (!UnsafeUtility.IsBlittable <T>())
            {
                throw new ArgumentException(string.Format("{0} used in NativeList<{0}> must be blittable", typeof(T)));
            }
#endif

            NativeListData *data = (NativeListData *)UnsafeUtility.Malloc(sizeof(NativeListData), UnsafeUtility.AlignOf <NativeListData>(), i_label);

            int elementSize = UnsafeUtility.SizeOf <T> ();

            //@TODO: Find out why this is needed?
            capacity     = Math.Max(1, capacity);
            data->buffer = UnsafeUtility.Malloc(capacity * elementSize, UnsafeUtility.AlignOf <T>(), i_label);

            data->length   = 0;
            data->capacity = capacity;

            m_ListData       = data;
            m_AllocatorLabel = i_label;

#if ENABLE_UNITY_COLLECTIONS_CHECKS
            DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, stackDepth);
#endif
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        /// <summary>
        /// Constructs a new result with an initial value.  You must specify the Allocator
        /// type to use to allocate the memory used by this Result container.
        ///
        /// You can optionally specify an instance of the Op type to use to combine results
        /// into the final single result.  You only need to specify an instance if the op will
        /// contain specific instance data that is important to performing its operation.
        ///
        /// For operations that need no context, such as addition, no operation needs to be
        /// specified, as the result will use the default instance automatically based on the
        /// Op type argument.
        /// </summary>
        public Result(Allocator allocator, Op op = default(Op))
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            if (!UnsafeUtility.IsBlittable <T>())
            {
                throw new ArgumentException(string.Format("{0} used in Result<{0}, {1}> must be blittable", typeof(T), typeof(Op)));
            }
            if (UnsafeUtility.SizeOf <T>() > JobsUtility.CacheLineSize)
            {
                throw new ArgumentException(string.Format("{0} used in Result<{0}, {1}> had a size of {2} which is greater than the maximum size of {3}",
                                                          typeof(T),
                                                          typeof(Op),
                                                          UnsafeUtility.SizeOf <T>(),
                                                          JobsUtility.CacheLineSize));
            }
            DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 0);
#endif

            unsafe {
                m_Buffer = (IntPtr)UnsafeUtility.Malloc(JobsUtility.CacheLineSize * JobsUtility.MaxJobThreadCount,
                                                        JobsUtility.CacheLineSize,
                                                        allocator);
            }

            m_AllocatorLabel = allocator;
            m_Op             = op;

            Reset();
        }
コード例 #11
0
        /// <summary>
        /// Create a system with some custom settings.
        /// </summary>
        /// <param name="subscriberStartingCapacity">The starting capacity of subscriber containers.</param>
        /// <param name="queuedEventsStartingCapacity">The starting capacity of queued events containers.</param>
        /// <param name="parallelBatchCount">The batch count allowed per thread for parallel processing.</param>
        public EventHandlerJob(
            int subscriberStartingCapacity,
            int queuedEventsStartingCapacity,
            int parallelBatchCount)
        {
#if !DISABLE_EVENT_SAFETY_CHKS
            if (!UnsafeUtility.IsBlittable <T_Job>())
            {
                throw new JobTypeNotBlittableException(typeof(T_Job));
            }

            if (!UnsafeUtility.IsBlittable <T_Event>())
            {
                throw new EventTypeNotBlittableException(typeof(T_Event));
            }
#endif
            _batchCount = parallelBatchCount;

            _subscribers           = new NativeList <Subscription>(subscriberStartingCapacity, Allocator.Persistent);
            _subscriberCallbacks   = new List <Action <T_Job> >(subscriberStartingCapacity);
            _entityCallbackToIndex = new Dictionary <EntityCallbackId <T_Job>, int>(subscriberStartingCapacity);

            _queuedEvents = new NativeList <QueuedEvent <T_Event> >(queuedEventsStartingCapacity, Allocator.Persistent);

#if !DISABLE_EVENT_SAFETY_CHKS
            _cachedCurEvents = new Dictionary <QueuedEvent <T_Event>, int>(subscriberStartingCapacity);
#endif
        }
コード例 #12
0
 internal static void IsBlittableAndThrow()
 {
     if (!UnsafeUtility.IsBlittable <T>())
     {
         throw new ArgumentException(string.Format("{0} used in NativeArray<{0}> must be blittable", typeof(T)));
     }
 }
コード例 #13
0
        public bool Generate <TContainer, TValue>(FieldInfo fieldInfo, ReflectedPropertyBag <TContainer> propertyBag)
        {
            if (!typeof(TContainer).IsValueType)
            {
                return(false);
            }

            if (!fieldInfo.FieldType.IsValueType)
            {
                return(false);
            }

            if (!UnsafeUtility.IsBlittable(fieldInfo.FieldType) && fieldInfo.FieldType != typeof(char))
            {
                return(false);
            }

            var propertyType = typeof(UnmanagedProperty <,>).MakeGenericType(typeof(TContainer), fieldInfo.FieldType);
            var property     = Activator.CreateInstance(propertyType,
                                                        fieldInfo.Name,
                                                        UnsafeUtility.GetFieldOffset(fieldInfo),
                                                        null != fieldInfo.GetCustomAttribute <ReadOnlyAttribute>(),
                                                        new PropertyAttributeCollection(fieldInfo.GetCustomAttributes().ToArray()));

            propertyBag.AddProperty <IProperty <TContainer, TValue>, TValue>((IProperty <TContainer, TValue>)property);
            return(true);
        }
コード例 #14
0
        public NativeArrayFullSOA(int length, Allocator label, int stackDepth)
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            if (!UnsafeUtility.IsBlittable <T>())
            {
                throw new ArgumentException($"{typeof(T)} is not blittable");
            }
#endif
            if (!ms_CachedLayout.IsCreated)
            {
                ms_CachedLayout = new StructLayoutData4(typeof(T));
            }

            m_Base      = (byte *)UnsafeUtility.Malloc(4 * length * ms_CachedLayout.FieldCount, StructLayoutData4.ChunkSizeBytes, label);
            m_Length    = length;
            m_Allocator = label;

#if ENABLE_UNITY_COLLECTIONS_CHECKS
#if UNITY_2018_3_OR_NEWER
            DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, stackDepth, label);
#else
            DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, stackDepth);
#endif
#endif
        }
コード例 #15
0
ファイル: NativeArray.cs プロジェクト: yaoya/UnityDecompiled
        private static void Allocate(int length, Allocator allocator, out NativeArray <T> array)
        {
            long num = (long)UnsafeUtility.SizeOf <T>() * (long)length;

            if (allocator <= Allocator.None)
            {
                throw new ArgumentException("Allocator must be Temp, TempJob or Persistent", "allocator");
            }
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException("length", "Length must be >= 0");
            }
            if (!UnsafeUtility.IsBlittable <T>())
            {
                throw new ArgumentException(string.Format("{0} used in NativeArray<{0}> must be blittable", typeof(T)));
            }
            if (num > 2147483647L)
            {
                throw new ArgumentOutOfRangeException("length", string.Format("Length * sizeof(T) cannot exceed {0} bytes", 2147483647));
            }
            array.m_Buffer         = UnsafeUtility.Malloc((ulong)num, UnsafeUtility.AlignOf <T>(), allocator);
            array.m_Length         = length;
            array.m_AllocatorLabel = allocator;
            array.m_MinIndex       = 0;
            array.m_MaxIndex       = length - 1;
            DisposeSentinel.Create(array.m_Buffer, allocator, out array.m_Safety, out array.m_DisposeSentinel, 1, null);
        }
コード例 #16
0
        private void CheckInputArray(Array array)
        {
            if (array == null)
            {
                throw new ArgumentNullException($"Array data used in InputData must be not null");
            }

            if (array.Rank > 1)
            {
                throw new ArgumentException(
                          $"Array data {array.GetType()} used in InputData must be single-dimensional array"
                          );
            }

            var elementType = array.GetType().GetElementType();

            // ReSharper disable once PossibleNullReferenceException
            if (!elementType.IsValueType)
            {
                throw new ArgumentException($"Array data {array.GetType()} used in InputData must be value type");
            }

            if (!UnsafeUtility.IsBlittable(elementType))
            {
                throw new ArgumentException($"Array data {array.GetType()} used in InputData must be blittable");
            }
        }
コード例 #17
0
        public static void AllocateHashMap <TKey, TValue>(int length, int bucketLength, Allocator label, out NativeHashMapData *outBuf)
            where TKey : struct
            where TValue : struct
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            if (!UnsafeUtility.IsBlittable <TKey>())
            {
                throw new ArgumentException(string.Format("{0} used in NativeHashMap<{0},{1}> must be blittable", typeof(TKey), typeof(TValue)));
            }
            if (!UnsafeUtility.IsBlittable <TKey>())
            {
                throw new ArgumentException(string.Format("{1} used in NativeHashMap<{0},{1}> must be blittable", typeof(TKey), typeof(TValue)));
            }
#endif

            NativeHashMapData *data = (NativeHashMapData *)UnsafeUtility.Malloc(sizeof(NativeHashMapData), UnsafeUtility.AlignOf <NativeHashMapData>(), label);

            bucketLength = math.ceil_pow2(bucketLength);

            data->capacity           = length;
            data->bucketCapacityMask = bucketLength - 1;

            int keyOffset, nextOffset, bucketOffset;
            int totalSize = CalculateDataSize <TKey, TValue>(length, bucketLength, out keyOffset, out nextOffset, out bucketOffset);

            data->values  = (byte *)UnsafeUtility.Malloc(totalSize, JobsUtility.CacheLineSize, label);
            data->keys    = data->values + keyOffset;
            data->next    = data->values + nextOffset;
            data->buckets = data->values + bucketOffset;

            outBuf = data;
        }
コード例 #18
0
 private static void IsBlittableAndThrow()
 {
     if (!UnsafeUtility.IsBlittable <T>())
     {
         throw new ArgumentException($"{typeof(T)} used in NativeArray<{typeof(T)}> must be blittable");
     }
 }
コード例 #19
0
ファイル: NativeCounter.cs プロジェクト: C0NC00L/TDMSource
        public NativeCounter(Allocator label, int inc = 1)
        {
            // This check is redundant since we always use an int which is blittable.
            // It is here as an example of how to check for type correctness for generic types.
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            if (!UnsafeUtility.IsBlittable <int>())
            {
                throw new ArgumentException(string.Format("{0} used in NativeQueue<{0}> must be blittable", typeof(int)));
            }
#endif
            m_AllocatorLabel = label;
            increment        = inc;

            // Allocate native memory for a single integer
            m_Counter = (int *)UnsafeUtility.Malloc(UnsafeUtility.SizeOf <int>(), 4, label);

            // Create a dispose sentinel to track memory leaks. This also creates the AtomicSafetyHandle
#if ENABLE_UNITY_COLLECTIONS_CHECKS
#if UNITY_2018_3_OR_NEWER
            DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 0, label);
#else
            DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 0);
#endif
#endif
            // Initialize the count to 0 to avoid uninitialized data
            Count = 0;
        }
コード例 #20
0
        private static unsafe void Allocate(int length, Allocator allocator, out NativeArrayBurst <T> array)
        {
            long totalSize = (long)((ulong)UnsafeUtility.SizeOf <T>() * (ulong)length);

            #if 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", "allocator");
            }
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException("length", "Length must be >= 0");
            }
            if (!UnsafeUtility.IsBlittable <T>())
            {
                throw new ArgumentException(string.Format("{0} used in NativeArrayBurst<{0}> must be blittable", typeof(T)));
            }
            #endif

            array.m_Buffer = UnsafeUtility.Malloc(totalSize, UnsafeUtility.AlignOf <T>(), allocator);
            UnsafeUtility.MemClear(array.m_Buffer, totalSize);

            array.m_Length         = length;
            array.m_AllocatorLabel = allocator;

            #if COLLECTIONS_CHECKS
            array.m_MinIndex = 0;
            array.m_MaxIndex = length - 1;
            DisposeSentinel.Create(out array.m_Safety, out array.m_DisposeSentinel, 1, allocator);
            #endif
        }
コード例 #21
0
 internal static void IsBlittableAndThrow()
 {
     if (!UnsafeUtility.IsBlittable <T>())
     {
         throw new InvalidOperationException(
                   $"{typeof(T)} used in NativeArray<{typeof(T)}> must be blittable.\n{UnsafeUtility.GetReasonForValueTypeNonBlittable<T>()}");
     }
 }
コード例 #22
0
        static void InitializeAllComponentTypes()
        {
            var componentTypeSet = new HashSet <Type>();

            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                if (!IsAssemblyReferencingEntities(assembly))
                {
                    continue;
                }

                foreach (var type in assembly.GetTypes())
                {
                    if (type.IsAbstract || !type.IsValueType || !UnsafeUtility.IsBlittable(type))
                    {
                        continue;
                    }

                    if (typeof(IComponentData).IsAssignableFrom(type) ||
                        typeof(ISharedComponentData).IsAssignableFrom(type) ||
                        typeof(IBufferElementData).IsAssignableFrom(type))
                    {
                        componentTypeSet.Add(type);
                    }
                }
            }

            var lockTaken = false;

            try
            {
                s_CreateTypeLock.Enter(ref lockTaken);

                var componentTypeCount = componentTypeSet.Count;
                var componentTypes     = new Type[componentTypeCount];
                componentTypeSet.CopyTo(componentTypes);

                var typeIndexByType  = new Dictionary <Type, int>();
                var writeGroupByType = new Dictionary <int, HashSet <int> >();
                var startTypeIndex   = s_Count;

                for (int i = 0; i < componentTypes.Length; i++)
                {
                    typeIndexByType[componentTypes[i]] = startTypeIndex + i;
                }

                GatherWriteGroups(componentTypes, startTypeIndex, typeIndexByType, writeGroupByType);
                AddAllComponentTypes(componentTypes, startTypeIndex, writeGroupByType);
            }
            finally
            {
                if (lockTaken)
                {
                    s_CreateTypeLock.Exit(true);
                }
            }
        }
コード例 #23
0
        public BlitableArray(int length, Allocator allocator) : this()
        {
#if ENABLE_UNITY_COLLECTIONS_CHECKS
            if (!UnsafeUtility.IsBlittable <T>())
            {
                throw new ArgumentException(string.Format("{0} used in BlitableArray<{0}> must be blittable", typeof(T)));
            }
#endif
            Allocate(length, allocator);
        }
コード例 #24
0
 public static void IsBlittableAndThrow <Container, T>()
     where T : struct
     where Container : struct
 {
     if (!UnsafeUtility.IsBlittable <T>())
     {
         throw new ArgumentException(
                   $"{typeof(T)} used in {typeof(Container)} must be blittable"
                   );
     }
 }
コード例 #25
0
        /// <summary>
        /// Throw an exception if <typeparam name="T"/> is not blittable
        /// </summary>
        private static void RequireBlittable()
        {
// No check is necessary because C# 7.3 uses `where T : unmanaged`
#if !CSHARP_7_3_OR_NEWER
            if (!UnsafeUtility.IsBlittable <T>())
            {
                throw new ArgumentException(
                          "Type used in NativeHashSet must be blittable");
            }
#endif
        }
コード例 #26
0
        internal unsafe void WriteBlittable <T>(T value)
            where T : unmanaged
        {
            // check if blittable for safety
#if UNITY_EDITOR
            if (!UnsafeUtility.IsBlittable(typeof(T)))
            {
                Debug.LogError($"{typeof(T)} is not blittable!");
                return;
            }
#endif
            // calculate size
            //   sizeof(T) gets the managed size at compile time.
            //   Marshal.SizeOf<T> gets the unmanaged size at runtime (slow).
            // => our 1mio writes benchmark is 6x slower with Marshal.SizeOf<T>
            // => for blittable types, sizeof(T) is even recommended:
            // https://docs.microsoft.com/en-us/dotnet/standard/native-interop/best-practices
            int size = sizeof(T);

            // ensure capacity
            // NOTE that our runtime resizing comes at no extra cost because:
            // 1. 'has space' checks are necessary even for fixed sized writers.
            // 2. all writers will eventually be large enough to stop resizing.
            EnsureCapacity(Position + size);

            // write blittable
            fixed(byte *ptr = &buffer[Position])
            {
#if UNITY_ANDROID
                // on some android systems, assigning *(T*)ptr throws a NRE if
                // the ptr isn't aligned (i.e. if Position is 1,2,3,5, etc.).
                // here we have to use memcpy.
                //
                // => we can't get a pointer of a struct in C# without
                //    marshalling allocations
                // => instead, we stack allocate an array of type T and use that
                // => stackalloc avoids GC and is very fast. it only works for
                //    value types, but all blittable types are anyway.
                //
                // this way, we can still support blittable reads on android.
                // see also: https://github.com/vis2k/Mirror/issues/3044
                // (solution discovered by AIIO, FakeByte, mischa)
                T *valueBuffer = stackalloc T[1] {
                    value
                };
                UnsafeUtility.MemCpy(ptr, valueBuffer, size);
#else
                // cast buffer to T* pointer, then assign value to the area
                *(T *)ptr = value;
#endif
            }

            Position += size;
        }
コード例 #27
0
 /// <inheritdoc/>
 public override bool IsConstraintSatisfied(Type type)
 {
     if (!type.IsValueType)
     {
         return(false);
     }
     if (type.IsGenericType)
     {
         return(false);
     }
     return(UnsafeUtility.IsBlittable(type));
 }
コード例 #28
0
        public NativeBucket(int blockNumCapacity,
                            Allocator allocator)
        {
            if (UnsafeUtility.SizeOf <NativeBucketHeader>() > JobsUtility.CacheLineSize)
            {
                throw new ArgumentException("CacheLineSize is too small.");
            }

            int headerBlockSize = JobsUtility.CacheLineSize * JobsUtility.MaxJobThreadCount;
            int unitSize        = UnsafeUtility.SizeOf <T>();
            int blockSize       = unitSize * blockNumCapacity;

#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 (blockNumCapacity < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(blockNumCapacity), "capacity must be >= 0");
            }
            if (!UnsafeUtility.IsBlittable <T>())
            {
                throw new ArgumentException(string.Format("{0} used in NativeBucket<{0}> must be blittable", typeof(T)));
            }
            if (blockSize > int.MaxValue)
            {
                throw new ArgumentOutOfRangeException(nameof(blockNumCapacity), $"Length * sizeof(T) cannot exceed {int.MaxValue} bytes");
            }
#if UNITY_2018_3_OR_NEWER
            DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 0, allocator);
#else
            DisposeSentinel.Create(out m_Safety, out m_DisposeSentinel, 0);
#endif
#endif
            m_HeaderBlock      = (byte *)UnsafeUtility.Malloc(headerBlockSize, ALIGN, allocator);
            m_BlockNumCapacity = blockNumCapacity;
            m_BlockSize        = blockSize;
            m_AllocatorLabel   = allocator;

            UnsafeUtility.MemClear(m_HeaderBlock, (long)headerBlockSize);
            for (int i = 0; i < JobsUtility.MaxJobThreadCount; ++i)
            {
                NativeBucketHeader *headerBlock = GetHeaderBlock(m_HeaderBlock, i);
                headerBlock->block        = IntPtr.Zero;
                headerBlock->unitSize     = unitSize;
                headerBlock->itemsInBlock = 0;
            }
        }
コード例 #29
0
        public static void Register <T>()
            where T : struct
        {
            if (isFreezed)
            {
                throw new InvalidOperationException("Register must call on startup(before use GetFormatter<T>).");
            }
            if (!UnsafeUtility.IsBlittable <T>())
            {
                throw new InvalidOperationException(typeof(T) + " is not blittable so can not register UnsafeBlitResolver.");
            }

            formatters.Add(typeof(T), new UnsafeDirectBlitFormatter <T>());
            formatters.Add(typeof(T[]), new UnsafeDirectBlitArrayFormatter <T>());
        }
コード例 #30
0
        // This is the ugly bit, necessary until Graphics.DrawMeshInstanced supports NativeArrays pulling the data in from a job.
        public unsafe static Vector4[] CopyToArray(this NativeSlice <Vector4> src, Vector4[] dst) // where T:struct
        {
            fixed(Vector4 *p = dst)
            {
                UnityEngine.Assertions.Assert.IsTrue(UnsafeUtility.IsBlittable <Vector4>());
                var s = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice <Vector4>(p, UnsafeUtility.SizeOf <Vector4>(), src.Length);

                    #if ENABLE_UNITY_COLLECTIONS_CHECKS
                NativeSliceUnsafeUtility.SetAtomicSafetyHandle(ref s, AtomicSafetyHandle.GetTempUnsafePtrSliceHandle());
                    #endif
                s.CopyFrom(src);
            }

            return(dst);
        }