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