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; }
// 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; }
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]); } }
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(); }
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))); } }
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; }
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()); } }
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 }
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> /// 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(); }
/// <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 }
internal static void IsBlittableAndThrow() { if (!UnsafeUtility.IsBlittable <T>()) { throw new ArgumentException(string.Format("{0} used in NativeArray<{0}> must be blittable", typeof(T))); } }
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); }
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 }
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); }
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"); } }
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; }
private static void IsBlittableAndThrow() { if (!UnsafeUtility.IsBlittable <T>()) { throw new ArgumentException($"{typeof(T)} used in NativeArray<{typeof(T)}> must be blittable"); } }
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; }
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 }
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>()}"); } }
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); } } }
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); }
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" ); } }
/// <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 }
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; }
/// <inheritdoc/> public override bool IsConstraintSatisfied(Type type) { if (!type.IsValueType) { return(false); } if (type.IsGenericType) { return(false); } return(UnsafeUtility.IsBlittable(type)); }
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; } }
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>()); }
// 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); }