説明なし
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

Memory.cs 6.9KB

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