暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BurstCompilerOptions.cs 37KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973
  1. // BurstCompiler.Compile is not supported on Tiny/ZeroPlayer
  2. #if !UNITY_DOTSPLAYER && !NET_DOTS
  3. using System;
  4. using System.ComponentModel;
  5. using System.IO;
  6. using System.Reflection;
  7. using System.Text;
  8. using System.Collections.Generic;
  9. using System.Diagnostics;
  10. using System.Linq;
  11. #if !BURST_COMPILER_SHARED
  12. using Unity.Jobs.LowLevel.Unsafe;
  13. #endif
  14. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  15. // NOTE: This file is shared via a csproj cs link in Burst.Compiler.IL
  16. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  17. #endif //!UNITY_DOTSPLAYER && !NET_DOTS
  18. namespace Unity.Burst
  19. {
  20. internal enum GlobalSafetyChecksSettingKind
  21. {
  22. Off = 0,
  23. On = 1,
  24. ForceOn = 2,
  25. }
  26. #if !UNITY_DOTSPLAYER && !NET_DOTS
  27. /// <summary>
  28. /// Options available at Editor time and partially at runtime to control the behavior of the compilation and to enable/disable burst jobs.
  29. /// </summary>
  30. #if BURST_COMPILER_SHARED
  31. internal sealed partial class BurstCompilerOptionsInternal
  32. #else
  33. public sealed partial class BurstCompilerOptions
  34. #endif
  35. {
  36. private const string DisableCompilationArg = "--burst-disable-compilation";
  37. private const string ForceSynchronousCompilationArg = "--burst-force-sync-compilation";
  38. internal const string DefaultLibraryName = "lib_burst_generated";
  39. internal const string BurstInitializeName = "burst.initialize";
  40. internal const string BurstInitializeExternalsName = "burst.initialize.externals";
  41. internal const string BurstInitializeStaticsName = "burst.initialize.statics";
  42. #if BURST_COMPILER_SHARED || UNITY_EDITOR
  43. internal static readonly string DefaultCacheFolder = Path.Combine(Environment.CurrentDirectory, "Library", "BurstCache", "JIT");
  44. internal const string DeleteCacheMarkerFileName = "DeleteCache.txt";
  45. #endif
  46. internal const string OptionDoNotEagerCompile = "do-not-eager-compile";
  47. internal const string DoNotEagerCompile = "--" + OptionDoNotEagerCompile;
  48. // -------------------------------------------------------
  49. // Common options used by the compiler
  50. // -------------------------------------------------------
  51. internal const string OptionGroup = "group";
  52. internal const string OptionPlatform = "platform=";
  53. internal const string OptionBackend = "backend=";
  54. internal const string OptionGlobalSafetyChecksSetting = "global-safety-checks-setting=";
  55. internal const string OptionDisableSafetyChecks = "disable-safety-checks";
  56. internal const string OptionDisableOpt = "disable-opt";
  57. internal const string OptionFastMath = "fastmath";
  58. internal const string OptionTarget = "target=";
  59. internal const string OptionOptLevel = "opt-level=";
  60. internal const string OptionOptForSize = "opt-for-size";
  61. internal const string OptionFloatPrecision = "float-precision=";
  62. internal const string OptionFloatMode = "float-mode=";
  63. internal const string OptionDisableWarnings = "disable-warnings=";
  64. internal const string OptionCompilationDefines = "compilation-defines=";
  65. internal const string OptionDump = "dump=";
  66. internal const string OptionFormat = "format=";
  67. internal const string OptionDebugTrap = "debugtrap";
  68. internal const string OptionDisableVectors = "disable-vectors";
  69. internal const string OptionDebug = "debug=";
  70. internal const string OptionDebugMode = "debugMode";
  71. internal const string OptionStaticLinkage = "generate-static-linkage-methods";
  72. internal const string OptionJobMarshalling = "generate-job-marshalling-methods";
  73. internal const string OptionTempDirectory = "temp-folder=";
  74. internal const string OptionEnableDirectExternalLinking = "enable-direct-external-linking";
  75. internal const string OptionLinkerOptions = "linker-options=";
  76. internal const string OptionEnableAutoLayoutFallbackCheck = "enable-autolayout-fallback-check";
  77. internal const string OptionGenerateLinkXml = "generate-link-xml=";
  78. // -------------------------------------------------------
  79. // Options used by the Jit and Bcl compilers
  80. // -------------------------------------------------------
  81. internal const string OptionCacheDirectory = "cache-directory=";
  82. // -------------------------------------------------------
  83. // Options used by the Jit compiler
  84. // -------------------------------------------------------
  85. internal const string OptionJitDisableFunctionCaching = "disable-function-caching";
  86. internal const string OptionJitDisableAssemblyCaching = "disable-assembly-caching";
  87. internal const string OptionJitEnableAssemblyCachingLogs = "enable-assembly-caching-logs";
  88. internal const string OptionJitEnableSynchronousCompilation = "enable-synchronous-compilation";
  89. internal const string OptionJitCompilationPriority = "compilation-priority=";
  90. // TODO: Remove this option and use proper dump flags or revisit how we log timings
  91. internal const string OptionJitLogTimings = "log-timings";
  92. internal const string OptionJitIsForFunctionPointer = "is-for-function-pointer";
  93. internal const string OptionJitManagedFunctionPointer = "managed-function-pointer=";
  94. internal const string OptionJitProvider = "jit-provider=";
  95. internal const string OptionJitSkipCheckDiskCache = "skip-check-disk-cache";
  96. internal const string OptionJitSkipBurstInitialize = "skip-burst-initialize";
  97. internal const string OptionEnableInterpreter = "enable-interpreter";
  98. // -------------------------------------------------------
  99. // Options used by the Aot compiler
  100. // -------------------------------------------------------
  101. internal const string OptionAotAssemblyFolder = "assembly-folder=";
  102. internal const string OptionRootAssembly = "root-assembly=";
  103. internal const string OptionIncludeRootAssemblyReferences = "include-root-assembly-references=";
  104. internal const string OptionAotMethod = "method=";
  105. internal const string OptionAotType = "type=";
  106. internal const string OptionAotAssembly = "assembly=";
  107. internal const string OptionAotOutputPath = "output=";
  108. internal const string OptionAotKeepIntermediateFiles = "keep-intermediate-files";
  109. internal const string OptionAotNoLink = "nolink";
  110. internal const string OptionAotPatchedAssembliesOutputFolder = "patch-assemblies-into=";
  111. internal const string OptionAotPinvokeNameToPatch = "pinvoke-name=";
  112. internal const string OptionAotExecuteMethodNameToFind = "execute-method-name=";
  113. internal const string OptionAotUsePlatformSDKLinkers = "use-platform-sdk-linkers";
  114. internal const string OptionAotOnlyStaticMethods = "only-static-methods";
  115. internal const string OptionMethodPrefix = "method-prefix=";
  116. internal const string OptionAotNoNativeToolchain = "no-native-toolchain";
  117. internal const string OptionAotEmitLlvmObjects = "emit-llvm-objects";
  118. internal const string OptionAotKeyFolder = "key-folder=";
  119. internal const string OptionAotDecodeFolder = "decode-folder=";
  120. internal const string OptionVerbose = "verbose";
  121. internal const string OptionValidateExternalToolChain = "validate-external-tool-chain";
  122. internal const string OptionCompilerThreads = "threads=";
  123. internal const string OptionChunkSize = "chunk-size=";
  124. internal const string OptionPrintLogOnMissingPInvokeCallbackAttribute = "print-monopinvokecallbackmissing-message";
  125. internal const string OptionOutputMode = "output-mode=";
  126. internal const string OptionAlwaysCreateOutput = "always-create-output=";
  127. internal const string OptionAotPdbSearchPaths = "pdb-search-paths=";
  128. internal const string OptionSafetyChecks = "safety-checks";
  129. internal const string CompilerCommandShutdown = "$shutdown";
  130. internal const string CompilerCommandCancel = "$cancel";
  131. internal const string CompilerCommandEnableCompiler = "$enable_compiler";
  132. internal const string CompilerCommandDisableCompiler = "$disable_compiler";
  133. internal const string CompilerCommandTriggerRecompilation = "$trigger_recompilation";
  134. internal const string CompilerCommandEagerCompileMethods = "$eager_compile_methods";
  135. internal const string CompilerCommandWaitUntilCompilationFinished = "$wait_until_compilation_finished";
  136. internal const string CompilerCommandClearEagerCompilationQueues = "$clear_eager_compilation_queues";
  137. internal const string CompilerCommandCancelEagerCompilation = "$cancel_eager_compilation";
  138. internal const string CompilerCommandReset = "$reset";
  139. internal const string CompilerCommandDomainReload = "$domain_reload";
  140. internal const string CompilerCommandUpdateAssemblyFolders = "$update_assembly_folders";
  141. internal const string CompilerCommandVersionNotification = "$version";
  142. internal const string CompilerCommandSetProgressCallback = "$set_progress_callback";
  143. internal const string CompilerCommandRequestClearJitCache = "$request_clear_jit_cache";
  144. internal const string CompilerCommandSetProfileCallbacks = "$set_profile_callbacks";
  145. internal const string CompilerCommandUnloadBurstNatives = "$unload_burst_natives";
  146. internal const string CompilerCommandIsNativeApiAvailable = "$is_native_api_available";
  147. internal const string CompilerCommandILPPCompilation = "$ilpp_compilation";
  148. internal const string CompilerCommandIsArmTestEnv = "$is_arm_test_env";
  149. // All the following content is exposed to the public interface
  150. #if !BURST_COMPILER_SHARED
  151. // These fields are only setup at startup
  152. internal static readonly bool ForceDisableBurstCompilation;
  153. private static readonly bool ForceBurstCompilationSynchronously;
  154. internal static readonly bool IsSecondaryUnityProcess;
  155. #if UNITY_EDITOR
  156. internal bool IsInitializing;
  157. #endif
  158. private bool _enableBurstCompilation;
  159. private bool _enableBurstCompileSynchronously;
  160. private bool _enableBurstSafetyChecks;
  161. private bool _enableBurstTimings;
  162. private bool _enableBurstDebug;
  163. private bool _forceEnableBurstSafetyChecks;
  164. private BurstCompilerOptions() : this(false)
  165. {
  166. }
  167. internal BurstCompilerOptions(bool isGlobal)
  168. {
  169. #if UNITY_EDITOR
  170. IsInitializing = true;
  171. #endif
  172. try
  173. {
  174. IsGlobal = isGlobal;
  175. // By default, burst is enabled as well as safety checks
  176. EnableBurstCompilation = true;
  177. EnableBurstSafetyChecks = true;
  178. }
  179. finally
  180. {
  181. #if UNITY_EDITOR
  182. IsInitializing = false;
  183. #endif
  184. }
  185. }
  186. /// <summary>
  187. /// <c>true</c> if this option is the global options that affects menus
  188. /// </summary>
  189. private bool IsGlobal { get; }
  190. /// <summary>
  191. /// Gets a boolean indicating whether burst is enabled.
  192. /// </summary>
  193. public bool IsEnabled
  194. {
  195. get => EnableBurstCompilation && !ForceDisableBurstCompilation;
  196. }
  197. /// <summary>
  198. /// Gets or sets a boolean to enable or disable compilation of burst jobs.
  199. /// </summary>
  200. public bool EnableBurstCompilation
  201. {
  202. get => _enableBurstCompilation;
  203. set
  204. {
  205. // If we are in the global settings, and we are forcing to no burst compilation
  206. if (IsGlobal && ForceDisableBurstCompilation) value = false;
  207. bool changed = _enableBurstCompilation != value;
  208. if (changed && value)
  209. {
  210. MaybePreventChangingOption();
  211. }
  212. _enableBurstCompilation = value;
  213. // Modify only JobsUtility.JobCompilerEnabled when modifying global settings
  214. if (IsGlobal)
  215. {
  216. #if !BURST_INTERNAL
  217. // We need also to disable jobs as functions are being cached by the job system
  218. // and when we ask for disabling burst, we are also asking the job system
  219. // to no longer use the cached functions
  220. JobsUtility.JobCompilerEnabled = value;
  221. #if UNITY_EDITOR
  222. if (changed)
  223. {
  224. // Send the command to the compiler service
  225. if (value)
  226. {
  227. BurstCompiler.Enable();
  228. MaybeTriggerRecompilation();
  229. }
  230. else
  231. {
  232. BurstCompiler.Disable();
  233. }
  234. }
  235. #endif
  236. #endif
  237. // Store the option directly into BurstCompiler.IsEnabled
  238. BurstCompiler._IsEnabled = value;
  239. }
  240. if (changed)
  241. {
  242. OnOptionsChanged();
  243. }
  244. }
  245. }
  246. /// <summary>
  247. /// Gets or sets a boolean to force the compilation of all burst jobs synchronously.
  248. /// </summary>
  249. /// <remarks>
  250. /// This is only available at Editor time. Does not have an impact on player mode.
  251. /// </remarks>
  252. public bool EnableBurstCompileSynchronously
  253. {
  254. get => _enableBurstCompileSynchronously;
  255. set
  256. {
  257. bool changed = _enableBurstCompileSynchronously != value;
  258. _enableBurstCompileSynchronously = value;
  259. if (changed) OnOptionsChanged();
  260. }
  261. }
  262. /// <summary>
  263. /// Gets or sets a boolean to enable or disable safety checks.
  264. /// </summary>
  265. /// <remarks>
  266. /// This is only available at Editor time. Does not have an impact on player mode.
  267. /// </remarks>
  268. public bool EnableBurstSafetyChecks
  269. {
  270. get => _enableBurstSafetyChecks;
  271. set
  272. {
  273. bool changed = _enableBurstSafetyChecks != value;
  274. if (changed)
  275. {
  276. MaybePreventChangingOption();
  277. }
  278. _enableBurstSafetyChecks = value;
  279. if (changed)
  280. {
  281. OnOptionsChanged();
  282. MaybeTriggerRecompilation();
  283. }
  284. }
  285. }
  286. /// <summary>
  287. /// Gets or sets a boolean to force enable safety checks, irrespective of what
  288. /// <c>EnableBurstSafetyChecks</c> is set to, or whether the job or function
  289. /// has <c>DisableSafetyChecks</c> set.
  290. /// </summary>
  291. /// <remarks>
  292. /// This is only available at Editor time. Does not have an impact on player mode.
  293. /// </remarks>
  294. public bool ForceEnableBurstSafetyChecks
  295. {
  296. get => _forceEnableBurstSafetyChecks;
  297. set
  298. {
  299. bool changed = _forceEnableBurstSafetyChecks != value;
  300. if (changed)
  301. {
  302. MaybePreventChangingOption();
  303. }
  304. _forceEnableBurstSafetyChecks = value;
  305. if (changed)
  306. {
  307. OnOptionsChanged();
  308. MaybeTriggerRecompilation();
  309. }
  310. }
  311. }
  312. /// <summary>
  313. /// Enable debugging mode
  314. /// </summary>
  315. public bool EnableBurstDebug
  316. {
  317. get => _enableBurstDebug;
  318. set
  319. {
  320. bool changed = _enableBurstDebug != value;
  321. if (changed)
  322. {
  323. MaybePreventChangingOption();
  324. }
  325. _enableBurstDebug = value;
  326. if (changed)
  327. {
  328. OnOptionsChanged();
  329. MaybeTriggerRecompilation();
  330. }
  331. }
  332. }
  333. /// <summary>
  334. /// This property is no longer used and will be removed in a future major release.
  335. /// </summary>
  336. [Obsolete("This property is no longer used and will be removed in a future major release")]
  337. public bool DisableOptimizations
  338. {
  339. get => false;
  340. set
  341. {
  342. }
  343. }
  344. /// <summary>
  345. /// This property is no longer used and will be removed in a future major release. Use the [BurstCompile(FloatMode = FloatMode.Fast)] on the method directly to enable this feature
  346. /// </summary>
  347. [Obsolete("This property is no longer used and will be removed in a future major release. Use the [BurstCompile(FloatMode = FloatMode.Fast)] on the method directly to enable this feature")]
  348. public bool EnableFastMath
  349. {
  350. get => true;
  351. set
  352. {
  353. // ignored
  354. }
  355. }
  356. internal bool EnableBurstTimings
  357. {
  358. get => _enableBurstTimings;
  359. set
  360. {
  361. bool changed = _enableBurstTimings != value;
  362. _enableBurstTimings = value;
  363. if (changed) OnOptionsChanged();
  364. }
  365. }
  366. internal bool RequiresSynchronousCompilation => EnableBurstCompileSynchronously || ForceBurstCompilationSynchronously;
  367. internal Action OptionsChanged { get; set; }
  368. internal BurstCompilerOptions Clone()
  369. {
  370. // WARNING: for some reason MemberwiseClone() is NOT WORKING on Mono/Unity
  371. // so we are creating a manual clone
  372. var clone = new BurstCompilerOptions
  373. {
  374. EnableBurstCompilation = EnableBurstCompilation,
  375. EnableBurstCompileSynchronously = EnableBurstCompileSynchronously,
  376. EnableBurstSafetyChecks = EnableBurstSafetyChecks,
  377. EnableBurstTimings = EnableBurstTimings,
  378. EnableBurstDebug = EnableBurstDebug,
  379. ForceEnableBurstSafetyChecks = ForceEnableBurstSafetyChecks,
  380. };
  381. return clone;
  382. }
  383. private static bool TryGetAttribute(MemberInfo member, out BurstCompileAttribute attribute, bool isForEagerCompilation = false)
  384. {
  385. attribute = null;
  386. // We don't fail if member == null as this method is being called by native code and doesn't expect to crash
  387. if (member == null)
  388. {
  389. return false;
  390. }
  391. // Fetch options from attribute
  392. attribute = GetBurstCompileAttribute(member);
  393. if (attribute == null)
  394. {
  395. return false;
  396. }
  397. // If we're compiling for eager compilation, and this method has requested not to be eager-compiled... don't compile it.
  398. if (isForEagerCompilation && (attribute.Options?.Contains(DoNotEagerCompile) ?? false))
  399. {
  400. return false;
  401. }
  402. return true;
  403. }
  404. private static bool TryGetAttribute(Assembly assembly, out BurstCompileAttribute attribute)
  405. {
  406. // We don't fail if assembly == null as this method is being called by native code and doesn't expect to crash
  407. if (assembly == null)
  408. {
  409. attribute = null;
  410. return false;
  411. }
  412. // Fetch options from attribute
  413. attribute = assembly.GetCustomAttribute<BurstCompileAttribute>();
  414. return attribute != null;
  415. }
  416. private static BurstCompileAttribute GetBurstCompileAttribute(MemberInfo memberInfo)
  417. {
  418. var result = memberInfo.GetCustomAttribute<BurstCompileAttribute>();
  419. if (result != null)
  420. {
  421. return result;
  422. }
  423. foreach (var a in memberInfo.GetCustomAttributes())
  424. {
  425. var attributeType = a.GetType();
  426. if (attributeType.FullName == "Burst.Compiler.IL.Tests.TestCompilerAttribute")
  427. {
  428. var options = new List<string>();
  429. // Don't eager-compile tests that we expect to fail compilation.
  430. var expectCompilerExceptionProperty = attributeType.GetProperty("ExpectCompilerException");
  431. var expectCompilerException = (expectCompilerExceptionProperty != null)
  432. ? (bool)expectCompilerExceptionProperty.GetValue(a)
  433. : false;
  434. if (expectCompilerException)
  435. {
  436. options.Add(DoNotEagerCompile);
  437. }
  438. return new BurstCompileAttribute(FloatPrecision.Standard, FloatMode.Default)
  439. {
  440. CompileSynchronously = true,
  441. Options = options.ToArray(),
  442. };
  443. }
  444. }
  445. return null;
  446. }
  447. internal static bool HasBurstCompileAttribute(MemberInfo member)
  448. {
  449. if (member == null) throw new ArgumentNullException(nameof(member));
  450. BurstCompileAttribute attr;
  451. return TryGetAttribute(member, out attr);
  452. }
  453. /// <summary>
  454. /// Merges the attributes from the assembly into the member attribute, such that if any field of the member attribute
  455. /// was not specifically set by the user (or is a default), the assembly level setting is used for the Burst compilation.
  456. /// </summary>
  457. internal static void MergeAttributes(ref BurstCompileAttribute memberAttribute, in BurstCompileAttribute assemblyAttribute)
  458. {
  459. if (memberAttribute.FloatMode == FloatMode.Default)
  460. {
  461. memberAttribute.FloatMode = assemblyAttribute.FloatMode;
  462. }
  463. if (memberAttribute.FloatPrecision == FloatPrecision.Standard)
  464. {
  465. memberAttribute.FloatPrecision = assemblyAttribute.FloatPrecision;
  466. }
  467. if (memberAttribute.OptimizeFor == OptimizeFor.Default)
  468. {
  469. memberAttribute.OptimizeFor = assemblyAttribute.OptimizeFor;
  470. }
  471. if (!memberAttribute._compileSynchronously.HasValue && assemblyAttribute._compileSynchronously.HasValue)
  472. {
  473. memberAttribute._compileSynchronously = assemblyAttribute._compileSynchronously;
  474. }
  475. if (!memberAttribute._debug.HasValue && assemblyAttribute._debug.HasValue)
  476. {
  477. memberAttribute._debug = assemblyAttribute._debug;
  478. }
  479. if (!memberAttribute._disableDirectCall.HasValue && assemblyAttribute._disableDirectCall.HasValue)
  480. {
  481. memberAttribute._disableDirectCall = assemblyAttribute._disableDirectCall;
  482. }
  483. if (!memberAttribute._disableSafetyChecks.HasValue && assemblyAttribute._disableSafetyChecks.HasValue)
  484. {
  485. memberAttribute._disableSafetyChecks = assemblyAttribute._disableSafetyChecks;
  486. }
  487. }
  488. /// <summary>
  489. /// Gets the options for the specified member. Returns <c>false</c> if the `[BurstCompile]` attribute was not found.
  490. /// </summary>
  491. /// <returns><c>false</c> if the `[BurstCompile]` attribute was not found; otherwise <c>true</c></returns>
  492. internal bool TryGetOptions(MemberInfo member, bool isJit, out string flagsOut, bool isForEagerCompilation = false, bool isForILPostProcessing = false)
  493. {
  494. flagsOut = null;
  495. if (!TryGetAttribute(member, out var memberAttribute, isForEagerCompilation))
  496. {
  497. return false;
  498. }
  499. if (TryGetAttribute(member.Module.Assembly, out var assemblyAttribute))
  500. {
  501. MergeAttributes(ref memberAttribute, in assemblyAttribute);
  502. }
  503. flagsOut = GetOptions(isJit, memberAttribute, isForEagerCompilation, isForILPostProcessing);
  504. return true;
  505. }
  506. internal string GetOptions(bool isJit, BurstCompileAttribute attr = null, bool isForEagerCompilation = false, bool isForILPostProcessing = false)
  507. {
  508. // Add debug to Jit options instead of passing it here
  509. // attr.Debug
  510. var flagsBuilderOut = new StringBuilder();
  511. if (isJit && !isForEagerCompilation && ((attr?.CompileSynchronously ?? false) || RequiresSynchronousCompilation))
  512. {
  513. AddOption(flagsBuilderOut, GetOption(OptionJitEnableSynchronousCompilation));
  514. }
  515. if (isForILPostProcessing)
  516. {
  517. // IL Post Processing compiles are the only thing set to low priority.
  518. AddOption(flagsBuilderOut, GetOption(OptionJitCompilationPriority, CompilationPriority.ILPP));
  519. }
  520. else if (isJit && isForEagerCompilation)
  521. {
  522. // Eager compilation must always be asynchronous.
  523. // - For synchronous jobs, we set the compilation priority to HighPriority.
  524. // This has two effects:
  525. // - These synchronous jobs will be compiled before asynchronous jobs.
  526. // - We will block on these compilations when entering PlayMode.
  527. // - For asynchronous jobs, we set the compilation priority to LowestPriority.
  528. // These jobs will be compiled after "normal" compilation requests
  529. // for asynchronous jobs, and crucially after all LowPriority ILPostProcessing
  530. // jobs (which can map to the same function pointer to-be-compiled underneath
  531. // and cause compilation thrads to stall).
  532. // Note that we ignore the global "compile synchronously" option here because:
  533. // - If it's set when entering play mode, then we'll wait for all
  534. // methods to be compiled anyway.
  535. // - If it's not set when entering play mode, then we only want to wait
  536. // for methods that explicitly have CompileSynchronously=true on their attributes.
  537. var priority = (attr?.CompileSynchronously ?? false)
  538. ? CompilationPriority.EagerCompilationSynchronous
  539. : CompilationPriority.EagerCompilationAsynchronous;
  540. AddOption(flagsBuilderOut, GetOption(OptionJitCompilationPriority, priority));
  541. // Don't call `burst.initialize` when we're eager-compiling.
  542. AddOption(flagsBuilderOut, GetOption(OptionJitSkipBurstInitialize));
  543. }
  544. if (attr != null)
  545. {
  546. if (attr.FloatMode != FloatMode.Default)
  547. {
  548. AddOption(flagsBuilderOut, GetOption(OptionFloatMode, attr.FloatMode));
  549. }
  550. if (attr.FloatPrecision != FloatPrecision.Standard)
  551. {
  552. AddOption(flagsBuilderOut, GetOption(OptionFloatPrecision, attr.FloatPrecision));
  553. }
  554. // We disable safety checks for jobs with `[BurstCompile(DisableSafetyChecks = true)]`.
  555. if (attr.DisableSafetyChecks)
  556. {
  557. AddOption(flagsBuilderOut, GetOption(OptionDisableSafetyChecks));
  558. }
  559. if (attr.Options != null)
  560. {
  561. foreach (var option in attr.Options)
  562. {
  563. if (!string.IsNullOrEmpty(option))
  564. {
  565. AddOption(flagsBuilderOut, option);
  566. }
  567. }
  568. }
  569. switch (attr.OptimizeFor)
  570. {
  571. case OptimizeFor.Default:
  572. case OptimizeFor.Balanced:
  573. AddOption(flagsBuilderOut, GetOption(OptionOptLevel, 2));
  574. break;
  575. case OptimizeFor.Performance:
  576. AddOption(flagsBuilderOut, GetOption(OptionOptLevel, 3));
  577. break;
  578. case OptimizeFor.Size:
  579. AddOption(flagsBuilderOut, GetOption(OptionOptForSize));
  580. AddOption(flagsBuilderOut, GetOption(OptionOptLevel, 3));
  581. break;
  582. case OptimizeFor.FastCompilation:
  583. AddOption(flagsBuilderOut, GetOption(OptionOptLevel, 1));
  584. break;
  585. }
  586. }
  587. if (ForceEnableBurstSafetyChecks)
  588. {
  589. AddOption(flagsBuilderOut, GetOption(OptionGlobalSafetyChecksSetting, GlobalSafetyChecksSettingKind.ForceOn));
  590. }
  591. else if (EnableBurstSafetyChecks)
  592. {
  593. AddOption(flagsBuilderOut, GetOption(OptionGlobalSafetyChecksSetting, GlobalSafetyChecksSettingKind.On));
  594. }
  595. else
  596. {
  597. AddOption(flagsBuilderOut, GetOption(OptionGlobalSafetyChecksSetting, GlobalSafetyChecksSettingKind.Off));
  598. }
  599. if (isJit && EnableBurstTimings)
  600. {
  601. AddOption(flagsBuilderOut, GetOption(OptionJitLogTimings));
  602. }
  603. if (EnableBurstDebug || (attr?.Debug ?? false))
  604. {
  605. AddOption(flagsBuilderOut, GetOption(OptionDebugMode));
  606. }
  607. return flagsBuilderOut.ToString();
  608. }
  609. private static void AddOption(StringBuilder builder, string option)
  610. {
  611. if (builder.Length != 0)
  612. builder.Append('\n'); // Use \n to separate options
  613. builder.Append(option);
  614. }
  615. internal static string GetOption(string optionName, object value = null)
  616. {
  617. if (optionName == null) throw new ArgumentNullException(nameof(optionName));
  618. return "--" + optionName + (value ?? String.Empty);
  619. }
  620. private void OnOptionsChanged()
  621. {
  622. OptionsChanged?.Invoke();
  623. }
  624. private void MaybeTriggerRecompilation()
  625. {
  626. #if UNITY_EDITOR && UNITY_2019_3_OR_NEWER
  627. if (IsGlobal && IsEnabled && !IsInitializing)
  628. {
  629. UnityEditor.EditorUtility.DisplayProgressBar("Burst", "Waiting for compilation to finish", -1);
  630. try
  631. {
  632. BurstCompiler.TriggerRecompilation();
  633. }
  634. finally
  635. {
  636. UnityEditor.EditorUtility.ClearProgressBar();
  637. }
  638. }
  639. #endif
  640. }
  641. /// <summary>
  642. /// This method should be called before changing any option that requires
  643. /// an Editor restart in versions older than 2019.3.
  644. ///
  645. /// This is because Editors older than 2019.3 don't support recompilation
  646. /// of already-compiled jobs.
  647. /// </summary>
  648. private void MaybePreventChangingOption()
  649. {
  650. #if UNITY_EDITOR && !UNITY_2019_3_OR_NEWER
  651. if (IsGlobal && !IsInitializing)
  652. {
  653. if (RequiresRestartUtility.CalledFromUI)
  654. {
  655. RequiresRestartUtility.RequiresRestart = true;
  656. }
  657. else
  658. {
  659. throw new InvalidOperationException("This option cannot be set programmatically in 2019.2 and older versions of the Editor");
  660. }
  661. }
  662. #endif
  663. }
  664. #if !UNITY_DOTSPLAYER && !NET_DOTS
  665. /// <summary>
  666. /// Static initializer based on command line arguments
  667. /// </summary>
  668. static BurstCompilerOptions()
  669. {
  670. foreach (var arg in Environment.GetCommandLineArgs())
  671. {
  672. switch (arg)
  673. {
  674. case DisableCompilationArg:
  675. ForceDisableBurstCompilation = true;
  676. break;
  677. case ForceSynchronousCompilationArg:
  678. ForceBurstCompilationSynchronously = true;
  679. break;
  680. }
  681. }
  682. if (CheckIsSecondaryUnityProcess())
  683. {
  684. ForceDisableBurstCompilation = true;
  685. IsSecondaryUnityProcess = true;
  686. }
  687. }
  688. private static bool CheckIsSecondaryUnityProcess()
  689. {
  690. #if UNITY_EDITOR
  691. #if UNITY_2021_1_OR_NEWER
  692. if (UnityEditor.MPE.ProcessService.level == UnityEditor.MPE.ProcessLevel.Secondary
  693. || UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
  694. {
  695. return true;
  696. }
  697. #elif UNITY_2020_2_OR_NEWER
  698. if (UnityEditor.MPE.ProcessService.level == UnityEditor.MPE.ProcessLevel.Slave
  699. || UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
  700. {
  701. return true;
  702. }
  703. #elif UNITY_2019_4_OR_NEWER
  704. if (Unity.MPE.ProcessService.level == Unity.MPE.ProcessLevel.UMP_SLAVE
  705. || UnityEditor.Experimental.AssetDatabaseExperimental.IsAssetImportWorkerProcess())
  706. {
  707. return true;
  708. }
  709. #endif
  710. #endif
  711. return false;
  712. }
  713. #endif
  714. #endif // !BURST_COMPILER_SHARED
  715. }
  716. #if UNITY_EDITOR
  717. // NOTE: This must be synchronized with Backend.TargetPlatform
  718. internal enum TargetPlatform
  719. {
  720. Windows = 0,
  721. macOS = 1,
  722. Linux = 2,
  723. Android = 3,
  724. iOS = 4,
  725. PS4 = 5,
  726. XboxOne = 6,
  727. WASM = 7,
  728. UWP = 8,
  729. Lumin = 9,
  730. Switch = 10,
  731. Stadia = 11,
  732. tvOS = 12,
  733. EmbeddedLinux = 13,
  734. GameCoreXboxOne = 14,
  735. GameCoreXboxSeries = 15,
  736. PS5 = 16,
  737. }
  738. #endif
  739. // Need this enum for CPU intrinsics to work, so exposing it to Tiny too
  740. #endif //!UNITY_DOTSPLAYER && !NET_DOTS
  741. // Don't expose the enum in Burst.Compiler.IL, need only in Unity.Burst.dll which is referenced by Burst.Compiler.IL.Tests
  742. #if !BURST_COMPILER_SHARED
  743. // Make the enum public for btests via Unity.Burst.dll; leave it internal in the package
  744. #if BURST_INTERNAL
  745. public
  746. #else
  747. internal
  748. #endif
  749. // NOTE: This must be synchronized with Backend.TargetCpu
  750. enum BurstTargetCpu
  751. {
  752. Auto = 0,
  753. X86_SSE2 = 1,
  754. X86_SSE4 = 2,
  755. X64_SSE2 = 3,
  756. X64_SSE4 = 4,
  757. AVX = 5,
  758. AVX2 = 6,
  759. WASM32 = 7,
  760. ARMV7A_NEON32 = 8,
  761. ARMV8A_AARCH64 = 9,
  762. THUMB2_NEON32 = 10,
  763. ARMV8A_AARCH64_HALFFP = 11,
  764. }
  765. #endif
  766. #if !UNITY_DOTSPLAYER && !NET_DOTS
  767. /// <summary>
  768. /// Flags used by <see cref="NativeCompiler.CompileMethod"/> to dump intermediate compiler results.
  769. /// </summary>
  770. [Flags]
  771. #if BURST_COMPILER_SHARED
  772. public enum NativeDumpFlags
  773. #else
  774. internal enum NativeDumpFlags
  775. #endif
  776. {
  777. /// <summary>
  778. /// Nothing is selected.
  779. /// </summary>
  780. None = 0,
  781. /// <summary>
  782. /// Dumps the IL of the method being compiled
  783. /// </summary>
  784. IL = 1 << 0,
  785. /// <summary>
  786. /// Dumps the reformated backend API Calls
  787. /// </summary>
  788. Backend = 1 << 1,
  789. /// <summary>
  790. /// Dumps the generated module without optimizations
  791. /// </summary>
  792. IR = 1 << 2,
  793. /// <summary>
  794. /// Dumps the generated backend code after optimizations (if enabled)
  795. /// </summary>
  796. IROptimized = 1 << 3,
  797. /// <summary>
  798. /// Dumps the generated ASM code
  799. /// </summary>
  800. Asm = 1 << 4,
  801. /// <summary>
  802. /// Generate the native code
  803. /// </summary>
  804. Function = 1 << 5,
  805. /// <summary>
  806. /// Dumps the result of analysis
  807. /// </summary>
  808. Analysis = 1 << 6,
  809. /// <summary>
  810. /// Dumps the diagnostics from optimisation
  811. /// </summary>
  812. IRPassAnalysis = 1 << 7,
  813. /// <summary>
  814. /// Dumps the IL before all transformation of the method being compiled
  815. /// </summary>
  816. ILPre = 1 << 8,
  817. /// <summary>
  818. /// Dumps all normal output.
  819. /// </summary>
  820. All = IL | ILPre | IR | IROptimized | Asm | Function | Analysis | IRPassAnalysis
  821. }
  822. #if BURST_COMPILER_SHARED
  823. public enum CompilationPriority
  824. #else
  825. internal enum CompilationPriority
  826. #endif
  827. {
  828. EagerCompilationSynchronous = 0,
  829. Asynchronous = 1,
  830. ILPP = 2,
  831. EagerCompilationAsynchronous = 3,
  832. }
  833. #if UNITY_EDITOR
  834. /// <summary>
  835. /// Some options cannot be applied until after an Editor restart, in Editor versions prior to 2019.3.
  836. /// This class assists with allowing the relevant settings to be changed via the menu,
  837. /// followed by displaying a message to the user to say a restart is necessary.
  838. /// </summary>
  839. internal static class RequiresRestartUtility
  840. {
  841. [ThreadStatic]
  842. public static bool CalledFromUI;
  843. [ThreadStatic]
  844. public static bool RequiresRestart;
  845. }
  846. #endif
  847. internal readonly struct EagerCompilationRequest
  848. {
  849. public EagerCompilationRequest(string encodedMethod, string options)
  850. {
  851. EncodedMethod = encodedMethod;
  852. Options = options;
  853. }
  854. public readonly string EncodedMethod;
  855. public readonly string Options;
  856. }
  857. #endif //!UNITY_DOTSPLAYER && !NET_DOTS
  858. }