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