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

BurstRuntime.cs 9.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using System.Text;
  4. namespace Unity.Burst
  5. {
  6. /// <summary>
  7. /// Provides helper intrinsics that can be used at runtime.
  8. /// </summary>
  9. #if BURST_COMPILER_SHARED
  10. internal static class BurstRuntimeInternal
  11. #else
  12. public static class BurstRuntime
  13. #endif
  14. {
  15. /// <summary>
  16. /// Gets a 32-bits hashcode from a type computed for the <see cref="System.Type.AssemblyQualifiedName"/>
  17. /// </summary>
  18. /// <typeparam name="T">The type to compute the hash from</typeparam>
  19. /// <returns>The 32-bit hashcode.</returns>
  20. public static int GetHashCode32<T>()
  21. {
  22. #if !UNITY_DOTSRUNTIME_IL2CPP
  23. return HashCode32<T>.Value;
  24. #else
  25. // DOTS Runtime IL2CPP Builds do not use C#'s lazy static initialization order (it uses a C like order, aka random)
  26. // As such we cannot rely on static init for caching types since any static constructor calling this function
  27. // may return uninitialized/default-initialized memory
  28. return HashStringWithFNV1A32(typeof(T).AssemblyQualifiedName);
  29. #endif
  30. }
  31. /// <summary>
  32. /// Gets a 32-bits hashcode from a type computed for the <see cref="System.Type.AssemblyQualifiedName"/>
  33. /// This method cannot be used from a burst job.
  34. /// </summary>
  35. /// <param name="type">The type to compute the hash from</param>
  36. /// <returns>The 32-bit hashcode.</returns>
  37. public static int GetHashCode32(Type type)
  38. {
  39. return HashStringWithFNV1A32(type.AssemblyQualifiedName);
  40. }
  41. /// <summary>
  42. /// Gets a 64-bits hashcode from a type computed for the <see cref="System.Type.AssemblyQualifiedName"/>
  43. /// </summary>
  44. /// <typeparam name="T">The type to compute the hash from</typeparam>
  45. /// <returns>The 64-bit hashcode.</returns>
  46. public static long GetHashCode64<T>()
  47. {
  48. #if !UNITY_DOTSRUNTIME_IL2CPP
  49. return HashCode64<T>.Value;
  50. #else
  51. // DOTS Runtime IL2CPP Builds do not use C#'s lazy static initialization order (it uses a C like order, aka random)
  52. // As such we cannot rely on static init for caching types since any static constructor calling this function
  53. // may return uninitialized/default-initialized memory
  54. return HashStringWithFNV1A64(typeof(T).AssemblyQualifiedName);
  55. #endif
  56. }
  57. /// <summary>
  58. /// Gets a 64-bits hashcode from a type computed for the <see cref="System.Type.AssemblyQualifiedName"/>.
  59. /// This method cannot be used from a burst job.
  60. /// </summary>
  61. /// <param name="type">Type to calculate a hash for</param>
  62. /// <returns>The 64-bit hashcode.</returns>
  63. public static long GetHashCode64(Type type)
  64. {
  65. return HashStringWithFNV1A64(type.AssemblyQualifiedName);
  66. }
  67. // method internal as it is used by the compiler directly
  68. internal static int HashStringWithFNV1A32(string text)
  69. {
  70. // Using http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-1a
  71. // with basis and prime:
  72. const uint offsetBasis = 2166136261;
  73. const uint prime = 16777619;
  74. uint result = offsetBasis;
  75. foreach (var c in text)
  76. {
  77. result = prime * (result ^ (byte)(c & 255));
  78. result = prime * (result ^ (byte)(c >> 8));
  79. }
  80. return (int)result;
  81. }
  82. // method internal as it is used by the compiler directly
  83. internal static long HashStringWithFNV1A64(string text)
  84. {
  85. // Using http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-1a
  86. // with basis and prime:
  87. const ulong offsetBasis = 14695981039346656037;
  88. const ulong prime = 1099511628211;
  89. ulong result = offsetBasis;
  90. foreach (var c in text)
  91. {
  92. result = prime * (result ^ (byte)(c & 255));
  93. result = prime * (result ^ (byte)(c >> 8));
  94. }
  95. return (long)result;
  96. }
  97. private struct HashCode32<T>
  98. {
  99. public static readonly int Value = HashStringWithFNV1A32(typeof(T).AssemblyQualifiedName);
  100. }
  101. private struct HashCode64<T>
  102. {
  103. public static readonly long Value = HashStringWithFNV1A64(typeof(T).AssemblyQualifiedName);
  104. }
  105. #if !BURST_COMPILER_SHARED
  106. /// <summary>
  107. /// Allows for loading additional Burst native libraries
  108. /// Important: Designed for Play mode / Desktop Standalone Players ONLY
  109. /// In Editor, any libraries that have been loaded will be unloaded on exit of playmode
  110. /// Only supported from 2020.1 and later. You can use BurstCompiler.IsLoadAdditionalLibrarySupported() to confirm it is available.
  111. /// </summary>
  112. /// <param name="pathToLibBurstGenerated">Absolute filesystem location of bursted library to load</param>
  113. /// <returns>true if the library was loaded successfully</returns>
  114. public static bool LoadAdditionalLibrary(string pathToLibBurstGenerated)
  115. {
  116. if (BurstCompiler.IsLoadAdditionalLibrarySupported())
  117. {
  118. return LoadAdditionalLibraryInternal(pathToLibBurstGenerated);
  119. }
  120. return false;
  121. }
  122. internal static bool LoadAdditionalLibraryInternal(string pathToLibBurstGenerated)
  123. {
  124. #if !UNITY_DOTSRUNTIME
  125. return (bool)typeof(Unity.Burst.LowLevel.BurstCompilerService).GetMethod("LoadBurstLibrary").Invoke(null, new object[] { pathToLibBurstGenerated });
  126. #else
  127. return false;
  128. #endif
  129. }
  130. #if UNITY_2020_1_OR_NEWER
  131. internal static void Initialize()
  132. {
  133. }
  134. // Prevent BurstCompilerService.Log from being stripped, introduce PreserveAttribute to avoid
  135. //requiring a unityengine using directive, il2cpp will see the attribute and know to not strip
  136. //the Log method and its BurstCompilerService.Log dependency
  137. internal class PreserveAttribute : System.Attribute {}
  138. [Preserve]
  139. internal static unsafe void Log(byte* message, int logType, byte* fileName, int lineNumber)
  140. {
  141. Unity.Burst.LowLevel.BurstCompilerService.Log((byte*) 0, (Unity.Burst.LowLevel.BurstCompilerService.BurstLogType)logType, message, fileName, lineNumber);
  142. }
  143. #elif UNITY_2019_4_OR_NEWER
  144. // Because we can't back-port the new API BurstCompilerService.Log introduced in 2020.1
  145. // we are still trying to allow to log on earlier version of Unity by going back to managed
  146. // code when we are using Debug.Log. It is not great in terms of performance but it should not
  147. // be a matter when debugging.
  148. internal static unsafe void Log(byte* message, int logType, byte* fileName, int lineNumber)
  149. {
  150. var fp = LogHelper.Instance.Data;
  151. // If we have a domain reload, the function pointer will be cleared, so we can't call it.
  152. if (fp.IsCreated)
  153. {
  154. fp.Invoke(message, logType, fileName, lineNumber);
  155. }
  156. }
  157. private unsafe delegate void NativeLogDelegate(byte* message, int logType, byte* filename, int lineNumber);
  158. private static readonly unsafe NativeLogDelegate ManagedNativeLog = ManagedNativeLogImpl;
  159. [AOT.MonoPInvokeCallback(typeof(NativeLogDelegate))]
  160. private static unsafe void ManagedNativeLogImpl(byte* message, int logType, byte* filename, int lineNumber)
  161. {
  162. if (message == null) return;
  163. int byteCount = 0;
  164. while (message[byteCount] != 0) byteCount++;
  165. var managedText = Encoding.UTF8.GetString(message, byteCount);
  166. switch (logType)
  167. {
  168. case 1:
  169. UnityEngine.Debug.LogWarning(managedText);
  170. break;
  171. case 2:
  172. UnityEngine.Debug.LogError(managedText);
  173. break;
  174. default:
  175. UnityEngine.Debug.Log(managedText);
  176. break;
  177. }
  178. }
  179. private class LogHelper
  180. {
  181. public static readonly SharedStatic<FunctionPointer<NativeLogDelegate>> Instance = SharedStatic<FunctionPointer<NativeLogDelegate>>.GetOrCreate<LogHelper>();
  182. }
  183. static BurstRuntime()
  184. {
  185. LogHelper.Instance.Data = new FunctionPointer<NativeLogDelegate>(Marshal.GetFunctionPointerForDelegate(ManagedNativeLog));
  186. }
  187. [UnityEngine.RuntimeInitializeOnLoadMethod(UnityEngine.RuntimeInitializeLoadType.AfterAssembliesLoaded)]
  188. internal static void Initialize()
  189. {
  190. }
  191. #else
  192. internal static void Initialize()
  193. {
  194. }
  195. internal static unsafe void Log(byte* message, int logType, byte* fileName, int lineNumber)
  196. {
  197. }
  198. #endif
  199. #endif // !BURST_COMPILER_SHARED
  200. /// <summary>
  201. /// Return a pointer to read-only memory consisting of the literal UTF-8 bytes of a string constant.
  202. /// </summary>
  203. /// <param name="str">A string which must a string literal</param>
  204. /// <param name="byteCount">Receives the number of UTF-8 encoded bytes the constant contains (excluding null terminator)</param>
  205. /// <returns>A pointer to constant data representing the UTF-8 encoded bytes of the string literal, terminated with a null terminator</returns>
  206. public unsafe static byte* GetUTF8LiteralPointer(string str, out int byteCount)
  207. {
  208. throw new NotImplementedException("This function only works from Burst");
  209. }
  210. }
  211. }