A game about forced loneliness, made by TACStudios
1using System; 2using System.Diagnostics; 3using Unity.Collections.LowLevel.Unsafe; 4using Unity.Mathematics; 5using Unity.Jobs.LowLevel.Unsafe; 6 7 8namespace Unity.Collections 9{ 10 [GenerateTestsForBurstCompatibility] 11 unsafe internal struct Memory 12 { 13 internal const long k_MaximumRamSizeInBytes = 1L << 40; // a terabyte 14 15 [GenerateTestsForBurstCompatibility] 16 internal struct Unmanaged 17 { 18 internal static void* Allocate(long size, int align, AllocatorManager.AllocatorHandle allocator) 19 { 20 return Array.Resize(null, 0, 1, allocator, size, align); 21 } 22 23 internal static void Free(void* pointer, AllocatorManager.AllocatorHandle allocator) 24 { 25 if (pointer == null) 26 return; 27 Array.Resize(pointer, 1, 0, allocator, 1, 1); 28 } 29 30 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 31 internal static T* Allocate<T>(AllocatorManager.AllocatorHandle allocator) where T : unmanaged 32 { 33 return Array.Resize<T>(null, 0, 1, allocator); 34 } 35 36 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 37 internal static void Free<T>(T* pointer, AllocatorManager.AllocatorHandle allocator) where T : unmanaged 38 { 39 if (pointer == null) 40 return; 41 Array.Resize(pointer, 1, 0, allocator); 42 } 43 44 [GenerateTestsForBurstCompatibility] 45 internal struct Array 46 { 47 static bool IsCustom(AllocatorManager.AllocatorHandle allocator) 48 { 49 return (int) allocator.Index >= AllocatorManager.FirstUserIndex; 50 } 51 52 static void* CustomResize(void* oldPointer, long oldCount, long newCount, AllocatorManager.AllocatorHandle allocator, long size, int align) 53 { 54 AllocatorManager.Block block = default; 55 block.Range.Allocator = allocator; 56 block.Range.Items = (int)newCount; 57 block.Range.Pointer = (IntPtr)oldPointer; 58 block.BytesPerItem = (int)size; 59 block.Alignment = align; 60 block.AllocatedItems = (int)oldCount; 61 var error = AllocatorManager.Try(ref block); 62 AllocatorManager.CheckFailedToAllocate(error); 63 return (void*)block.Range.Pointer; 64 } 65 66 internal static void* Resize(void* oldPointer, long oldCount, long newCount, AllocatorManager.AllocatorHandle allocator, 67 long size, int align) 68 { 69 // Make the alignment multiple of cacheline size 70 var alignment = math.max(JobsUtility.CacheLineSize, align); 71 72 if (IsCustom(allocator)) 73 return CustomResize(oldPointer, oldCount, newCount, allocator, size, alignment); 74 void* newPointer = default; 75 if (newCount > 0) 76 { 77 long bytesToAllocate = newCount * size; 78 CheckByteCountIsReasonable(bytesToAllocate); 79 newPointer = UnsafeUtility.MallocTracked(bytesToAllocate, alignment, allocator.ToAllocator, 0); 80 if (oldCount > 0) 81 { 82 long count = math.min(oldCount, newCount); 83 long bytesToCopy = count * size; 84 CheckByteCountIsReasonable(bytesToCopy); 85 UnsafeUtility.MemCpy(newPointer, oldPointer, bytesToCopy); 86 } 87 } 88 if (oldCount > 0) 89 UnsafeUtility.FreeTracked(oldPointer, allocator.ToAllocator); 90 return newPointer; 91 } 92 93 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 94 internal static T* Resize<T>(T* oldPointer, long oldCount, long newCount, AllocatorManager.AllocatorHandle allocator) where T : unmanaged 95 { 96 return (T*)Resize((byte*)oldPointer, oldCount, newCount, allocator, UnsafeUtility.SizeOf<T>(), UnsafeUtility.AlignOf<T>()); 97 } 98 99 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 100 internal static T* Allocate<T>(long count, AllocatorManager.AllocatorHandle allocator) 101 where T : unmanaged 102 { 103 return Resize<T>(null, 0, count, allocator); 104 } 105 106 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 107 internal static void Free<T>(T* pointer, long count, AllocatorManager.AllocatorHandle allocator) 108 where T : unmanaged 109 { 110 if (pointer == null) 111 return; 112 Resize(pointer, count, 0, allocator); 113 } 114 } 115 } 116 117 [GenerateTestsForBurstCompatibility] 118 internal struct Array 119 { 120 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 121 internal static void Set<T>(T* pointer, long count, T t = default) where T : unmanaged 122 { 123 long bytesToSet = count * UnsafeUtility.SizeOf<T>(); 124 CheckByteCountIsReasonable(bytesToSet); 125 for (var i = 0; i < count; ++i) 126 pointer[i] = t; 127 } 128 129 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 130 internal static void Clear<T>(T* pointer, long count) where T : unmanaged 131 { 132 long bytesToClear = count * UnsafeUtility.SizeOf<T>(); 133 CheckByteCountIsReasonable(bytesToClear); 134 UnsafeUtility.MemClear(pointer, bytesToClear); 135 } 136 137 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] 138 internal static void Copy<T>(T* dest, T* src, long count) where T : unmanaged 139 { 140 long bytesToCopy = count * UnsafeUtility.SizeOf<T>(); 141 CheckByteCountIsReasonable(bytesToCopy); 142 UnsafeUtility.MemCpy(dest, src, bytesToCopy); 143 } 144 } 145 146 [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS"), Conditional("UNITY_DOTS_DEBUG")] 147 internal static void CheckByteCountIsReasonable(long size) 148 { 149 if (size < 0) 150 throw new InvalidOperationException($"Attempted to operate on {size} bytes of memory: negative size"); 151 if (size > k_MaximumRamSizeInBytes) 152 throw new InvalidOperationException($"Attempted to operate on {size} bytes of memory: size too big"); 153 } 154 155 } 156}