No Description
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.

BurstLoader.cs 30KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. #if UNITY_EDITOR
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Reflection;
  7. using System.Runtime.CompilerServices;
  8. using System.Runtime.InteropServices;
  9. using Unity.Burst.LowLevel;
  10. using Unity.Profiling;
  11. using Unity.Profiling.LowLevel;
  12. using Unity.Profiling.LowLevel.Unsafe;
  13. using UnityEditor;
  14. using UnityEditor.Compilation;
  15. using UnityEditor.Scripting.ScriptCompilation;
  16. using UnityEngine;
  17. namespace Unity.Burst.Editor
  18. {
  19. /// <summary>
  20. /// Main entry point for initializing the burst compiler service for both JIT and AOT
  21. /// </summary>
  22. [InitializeOnLoad]
  23. internal class BurstLoader
  24. {
  25. private const int BURST_PROTOCOL_VERSION = 1;
  26. // Cache the delegate to make sure it doesn't get collected.
  27. private static readonly BurstCompilerService.ExtractCompilerFlags TryGetOptionsFromMemberDelegate = TryGetOptionsFromMember;
  28. /// <summary>
  29. /// Gets the location to the runtime path of burst.
  30. /// </summary>
  31. public static string RuntimePath { get; private set; }
  32. public static BclConfiguration BclConfiguration { get; private set; }
  33. public static bool IsDebugging { get; private set; }
  34. public static bool SafeShutdown { get; private set; }
  35. public static int ProtocolVersion { get; private set; }
  36. private static void VersionUpdateCheck()
  37. {
  38. var seek = "com.unity.burst@";
  39. var first = RuntimePath.LastIndexOf(seek);
  40. var last = RuntimePath.LastIndexOf(".Runtime");
  41. string version;
  42. if (first == -1 || last == -1 || last <= first)
  43. {
  44. version = "Unknown";
  45. }
  46. else
  47. {
  48. first += seek.Length;
  49. last -= 1;
  50. version = RuntimePath.Substring(first, last - first);
  51. }
  52. var result = BurstCompiler.VersionNotify(version);
  53. // result will be empty if we are shutting down, and thus we shouldn't popup a dialog
  54. if (!String.IsNullOrEmpty(result) && result != version)
  55. {
  56. if (IsDebugging)
  57. {
  58. UnityEngine.Debug.LogWarning($"[com.unity.burst] - '{result}' != '{version}'");
  59. }
  60. OnVersionChangeDetected();
  61. }
  62. }
  63. private static bool UnityBurstRuntimePathOverwritten(out string path)
  64. {
  65. path = Environment.GetEnvironmentVariable("UNITY_BURST_RUNTIME_PATH");
  66. return Directory.Exists(path);
  67. }
  68. private static void OnVersionChangeDetected()
  69. {
  70. // Write marker file to tell Burst to delete the cache at next startup.
  71. try
  72. {
  73. File.Create(Path.Combine(BurstCompilerOptions.DefaultCacheFolder, BurstCompilerOptions.DeleteCacheMarkerFileName)).Dispose();
  74. }
  75. catch (IOException)
  76. {
  77. // In the unlikely scenario that two processes are creating this marker file at the same time,
  78. // and one of them fails, do nothing because the other one has hopefully succeeded.
  79. }
  80. // Skip checking if we are using an explicit runtime path.
  81. if (!UnityBurstRuntimePathOverwritten(out var _))
  82. {
  83. EditorUtility.DisplayDialog("Burst Package Update Detected", "The version of Burst used by your project has changed. Please restart the Editor to continue.", "OK");
  84. BurstCompiler.Shutdown();
  85. }
  86. }
  87. private static CompilationTaskReason _currentBuildKind;
  88. static BurstLoader()
  89. {
  90. if (BurstCompilerOptions.ForceDisableBurstCompilation)
  91. {
  92. if (!BurstCompilerOptions.IsSecondaryUnityProcess)
  93. {
  94. UnityEngine.Debug.LogWarning("[com.unity.burst] Burst is disabled entirely from the command line");
  95. }
  96. return;
  97. }
  98. // This can be setup to get more diagnostics
  99. var debuggingStr = Environment.GetEnvironmentVariable("UNITY_BURST_DEBUG");
  100. IsDebugging = debuggingStr != null && int.TryParse(debuggingStr, out var debugLevel) && debugLevel > 0;
  101. if (IsDebugging)
  102. {
  103. UnityEngine.Debug.LogWarning("[com.unity.burst] Extra debugging is turned on.");
  104. }
  105. // Try to load the runtime through an environment variable
  106. var isRuntimePathOverwritten = UnityBurstRuntimePathOverwritten(out var path);
  107. if (!isRuntimePathOverwritten)
  108. {
  109. // Otherwise try to load it from the package itself
  110. #if UNITY_2021_3_OR_NEWER
  111. path = FileUtil.GetPhysicalPath("Packages/com.unity.burst/.Runtime");
  112. #else
  113. path = Path.GetFullPath("Packages/com.unity.burst/.Runtime");
  114. #endif
  115. }
  116. RuntimePath = path;
  117. BclConfiguration = GetBclConfiguration(path, isRuntimePathOverwritten);
  118. if (IsDebugging)
  119. {
  120. UnityEngine.Debug.LogWarning($"[com.unity.burst] Runtime directory set to {RuntimePath}");
  121. }
  122. BurstCompilerService.Initialize(RuntimePath, TryGetOptionsFromMemberDelegate);
  123. ProtocolVersion = BurstCompiler.RequestSetProtocolVersion(BURST_PROTOCOL_VERSION);
  124. BurstCompiler.Initialize(GetAssemblyFolders(),BurstAssemblyDisable.GetDisabledAssemblies(BurstAssemblyDisable.DisableType.Editor, ""));
  125. // It's important that this call comes *after* BurstCompilerService.Initialize,
  126. // otherwise any calls from within EnsureSynchronized to BurstCompilerService,
  127. // such as BurstCompiler.Disable(), will silently fail.
  128. BurstEditorOptions.EnsureSynchronized();
  129. EditorApplication.quitting += OnEditorApplicationQuitting;
  130. CompilationPipeline.compilationStarted += OnCompilationStarted;
  131. CompilationPipeline.compilationFinished += OnCompilationFinished;
  132. // We use this internal event because it's the only way to get access to the ScriptAssembly.HasCompileErrors,
  133. // which tells us whether C# compilation succeeded or failed for this assembly.
  134. EditorCompilationInterface.Instance.assemblyCompilationFinished += OnAssemblyCompilationFinished;
  135. #if UNITY_2022_2_OR_NEWER
  136. CompilationPipeline.assemblyCompilationNotRequired += OnAssemblyCompilationNotRequired;
  137. #endif
  138. EditorApplication.playModeStateChanged += EditorApplicationOnPlayModeStateChanged;
  139. AppDomain.CurrentDomain.DomainUnload += OnDomainUnload;
  140. SafeShutdown = false;
  141. UnityEditor.PackageManager.Events.registeringPackages += PackageRegistrationEvent;
  142. SafeShutdown = BurstCompiler.IsApiAvailable("SafeShutdown");
  143. if (!SafeShutdown)
  144. {
  145. VersionUpdateCheck();
  146. }
  147. // Notify the compiler about a domain reload
  148. if (IsDebugging)
  149. {
  150. UnityEngine.Debug.Log("Burst - Domain Reload");
  151. }
  152. BurstCompiler.OnProgress += OnProgress;
  153. BurstCompiler.EagerCompilationLoggingEnabled = true;
  154. // Make sure BurstRuntime is initialized. This needs to happen before BurstCompiler.DomainReload,
  155. // because that can cause calls to BurstRuntime.Log.
  156. BurstRuntime.Initialize();
  157. // Notify the JitCompilerService about a domain reload
  158. BurstCompiler.SetDefaultOptions();
  159. BurstCompiler.DomainReload();
  160. BurstCompiler.OnProfileBegin += OnProfileBegin;
  161. BurstCompiler.OnProfileEnd += OnProfileEnd;
  162. BurstCompiler.SetProfilerCallbacks();
  163. BurstCompiler.InitialiseDebuggerHooks();
  164. }
  165. private static bool _isQuitting;
  166. private static void OnEditorApplicationQuitting()
  167. {
  168. _isQuitting = true;
  169. }
  170. public static Action OnBurstShutdown;
  171. private static void PackageRegistrationEvent(UnityEditor.PackageManager.PackageRegistrationEventArgs obj)
  172. {
  173. bool requireCleanup = false;
  174. if (SafeShutdown)
  175. {
  176. foreach (var changed in obj.changedFrom)
  177. {
  178. if (changed.name.Contains("com.unity.burst"))
  179. {
  180. requireCleanup = true;
  181. break;
  182. }
  183. }
  184. }
  185. foreach (var removed in obj.removed)
  186. {
  187. if (removed.name.Contains("com.unity.burst"))
  188. {
  189. requireCleanup = true;
  190. }
  191. }
  192. if (requireCleanup)
  193. {
  194. OnBurstShutdown?.Invoke();
  195. if (!SafeShutdown)
  196. {
  197. EditorUtility.DisplayDialog("Burst Package Has Been Removed", "Please restart the Editor to continue.", "OK");
  198. }
  199. BurstCompiler.Shutdown();
  200. }
  201. }
  202. private static BclConfiguration GetBclConfiguration(string runtimePath, bool isRuntimePathOverwritten)
  203. {
  204. string bclFolderPath;
  205. if (isRuntimePathOverwritten)
  206. {
  207. return new BclConfiguration
  208. {
  209. FolderPath = runtimePath,
  210. ExecutablePath = Path.Combine(runtimePath, "bcl.exe"),
  211. IsExecutableNative = false,
  212. };
  213. }
  214. else
  215. {
  216. bclFolderPath = Path.Combine(runtimePath, "bcl", GetBclPlatformFolderName());
  217. if (Directory.Exists(bclFolderPath))
  218. {
  219. var bclFileName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
  220. ? "bcl.exe"
  221. : "bcl";
  222. return new BclConfiguration
  223. {
  224. FolderPath = bclFolderPath,
  225. ExecutablePath = Path.Combine(bclFolderPath, bclFileName),
  226. IsExecutableNative = true,
  227. };
  228. }
  229. return new BclConfiguration
  230. {
  231. FolderPath = runtimePath,
  232. ExecutablePath = Path.Combine(runtimePath, "bcl.exe"),
  233. IsExecutableNative = false,
  234. };
  235. }
  236. }
  237. private static string GetBclPlatformFolderName()
  238. {
  239. var hostPlatform = Application.platform;
  240. var hostArchitecture = RuntimeInformation.OSArchitecture;
  241. switch (hostPlatform)
  242. {
  243. case RuntimePlatform.WindowsEditor:
  244. return "win-x64";
  245. case RuntimePlatform.OSXEditor when hostArchitecture == Architecture.X64:
  246. return "osx-x64";
  247. case RuntimePlatform.OSXEditor when hostArchitecture == Architecture.Arm64:
  248. return "osx-arm64";
  249. case RuntimePlatform.LinuxEditor:
  250. return "linux-x64";
  251. default:
  252. throw new InvalidOperationException($"Current OS platform {hostPlatform} and architecture {hostArchitecture} combination is not supported");
  253. }
  254. }
  255. // Don't initialize to 0 because that could be a valid progress ID.
  256. private static int BurstProgressId = -1;
  257. // If this enum changes, update the benchmarks tool accordingly as we rely on integer value related to this enum
  258. internal enum BurstEagerCompilationStatus
  259. {
  260. NotScheduled,
  261. Scheduled,
  262. Completed
  263. }
  264. // For the time being, this field is only read through reflection
  265. internal static BurstEagerCompilationStatus EagerCompilationStatus;
  266. private static void OnProgress(int current, int total)
  267. {
  268. if (current == total)
  269. {
  270. EagerCompilationStatus = BurstEagerCompilationStatus.Completed;
  271. }
  272. // OnProgress is called from a background thread,
  273. // but we need to update the progress UI on the main thread.
  274. EditorApplication.CallDelayed(() =>
  275. {
  276. if (current == total)
  277. {
  278. // We've finished - remove progress bar.
  279. if (Progress.Exists(BurstProgressId))
  280. {
  281. Progress.Remove(BurstProgressId);
  282. BurstProgressId = -1;
  283. }
  284. }
  285. else
  286. {
  287. // Do we need to create the progress bar?
  288. if (!Progress.Exists(BurstProgressId))
  289. {
  290. BurstProgressId = Progress.Start(
  291. "Burst",
  292. "Compiling...",
  293. Progress.Options.Unmanaged);
  294. }
  295. Progress.Report(
  296. BurstProgressId,
  297. current / (float)total,
  298. $"Compiled {current} / {total} libraries");
  299. }
  300. });
  301. }
  302. [ThreadStatic]
  303. private static Dictionary<string, IntPtr> ProfilerMarkers;
  304. private static unsafe void OnProfileBegin(string markerName, string metadataName, string metadataValue)
  305. {
  306. if (ProfilerMarkers == null)
  307. {
  308. // Initialize thread-static dictionary.
  309. ProfilerMarkers = new Dictionary<string, IntPtr>();
  310. }
  311. if (!ProfilerMarkers.TryGetValue(markerName, out var markerPtr))
  312. {
  313. ProfilerMarkers.Add(markerName, markerPtr = ProfilerUnsafeUtility.CreateMarker(
  314. markerName,
  315. ProfilerUnsafeUtility.CategoryScripts,
  316. MarkerFlags.Script,
  317. metadataName != null ? 1 : 0));
  318. // metadataName is assumed to be consistent for a given markerName.
  319. if (metadataName != null)
  320. {
  321. ProfilerUnsafeUtility.SetMarkerMetadata(
  322. markerPtr,
  323. 0,
  324. metadataName,
  325. (byte)ProfilerMarkerDataType.String16,
  326. (byte)ProfilerMarkerDataUnit.Undefined);
  327. }
  328. }
  329. if (metadataName != null && metadataValue != null)
  330. {
  331. fixed (char* methodNamePtr = metadataValue)
  332. {
  333. var metadata = new ProfilerMarkerData
  334. {
  335. Type = (byte)ProfilerMarkerDataType.String16,
  336. Size = ((uint)metadataValue.Length + 1) * 2,
  337. Ptr = methodNamePtr
  338. };
  339. ProfilerUnsafeUtility.BeginSampleWithMetadata(markerPtr, 1, &metadata);
  340. }
  341. }
  342. else
  343. {
  344. ProfilerUnsafeUtility.BeginSample(markerPtr);
  345. }
  346. }
  347. private static void OnProfileEnd(string markerName)
  348. {
  349. if (ProfilerMarkers == null)
  350. {
  351. // If we got here it means we had a domain reload between when we called profile begin and
  352. // now profile end, and so we need to bail out.
  353. return;
  354. }
  355. if (!ProfilerMarkers.TryGetValue(markerName, out var markerPtr))
  356. {
  357. return;
  358. }
  359. ProfilerUnsafeUtility.EndSample(markerPtr);
  360. }
  361. private static void EditorApplicationOnPlayModeStateChanged(PlayModeStateChange state)
  362. {
  363. if (IsDebugging)
  364. {
  365. UnityEngine.Debug.Log($"Burst - Change of Editor State: {state}");
  366. }
  367. switch (state)
  368. {
  369. case PlayModeStateChange.ExitingPlayMode:
  370. // Cleanup any loaded burst natives so users have a clean point to update the libraries.
  371. BurstCompiler.UnloadAdditionalLibraries();
  372. break;
  373. }
  374. }
  375. enum CompilationTaskReason
  376. {
  377. IsForEditor, // Compilation should proceed as its for an editor build
  378. IsForPlayer, // Skip this compilation
  379. IsForPreviousScriptingMode, // We are about to enter a domain reload, don't start any new compilations
  380. IsForAssemblyBuilder, // Request is coming from an 'AssemblyBuilder' and should be skipped as not supported
  381. }
  382. static CompilationTaskReason CurrentCompilationTaskShouldStart()
  383. {
  384. try
  385. {
  386. if (BurstCompiler.WasScriptDebugInfoEnabledAtDomainReload != UnityEditor.Compilation.CompilationPipeline.IsScriptDebugInfoEnabled())
  387. {
  388. // If the scripting compilation mode has changed since we last had our domain reloaded, then we ignore all requests, and act as if
  389. //loading for the first time. This is to avoid having compilations kick off right before a Shutdown triggered by domain reload, that
  390. //would cause the a significant stall as we had to wait for those compilations to finish, thus blocking the main thread.
  391. return CompilationTaskReason.IsForPreviousScriptingMode;
  392. }
  393. var inst = EditorCompilationInterface.Instance;
  394. #if UNITY_2021_1_OR_NEWER
  395. var editorCompilationType = inst.GetType();
  396. var activeBeeBuildField = editorCompilationType.GetField("_currentBeeScriptCompilationState", BindingFlags.Instance | BindingFlags.NonPublic);
  397. if (activeBeeBuildField == null)
  398. {
  399. activeBeeBuildField = editorCompilationType.GetField("activeBeeBuild", BindingFlags.Instance | BindingFlags.NonPublic);
  400. }
  401. var activeBeeBuild = activeBeeBuildField.GetValue(inst);
  402. // If a user is doing an `AssemblyBuilder` compilation, we do not support that in Burst.
  403. // This seems to manifest as a null `activeBeeBuild`, so we bail here if that happens.
  404. if (activeBeeBuild == null)
  405. {
  406. return CompilationTaskReason.IsForAssemblyBuilder;
  407. }
  408. var settings = activeBeeBuild.GetType().GetProperty("settings", BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).GetValue(activeBeeBuild);
  409. var opt = (EditorScriptCompilationOptions)settings.GetType().GetProperty("CompilationOptions").GetValue(settings);
  410. #else
  411. var task = inst.GetType()
  412. .GetField("compilationTask", BindingFlags.Instance | BindingFlags.NonPublic)
  413. .GetValue(inst);
  414. // If a user is doing an `AssemblyBuilder` compilation, we do not support that in Burst.
  415. // This seems to manifest as a null `task`, so we bail here if that happens.
  416. if (task == null)
  417. {
  418. return CompilationTaskReason.IsForAssemblyBuilder;
  419. }
  420. var opt = (EditorScriptCompilationOptions)task.GetType()
  421. .GetField("options", BindingFlags.Instance | BindingFlags.NonPublic)
  422. .GetValue(task);
  423. #endif
  424. #if UNITY_2022_2_OR_NEWER
  425. if ((opt & EditorScriptCompilationOptions.BuildingSkipCompile) != 0)
  426. {
  427. return CompilationTaskReason.IsForPlayer;
  428. }
  429. #endif
  430. if ((opt & EditorScriptCompilationOptions.BuildingForEditor) != 0)
  431. {
  432. return CompilationTaskReason.IsForEditor;
  433. }
  434. return CompilationTaskReason.IsForPlayer;
  435. }
  436. catch (Exception ex)
  437. {
  438. UnityEngine.Debug.LogWarning("Burst - Unknown private compilation pipeline API\nAssuming editor build\n" + ex.ToString());
  439. return CompilationTaskReason.IsForEditor;
  440. }
  441. }
  442. private static void OnCompilationStarted(object value)
  443. {
  444. _currentBuildKind = CurrentCompilationTaskShouldStart();
  445. if (_currentBuildKind != CompilationTaskReason.IsForEditor)
  446. {
  447. if (IsDebugging)
  448. {
  449. UnityEngine.Debug.Log($"{DateTime.UtcNow} Burst - not handling '{value}' because '{_currentBuildKind}'");
  450. }
  451. return;
  452. }
  453. if (IsDebugging)
  454. {
  455. UnityEngine.Debug.Log($"{DateTime.UtcNow} Burst - compilation started for '{value}'");
  456. }
  457. BurstCompiler.NotifyCompilationStarted(GetAssemblyFolders(),
  458. BurstAssemblyDisable.GetDisabledAssemblies(BurstAssemblyDisable.DisableType.Editor,"") );
  459. }
  460. private static string[] GetAssemblyFolders()
  461. {
  462. var assemblyFolders = new HashSet<string>();
  463. // First, we get the path to Mono system libraries. This will be something like
  464. // <EditorPath>/Data/MonoBleedingEdge/lib/mono/unityjit-win32
  465. //
  466. // You might think we could use MonoLibraryHelpers.GetSystemReferenceDirectories
  467. // here, but we can't, because that returns the _reference assembly_ directories,
  468. // not the actual implementation assembly directory.
  469. var systemLibraryDirectory = Path.GetDirectoryName(typeof(object).Assembly.Location);
  470. assemblyFolders.Add(systemLibraryDirectory);
  471. // Also add the Facades directory, since that contains netstandard. Without this,
  472. // we'll potentially resolve the "wrong" netstandard from a dotnet compiler host.
  473. assemblyFolders.Add(Path.Combine(systemLibraryDirectory, "Facades"));
  474. // Now add the default assembly search paths.
  475. // This will include
  476. // - Unity dlls in <EditorPath>/Data/Managed and <EditorPath>/Data/Managed/UnityEngine
  477. // - Platform support dlls e.g. <EditorPath>/Data/PlaybackEngines/WindowsStandaloneSupport
  478. // - Package paths. These are interesting because they are "virtual" paths, of the form
  479. // Packages/<MyPackageName>. They need to be resolved to physical paths.
  480. // - Library/ScriptAssemblies. This needs to be resolved to the full path.
  481. var defaultAssemblySearchPaths = AssemblyHelper.GetDefaultAssemblySearchPaths();
  482. #if UNITY_2021_3_OR_NEWER
  483. foreach (var searchPath in defaultAssemblySearchPaths)
  484. {
  485. var resolvedPath = FileUtil.PathToAbsolutePath(searchPath);
  486. if (!string.IsNullOrEmpty(resolvedPath))
  487. {
  488. assemblyFolders.Add(resolvedPath);
  489. }
  490. }
  491. #else
  492. var packagesLookup = GetPackagesLookup();
  493. foreach (var searchPath in defaultAssemblySearchPaths)
  494. {
  495. if (TryResolvePath(searchPath, packagesLookup, out var resolvedPath))
  496. {
  497. assemblyFolders.Add(resolvedPath);
  498. }
  499. }
  500. #endif
  501. if (IsDebugging)
  502. {
  503. UnityEngine.Debug.Log($"{DateTime.UtcNow} Burst - AssemblyFolders : \n{string.Join("\n", assemblyFolders)}");
  504. }
  505. return assemblyFolders.ToArray();
  506. }
  507. #if !UNITY_2021_3_OR_NEWER
  508. private static Dictionary<string, string> GetPackagesLookup()
  509. {
  510. var packages = new Dictionary<string, string>();
  511. // Fetch list of packages
  512. #if UNITY_2021_1_OR_NEWER
  513. var allPackages = UnityEditor.PackageManager.PackageInfo.GetAllRegisteredPackages();
  514. #else
  515. var allPackages = UnityEditor.PackageManager.PackageInfo.GetAll();
  516. #endif
  517. foreach (var p in allPackages)
  518. {
  519. packages.Add(p.name, p.resolvedPath);
  520. }
  521. return packages;
  522. }
  523. private const string PackagesPath = "Packages/";
  524. private static readonly int PackagesPathLength = PackagesPath.Length;
  525. private static bool TryResolvePath(string path, Dictionary<string, string> packagesLookup, out string resolvedPath)
  526. {
  527. if (string.IsNullOrEmpty(path))
  528. {
  529. resolvedPath = null;
  530. return false;
  531. }
  532. else if (path.StartsWith("Packages/", StringComparison.InvariantCulture))
  533. {
  534. var secondSlashIndex = path.IndexOf('/', PackagesPathLength);
  535. var packageName = secondSlashIndex > -1
  536. ? path.Substring(PackagesPathLength, secondSlashIndex - PackagesPathLength)
  537. : path.Substring(PackagesPathLength);
  538. if (packagesLookup.TryGetValue(packageName, out var resolvedPathTemp))
  539. {
  540. path = secondSlashIndex > -1
  541. ? Path.Combine(resolvedPathTemp, path.Substring(secondSlashIndex + 1))
  542. : resolvedPathTemp;
  543. }
  544. else
  545. {
  546. if (IsDebugging)
  547. {
  548. UnityEngine.Debug.Log($"{DateTime.UtcNow} Burst - unknown package path '{path}'");
  549. }
  550. resolvedPath = null;
  551. return false;
  552. }
  553. }
  554. resolvedPath = Path.GetFullPath(path);
  555. return true;
  556. }
  557. #endif
  558. private static void OnCompilationFinished(object value)
  559. {
  560. if (_currentBuildKind!=CompilationTaskReason.IsForEditor)
  561. {
  562. if (IsDebugging)
  563. {
  564. UnityEngine.Debug.Log($"{DateTime.UtcNow} Burst - ignoring finished compilation '{value}' because it's '{_currentBuildKind}'");
  565. }
  566. _currentBuildKind = CompilationTaskReason.IsForEditor;
  567. return;
  568. }
  569. if (IsDebugging)
  570. {
  571. UnityEngine.Debug.Log($"{DateTime.UtcNow} Burst - compilation finished for '{value}'");
  572. }
  573. BurstCompiler.NotifyCompilationFinished();
  574. }
  575. #if UNITY_2021_1_OR_NEWER
  576. private static void OnAssemblyCompilationFinished(ScriptAssembly assembly, CompilerMessage[] messages)
  577. #else
  578. private static void OnAssemblyCompilationFinished(ScriptAssembly assembly, CompilerMessage[] messages, EditorScriptCompilationOptions options)
  579. #endif
  580. {
  581. if (_currentBuildKind!=CompilationTaskReason.IsForEditor)
  582. {
  583. if (IsDebugging)
  584. {
  585. UnityEngine.Debug.Log($"{DateTime.UtcNow} Burst - ignoring '{assembly.Filename}' because it's '{_currentBuildKind}'");
  586. }
  587. return;
  588. }
  589. if (IsDebugging)
  590. {
  591. UnityEngine.Debug.Log($"{DateTime.UtcNow} Burst - Assembly compilation finished for '{assembly.Filename}'");
  592. }
  593. if (assembly.HasCompileErrors)
  594. {
  595. if (IsDebugging)
  596. {
  597. UnityEngine.Debug.Log($"{DateTime.UtcNow} Burst - ignoring '{assembly.Filename}' because it failed C# compilation");
  598. }
  599. return;
  600. }
  601. BurstCompiler.NotifyAssemblyCompilationFinished(Path.GetFileNameWithoutExtension(assembly.Filename), assembly.Defines);
  602. }
  603. private static void OnAssemblyCompilationNotRequired(string arg1)
  604. {
  605. if (_currentBuildKind!=CompilationTaskReason.IsForEditor)
  606. {
  607. if (IsDebugging)
  608. {
  609. UnityEngine.Debug.Log($"{DateTime.UtcNow} Burst - ignoring '{arg1}' because it's '{_currentBuildKind}'");
  610. }
  611. return;
  612. }
  613. if (IsDebugging)
  614. {
  615. UnityEngine.Debug.Log($"{DateTime.UtcNow} Burst - Assembly compilation not required for '{arg1}'");
  616. }
  617. BurstCompiler.NotifyAssemblyCompilationNotRequired(Path.GetFileNameWithoutExtension(arg1));
  618. }
  619. private static bool TryGetOptionsFromMember(MemberInfo member, out string flagsOut)
  620. {
  621. return BurstCompiler.Options.TryGetOptions(member, out flagsOut);
  622. }
  623. private static void OnDomainUnload(object sender, EventArgs e)
  624. {
  625. if (IsDebugging)
  626. {
  627. UnityEngine.Debug.Log($"Burst - OnDomainUnload");
  628. }
  629. BurstCompiler.Cancel();
  630. // This check here is to execute shutdown after all OnDisable's. EditorApplication.quitting event is called before OnDisable's, so we need to shutdown in here.
  631. if (_isQuitting)
  632. {
  633. BurstCompiler.Shutdown();
  634. }
  635. // Because of a check in Unity (specifically SCRIPTINGAPI_THREAD_AND_SERIALIZATION_CHECK),
  636. // we are not allowed to call thread-unsafe methods (like Progress.Exists) after the
  637. // kApplicationTerminating bit has been set. And because the domain is unloaded
  638. // (thus triggering AppDomain.DomainUnload) *after* that bit is set, we can't call Progress.Exists
  639. // during shutdown. So we check _isQuitting here. When quitting, it's fine for the progress item
  640. // not to be removed since it's all being torn down anyway.
  641. if (!_isQuitting && Progress.Exists(BurstProgressId))
  642. {
  643. Progress.Remove(BurstProgressId);
  644. BurstProgressId = -1;
  645. }
  646. }
  647. }
  648. internal class BclConfiguration
  649. {
  650. public string FolderPath { get; set; }
  651. public string ExecutablePath { get; set; }
  652. public bool IsExecutableNative { get; set; }
  653. }
  654. }
  655. #endif