private static string GetDisassembly(MethodInfo method, string options)
        {
            try
            {
                var result = BurstCompilerService.GetDisassembly(method, options);
                if (result.IndexOf('\t') >= 0)
                {
                    result = result.Replace("\t", "        ");
                }

                // Workaround to remove timings
                if (result.Contains("Burst timings"))
                {
                    var index = result.IndexOf("While compiling", StringComparison.Ordinal);
                    if (index > 0)
                    {
                        result = result.Substring(index);
                    }
                }

                return(result);
            }
            catch (Exception e)
            {
                return("Failed to compile:\n" + e.Message);
            }
        }
Exemple #2
0
            public static unsafe void *GetOrCreateSharedStaticInternal(long getHashCode64, long getSubHashCode64, uint sizeOf, uint alignment)
            {
                CheckSizeOf(sizeOf);
                var hash128 = new Hash128((ulong)getHashCode64, (ulong)getSubHashCode64);
                var result  = BurstCompilerService.GetOrCreateSharedMemory(ref hash128, sizeOf, alignment == 0 ? 4 : alignment);

                CheckResult(result);
                return(result);
            }
 private static string GetDisassembly(MethodInfo method, string options)
 {
     try
     {
         var result = BurstCompilerService.GetDisassembly(method, options);
         return(TabsToSpaces(result));
     }
     catch (Exception e)
     {
         return("Failed to compile:\n" + e.Message);
     }
 }
Exemple #4
0
        static BurstLoader()
        {
            // Un-comment the following to log compilation steps to log.txt in the .Runtime folder
            // Environment.SetEnvironmentVariable("UNITY_BURST_DEBUG", "1");

            // Try to load the runtime through an environment variable
            RuntimePath = Environment.GetEnvironmentVariable("UNITY_BURST_RUNTIME_PATH");

            // Otherwise try to load it from the package itself
            if (!Directory.Exists(RuntimePath))
            {
                RuntimePath = Path.GetFullPath("Packages/com.unity.burst/.Runtime");
            }
            BurstCompilerService.Initialize(RuntimePath, BurstReflection.ExtractBurstCompilerOptions);
        }
        static BurstLoader()
        {
            // This can be setup to get more diagnostics
            var debuggingStr = Environment.GetEnvironmentVariable("UNITY_BURST_DEBUG");

            IsDebugging = debuggingStr != null;
            if (IsDebugging)
            {
                UnityEngine.Debug.LogWarning("[com.unity.burst] Extra debugging is turned on.");
                int debuggingLevel;
                int.TryParse(debuggingStr, out debuggingLevel);
                if (debuggingLevel <= 0)
                {
                    debuggingLevel = 1;
                }
                DebuggingLevel = debuggingLevel;
            }

            // Try to load the runtime through an environment variable
            RuntimePath = Environment.GetEnvironmentVariable("UNITY_BURST_RUNTIME_PATH");

            // Otherwise try to load it from the package itself
            if (!Directory.Exists(RuntimePath))
            {
                RuntimePath = Path.GetFullPath("Packages/com.unity.burst/.Runtime");
            }

            if (IsDebugging)
            {
                UnityEngine.Debug.LogWarning($"[com.unity.burst] Runtime directory set to {RuntimePath}");
            }

            BurstEditorOptions.EnsureSynchronized();

            if (DebuggingLevel > 2)
            {
                UnityEngine.Debug.Log("Burst - Domain Reload");
            }

            BurstCompilerService.Initialize(RuntimePath, TryGetOptionsFromMember);

            EditorApplication.quitting += BurstCompiler.Shutdown;

            CompilationPipeline.assemblyCompilationStarted  += OnAssemblyCompilationStarted;
            CompilationPipeline.assemblyCompilationFinished += OnAssemblyCompilationFinished;
            EditorApplication.playModeStateChanged          += EditorApplicationOnPlayModeStateChanged;
        }
        static BurstLoader()
        {
            // This can be setup to get more diagnostics
            IsDebugging = Environment.GetEnvironmentVariable("UNITY_BURST_DEBUG") != null;

            // Try to load the runtime through an environment variable
            RuntimePath = Environment.GetEnvironmentVariable("UNITY_BURST_RUNTIME_PATH");

            // Otherwise try to load it from the package itself
            if (!Directory.Exists(RuntimePath))
            {
                RuntimePath = Path.GetFullPath("Packages/com.unity.burst/.Runtime");
            }

            BurstEditorOptions.EnsureSynchronized();

            BurstCompilerService.Initialize(RuntimePath, TryGetOptionsFromMember);

            EditorApplication.quitting += BurstCompiler.Shutdown;
        }
Exemple #7
0
        private static void ScheduleEagerCompilation()
        {
            lock (EagerCompilationLockObject)
            {
                if (EagerCompilationTokenSource.IsCancellationRequested)
                {
                    return;
                }

                if (_cachedCompileTargets == null)
                {
                    throw new InvalidOperationException();
                }

                if (DebuggingLevel > 2)
                {
                    UnityEngine.Debug.Log($"Burst - Starting scheduling eager-compilation");
                }

                var methodsToCompile = new List <EagerCompilationRequest>();
                foreach (var compileTarget in _cachedCompileTargets)
                {
                    var member = compileTarget.IsStaticMethod
                        ? (MemberInfo)compileTarget.Method
                        : compileTarget.JobType;

                    if (compileTarget.Options.TryGetOptions(member, true, out var optionsString, isForEagerCompilation: true))
                    {
                        var encodedMethod = BurstCompilerService.GetMethodSignature(compileTarget.Method);
                        methodsToCompile.Add(new EagerCompilationRequest(encodedMethod, optionsString));
                    }
                }

                BurstCompiler.EagerCompileMethods(methodsToCompile);

                if (DebuggingLevel > 2)
                {
                    UnityEngine.Debug.Log($"Burst - Finished scheduling eager-compilation of {methodsToCompile.Count} methods");
                }
            }
        }
        private void OnPostBuildPlayerScriptDLLsImpl(BuildReport report)
        {
            BurstPlatformAotSettings aotSettingsForTarget = BurstPlatformAotSettings.GetOrCreateSettings(report.summary.platform);

            // Early exit if burst is not activated or the platform is not supported
            if (aotSettingsForTarget.DisableBurstCompilation || !IsSupportedPlatform(report.summary.platform))
            {
                return;
            }

            // Collect all method signatures
            var methodsToCompile = BurstReflection.FindExecuteMethods(AssembliesType.Player);

            if (methodsToCompile.Count == 0)
            {
                return; // Nothing to do
            }

            // Prepare options

            // We are grouping methods per their compiler options (float precision...etc)
            var methodGroups = new Dictionary <string, List <string> >();

            for (var i = 0; i < methodsToCompile.Count; i++)
            {
                var burstCompileTarget = methodsToCompile[i];
                if (!burstCompileTarget.IsSupported)
                {
                    continue;
                }

                var methodStr           = BurstCompilerService.GetMethodSignature(burstCompileTarget.Method);
                var methodFullSignature = methodStr + "--" + Hash128.Compute(methodStr);

                if (aotSettingsForTarget.DisableOptimisations)
                {
                    burstCompileTarget.Options.DisableOptimizations = true;
                }

                burstCompileTarget.Options.EnableBurstSafetyChecks = !aotSettingsForTarget.DisableSafetyChecks;

                string optionsAsStr;
                if (burstCompileTarget.TryGetOptionsAsString(false, out optionsAsStr))
                {
                    List <string> methodOptions;
                    if (!methodGroups.TryGetValue(optionsAsStr, out methodOptions))
                    {
                        methodOptions = new List <string>();
                        methodGroups.Add(optionsAsStr, methodOptions);
                    }
                    methodOptions.Add(GetOption(OptionAotMethod, methodFullSignature));
                }
            }

            var methodGroupOptions = new List <string>();

            // We should have something like this in the end:
            //
            // --group                1st group of method with the following shared options
            // --float-mode=xxx
            // --method=...
            // --method=...
            //
            // --group                2nd group of methods with the different shared options
            // --float-mode=yyy
            // --method=...
            // --method=...
            if (methodGroups.Count == 1)
            {
                var methodGroup = methodGroups.FirstOrDefault();
                // No need to create a group if we don't have multiple
                methodGroupOptions.Add(methodGroup.Key);
                foreach (var methodOption in methodGroup.Value)
                {
                    methodGroupOptions.Add(methodOption);
                }
            }
            else
            {
                foreach (var methodGroup in methodGroups)
                {
                    methodGroupOptions.Add(GetOption(OptionGroup));
                    methodGroupOptions.Add(methodGroup.Key);
                    foreach (var methodOption in methodGroup.Value)
                    {
                        methodGroupOptions.Add(methodOption);
                    }
                }
            }

            var commonOptions  = new List <string>();
            var targetCpu      = TargetCpu.Auto;
            var targetPlatform = GetTargetPlatformAndDefaultCpu(report.summary.platform, out targetCpu);

            commonOptions.Add(GetOption(OptionPlatform, targetPlatform));

            // TODO: Add support for configuring the optimizations/CPU
            // TODO: Add support for per method options

            var stagingFolder = Path.GetFullPath(TempStagingManaged);
            //Debug.Log($"Burst CompileAot - To Folder {stagingFolder}");

            // Prepare assembly folder list
            var assemblyFolders = new List <string>();

            assemblyFolders.Add(stagingFolder);

            var playerAssemblies = CompilationPipeline.GetAssemblies(AssembliesType.Player);

            foreach (var assembly in playerAssemblies)
            {
                foreach (var assemblyRef in assembly.compiledAssemblyReferences)
                {
                    // Exclude folders with assemblies already compiled in the `folder`
                    var assemblyName = Path.GetFileName(assemblyRef);
                    if (assemblyName != null && File.Exists(Path.Combine(stagingFolder, assemblyName)))
                    {
                        continue;
                    }

                    var directory = Path.GetDirectoryName(assemblyRef);
                    if (directory != null)
                    {
                        var fullPath = Path.GetFullPath(directory);
                        if (IsMonoReferenceAssemblyDirectory(fullPath) || IsDotNetStandardAssemblyDirectory(fullPath))
                        {
                            // Don't pass reference assemblies to burst because they contain methods without implementation
                            // If burst accidentally resolves them, it will emit calls to burst_abort.
                            fullPath = Path.Combine(EditorApplication.applicationContentsPath, "MonoBleedingEdge/lib/mono/unityaot");
                            fullPath = Path.GetFullPath(fullPath); // GetFullPath will normalize path separators to OS native format
                            if (!assemblyFolders.Contains(fullPath))
                            {
                                assemblyFolders.Add(fullPath);
                            }

                            fullPath = Path.Combine(fullPath, "Facades");
                            if (!assemblyFolders.Contains(fullPath))
                            {
                                assemblyFolders.Add(fullPath);
                            }
                        }
                        else if (!assemblyFolders.Contains(fullPath))
                        {
                            assemblyFolders.Add(fullPath);
                        }
                    }
                }
            }

            commonOptions.AddRange(assemblyFolders.Select(folder => GetOption(OptionAotAssemblyFolder, folder)));

            var combinations = new List <BurstOutputCombination>();

            if (targetPlatform == TargetPlatform.macOS)
            {
                // NOTE: OSX has a special folder for the plugin
                // Declared in GetStagingAreaPluginsFolder
                // PlatformDependent\OSXPlayer\Extensions\Managed\OSXDesktopStandalonePostProcessor.cs
                combinations.Add(new BurstOutputCombination("UnityPlayer.app/Contents/Plugins", targetCpu));
            }
            else if (targetPlatform == TargetPlatform.iOS)
            {
                if (Application.platform != RuntimePlatform.OSXEditor)
                {
                    Debug.LogWarning("Burst Cross Compilation to iOS for standalone player, is only supported on OSX Editor at this time, burst is disabled for this build.");
                }
                else
                {
                    var targetArchitecture = (IOSArchitecture)UnityEditor.PlayerSettings.GetArchitecture(report.summary.platformGroup);
                    if (targetArchitecture == IOSArchitecture.ARMv7 || targetArchitecture == IOSArchitecture.Universal)
                    {
                        // PlatformDependent\iPhonePlayer\Extensions\Common\BuildPostProcessor.cs
                        combinations.Add(new BurstOutputCombination("StaticLibraries", TargetCpu.ARMV7A_NEON32, DefaultLibraryName + "32"));
                    }
                    if (targetArchitecture == IOSArchitecture.ARM64 || targetArchitecture == IOSArchitecture.Universal)
                    {
                        // PlatformDependent\iPhonePlayer\Extensions\Common\BuildPostProcessor.cs
                        combinations.Add(new BurstOutputCombination("StaticLibraries", TargetCpu.ARMV8A_AARCH64, DefaultLibraryName + "64"));
                    }
                }
            }
            else if (targetPlatform == TargetPlatform.Android)
            {
                //TODO: would be better to query AndroidNdkRoot (but thats not exposed from unity)
                string ndkRoot = null;

                // 2019.1 now has an embedded ndk
#if UNITY_2019_1_OR_NEWER
                if (EditorPrefs.HasKey("NdkUseEmbedded"))
                {
                    if (EditorPrefs.GetBool("NdkUseEmbedded"))
                    {
                        ndkRoot = Path.Combine(BuildPipeline.GetPlaybackEngineDirectory(BuildTarget.Android, BuildOptions.None), "NDK");
                    }
                    else
                    {
                        ndkRoot = EditorPrefs.GetString("AndroidNdkRootR16b");
                    }
                }
#endif

                // If we still don't have a valid root, try the old key
                if (string.IsNullOrEmpty(ndkRoot))
                {
                    ndkRoot = EditorPrefs.GetString("AndroidNdkRoot");
                }


                // Verify the directory at least exists, if not we fall back to ANDROID_NDK_ROOT current setting
                if (!string.IsNullOrEmpty(ndkRoot) && !Directory.Exists(ndkRoot))
                {
                    ndkRoot = null;
                }

                // Always set the ANDROID_NDK_ROOT (if we got a valid result from above), so BCL knows where to find the Android toolchain and its the one the user expects
                if (!string.IsNullOrEmpty(ndkRoot))
                {
                    Environment.SetEnvironmentVariable("ANDROID_NDK_ROOT", ndkRoot);
                }

                var androidTargetArch = UnityEditor.PlayerSettings.Android.targetArchitectures;
                if ((androidTargetArch & AndroidArchitecture.ARMv7) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/armeabi-v7a", TargetCpu.ARMV7A_NEON32));
                }
                if ((androidTargetArch & AndroidArchitecture.ARM64) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/arm64-v8a", TargetCpu.ARMV8A_AARCH64));
                }
                if ((androidTargetArch & AndroidArchitecture.X86) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/x86", TargetCpu.X86_SSE2));
                }
            }
            else if (targetPlatform == TargetPlatform.UWP)
            {
                // TODO: Make it configurable for x86 (sse2, sse4)
                combinations.Add(new BurstOutputCombination("Plugins/x64", TargetCpu.X64_SSE4));
                combinations.Add(new BurstOutputCombination("Plugins/x86", TargetCpu.X86_SSE2));
                combinations.Add(new BurstOutputCombination("Plugins/ARM", TargetCpu.THUMB2_NEON32));
                combinations.Add(new BurstOutputCombination("Plugins/ARM64", TargetCpu.ARMV8A_AARCH64));
            }
            else
            {
                combinations.Add(new BurstOutputCombination("Data/Plugins/", targetCpu));
            }

            foreach (var combination in combinations)
            {
                // Gets the output folder
                var stagingOutputFolder = Path.GetFullPath(Path.Combine(TempStaging, combination.OutputPath));
                var outputFilePrefix    = Path.Combine(stagingOutputFolder, combination.LibraryName);

                var options = new List <string>(commonOptions);
                options.Add(GetOption(OptionAotOutputPath, outputFilePrefix));
                options.Add(GetOption(OptionTarget, combination.TargetCpu));

                if (targetPlatform == TargetPlatform.iOS)
                {
                    options.Add(GetOption(OptionStaticLinkage));
                }

                // finally add method group options
                options.AddRange(methodGroupOptions);

                var responseFile = Path.GetTempFileName();
                File.WriteAllLines(responseFile, options);

                //Debug.Log("Burst compile with response file: " + responseFile);

                try
                {
                    string generatedDebugInformationInOutput = "";
                    if ((report.summary.options & BuildOptions.Development) != 0)
                    {
                        // Workaround for apple clang development issue (due to latest being 7.0.0) - IOS is only affected because its a source level IR compatability issue
                        if (targetPlatform != TargetPlatform.iOS)
                        {
                            generatedDebugInformationInOutput = GetOption(OptionDebug);
                        }
                    }

                    BclRunner.RunManagedProgram(Path.Combine(BurstLoader.RuntimePath, BurstAotCompilerExecutable),
                                                $"{generatedDebugInformationInOutput} @{responseFile}",
                                                new BclOutputErrorParser(),
                                                report);
                }
                catch (Exception e)
                {
                    // We don't expect any error, but in case we have one, we identify that it is burst and we print the details here
                    Debug.LogError("Unexpected error while running the burst compiler: " + e);
                }
            }
        }
        public void OnPostBuildPlayerScriptDLLs(BuildReport report)
        {
            BurstPlatformAotSettings aotSettingsForTarget = BurstPlatformAotSettings.GetOrCreateSettings(report.summary.platform);

            // Early exit if burst is not activated or the platform is not supported
            if (aotSettingsForTarget.DisableBurstCompilation || !IsSupportedPlatform(report.summary.platform))
            {
                return;
            }

            // Collect all method signatures
            var methodsToCompile = BurstReflection.FindExecuteMethods(AssembliesType.Player);

            if (methodsToCompile.Count == 0)
            {
                return; // Nothing to do
            }

            // Prepare options
            var commonOptions = new List <string>();

            for (var i = 0; i < methodsToCompile.Count; i++)
            {
                var burstCompileTarget = methodsToCompile[i];
                if (!burstCompileTarget.SupportsBurst)
                {
                    continue;
                }

                var methodStr           = BurstCompilerService.GetMethodSignature(burstCompileTarget.Method);
                var methodFullSignature = methodStr + "--" + Hash128.Compute(methodStr);
                commonOptions.Add(GetOption(OptionAotMethod, methodFullSignature));
            }

            var targetCpu      = TargetCpu.Auto;
            var targetPlatform = GetTargetPlatformAndDefaultCpu(report.summary.platform, out targetCpu);

            commonOptions.Add(GetOption(OptionPlatform, targetPlatform));

            if (!BurstEditorOptions.EnableBurstSafetyChecks)
            {
                commonOptions.Add(GetOption(OptionDisableSafetyChecks));
            }

            // TODO: Add support for configuring the optimizations/CPU
            // TODO: Add support for per method options

            var stagingFolder = Path.GetFullPath(TempStagingManaged);
            //Debug.Log($"Burst CompileAot - To Folder {stagingFolder}");

            // Prepare assembly folder list
            var assemblyFolders = new List <string>();

            assemblyFolders.Add(stagingFolder);

            var playerAssemblies = CompilationPipeline.GetAssemblies(AssembliesType.Player);

            foreach (var assembly in playerAssemblies)
            {
                foreach (var assemblyRef in assembly.compiledAssemblyReferences)
                {
                    // Exclude folders with assemblies already compiled in the `folder`
                    var assemblyName = Path.GetFileName(assemblyRef);
                    if (assemblyName != null && File.Exists(Path.Combine(stagingFolder, assemblyName)))
                    {
                        continue;
                    }

                    var directory = Path.GetDirectoryName(assemblyRef);
                    if (directory != null)
                    {
                        var fullPath = Path.GetFullPath(directory);
                        if (IsMonoReferenceAssemblyDirectory(fullPath) || IsDotNetStandardAssemblyDirectory(fullPath))
                        {
                            // Don't pass reference assemblies to burst because they contain methods without implementation
                            // If burst accidentally resolves them, it will emit calls to burst_abort.
                            fullPath = Path.Combine(EditorApplication.applicationContentsPath, "MonoBleedingEdge/lib/mono/unityaot");
                            fullPath = Path.GetFullPath(fullPath); // GetFullPath will normalize path separators to OS native format
                            if (!assemblyFolders.Contains(fullPath))
                            {
                                assemblyFolders.Add(fullPath);
                            }

                            fullPath = Path.Combine(fullPath, "Facades");
                            if (!assemblyFolders.Contains(fullPath))
                            {
                                assemblyFolders.Add(fullPath);
                            }
                        }
                        else if (!assemblyFolders.Contains(fullPath))
                        {
                            assemblyFolders.Add(fullPath);
                        }
                    }
                }
            }

            commonOptions.AddRange(assemblyFolders.Select(folder => GetOption(OptionAotAssemblyFolder, folder)));

            // Gets platform specific IL2CPP plugin folder
            // Only the following platforms are providing a dedicated Tools directory
            switch (report.summary.platform)
            {
            case BuildTarget.XboxOne:
            case BuildTarget.PS4:
            case BuildTarget.Android:
            case BuildTarget.iOS:
                var pluginFolder = BuildPipeline.GetBuildToolsDirectory(report.summary.platform);
                commonOptions.Add(GetOption(OptionAotIL2CPPPluginFolder, pluginFolder));
                break;
            }

            var combinations = new List <BurstOutputCombination>();

            if (targetPlatform == TargetPlatform.macOS)
            {
                // NOTE: OSX has a special folder for the plugin
                // Declared in GetStagingAreaPluginsFolder
                // PlatformDependent\OSXPlayer\Extensions\Managed\OSXDesktopStandalonePostProcessor.cs
                combinations.Add(new BurstOutputCombination("UnityPlayer.app/Contents/Plugins", targetCpu));
            }
            else if (targetPlatform == TargetPlatform.iOS)
            {
                // Check if we are under il2cpp as we may have to force a CPU backend for it
                // TODO: Should use report.summary.platformGroup instead?
                bool isUsingIL2CPP = PlayerSettings.GetScriptingBackend(BuildTargetGroup.Standalone) == ScriptingImplementation.IL2CPP;

                if (!isUsingIL2CPP)
                {
                    var targetArchitecture = (IOSArchitecture)UnityEditor.PlayerSettings.GetArchitecture(report.summary.platformGroup);
                    switch (targetArchitecture)
                    {
                    case IOSArchitecture.ARMv7:
                        targetCpu = TargetCpu.ARMV7A_NEON32;
                        break;

                    case IOSArchitecture.ARM64:
                        targetCpu = TargetCpu.ARMV8A_AARCH64;
                        break;

                    case IOSArchitecture.Universal:
                        // TODO: How do we proceed here?
                        targetCpu = TargetCpu.ARMV7A_NEON32;
                        break;
                    }
                }

                // PlatformDependent\iPhonePlayer\Extensions\Common\BuildPostProcessor.cs
                combinations.Add(new BurstOutputCombination("Frameworks", targetCpu));
            }
            else if (targetPlatform == TargetPlatform.Android)
            {
                // Set the ANDROID_NDK_ROOT so IL2CPP knows where to find the Android toolchain
                if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ANDROID_NDK_ROOT")))
                {
                    var ndkRoot = EditorPrefs.GetString("AndroidNdkRoot");
                    if (!string.IsNullOrEmpty(ndkRoot))
                    {
                        Environment.SetEnvironmentVariable("ANDROID_NDK_ROOT", ndkRoot);
                    }
                }

                var androidTargetArch = UnityEditor.PlayerSettings.Android.targetArchitectures;
                if ((androidTargetArch & AndroidArchitecture.ARMv7) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/armeabi-v7a", TargetCpu.ARMV7A_NEON32));
                }
                if ((androidTargetArch & AndroidArchitecture.ARM64) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/arm64-v8a", TargetCpu.ARMV8A_AARCH64));
                }
                if ((androidTargetArch & AndroidArchitecture.X86) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/x86", TargetCpu.X86_SSE2));
                }
            }
            else if (targetPlatform == TargetPlatform.UWP)
            {
                // TODO: Make it configurable for x86 (sse2, sse4)
                combinations.Add(new BurstOutputCombination("Plugins/x64", TargetCpu.X64_SSE4));
                combinations.Add(new BurstOutputCombination("Plugins/x86", TargetCpu.X86_SSE2));
                combinations.Add(new BurstOutputCombination("Plugins/ARM", TargetCpu.THUMB2_NEON32));
                combinations.Add(new BurstOutputCombination("Plugins/ARM64", TargetCpu.ARMV8A_AARCH64));
            }
            else
            {
                combinations.Add(new BurstOutputCombination("Data/Plugins/", targetCpu));
            }

            foreach (var combination in combinations)
            {
                // Gets the output folder
                var stagingOutputFolder = Path.GetFullPath(Path.Combine(TempStaging, combination.OutputPath));
                var outputFilePrefix    = Path.Combine(stagingOutputFolder, DefaultLibraryName);

                var options = new List <string>(commonOptions);
                options.Add(GetOption(OptionAotOutputPath, outputFilePrefix));
                options.Add(GetOption(OptionTarget, combination.TargetCpu));

                if (aotSettingsForTarget.DisableOptimisations)
                {
                    options.Add(GetOption(OptionDisableOpt));
                }
                if (aotSettingsForTarget.DisableSafetyChecks)
                {
                    options.Add(GetOption(OptionDisableSafetyChecks));
                }
                else
                {
                    options.Add(GetOption(OptionSafetyChecks));
                }

                var responseFile = Path.GetTempFileName();
                File.WriteAllLines(responseFile, options);

                //Debug.Log("Burst compile with response file: " + responseFile);

                try
                {
                    Runner.RunManagedProgram(Path.Combine(BurstLoader.RuntimePath, BurstAotCompilerExecutable), "--debug=true " + "@" + responseFile, Application.dataPath + "/..", new BclParser(), null);
                }
                catch (Exception e)
                {
                    Debug.LogError(e.ToString());
                }
            }
        }
Exemple #10
0
        static BurstLoader()
        {
            if (BurstCompilerOptions.ForceDisableBurstCompilation)
            {
                UnityEngine.Debug.LogWarning("[com.unity.burst] Burst is disabled entirely from the command line");
                return;
            }

            // This can be setup to get more diagnostics
            var debuggingStr = Environment.GetEnvironmentVariable("UNITY_BURST_DEBUG");

            IsDebugging = debuggingStr != null;
            if (IsDebugging)
            {
                UnityEngine.Debug.LogWarning("[com.unity.burst] Extra debugging is turned on.");
                int debuggingLevel;
                int.TryParse(debuggingStr, out debuggingLevel);
                if (debuggingLevel <= 0)
                {
                    debuggingLevel = 1;
                }
                DebuggingLevel = debuggingLevel;
            }

            // Try to load the runtime through an environment variable
            RuntimePath = Environment.GetEnvironmentVariable("UNITY_BURST_RUNTIME_PATH");

            // Otherwise try to load it from the package itself
            if (!Directory.Exists(RuntimePath))
            {
                RuntimePath = Path.GetFullPath("Packages/com.unity.burst/.Runtime");
            }

            if (IsDebugging)
            {
                UnityEngine.Debug.LogWarning($"[com.unity.burst] Runtime directory set to {RuntimePath}");
            }

            BurstEditorOptions.EnsureSynchronized();

            BurstCompilerService.Initialize(RuntimePath, TryGetOptionsFromMemberDelegate);

            EditorApplication.quitting += BurstCompiler.Shutdown;

            CompilationPipeline.assemblyCompilationStarted  += OnAssemblyCompilationStarted;
            CompilationPipeline.assemblyCompilationFinished += OnAssemblyCompilationFinished;
            EditorApplication.playModeStateChanged          += EditorApplicationOnPlayModeStateChanged;

            VersionUpdateCheck();

            // Workaround to update the list of assembly folders as soon as possible
            // in order for the JitCompilerService to not fail with AssemblyResolveExceptions.
            try
            {
                var assemblyList    = BurstReflection.GetAssemblyList(AssembliesType.Editor);
                var assemblyFolders = new HashSet <string>();
                foreach (var assembly in assemblyList)
                {
                    try
                    {
                        var fullPath       = Path.GetFullPath(assembly.Location);
                        var assemblyFolder = Path.GetDirectoryName(fullPath);
                        if (!string.IsNullOrEmpty(assemblyFolder))
                        {
                            assemblyFolders.Add(assemblyFolder);
                        }
                    }
                    catch
                    {
                        // ignore
                    }
                }

                // Notify the compiler
                var assemblyFolderList = assemblyFolders.ToList();
                if (IsDebugging)
                {
                    UnityEngine.Debug.Log($"Burst - Change of list of assembly folders:\n{string.Join("\n", assemblyFolderList)}");
                }
                BurstCompiler.UpdateAssemblerFolders(assemblyFolderList);
            }
            catch
            {
                // ignore
            }

            // Notify the compiler about a domain reload
            if (IsDebugging)
            {
                UnityEngine.Debug.Log("Burst - Domain Reload");
            }

            // Notify the JitCompilerService about a domain reload
            BurstCompiler.DomainReload();

            // Make sure that the X86 CSR function pointers are compiled
            Intrinsics.X86.CompileManagedCsrAccessors();

            // Make sure BurstRuntime is initialized
            BurstRuntime.Initialize();
        }
        public void OnPostBuildPlayerScriptDLLs(BuildReport report)
        {
            BurstPlatformAotSettings aotSettingsForTarget = BurstPlatformAotSettings.GetOrCreateSettings(report.summary.platform);

            // Early exit if burst is not activated or the platform is not supported
            if (aotSettingsForTarget.DisableBurstCompilation || !IsSupportedPlatform(report.summary.platform))
            {
                return;
            }

            // Collect all method signatures
            var methodsToCompile = BurstReflection.FindExecuteMethods(AssembliesType.Player);

            if (methodsToCompile.Count == 0)
            {
                return; // Nothing to do
            }

            // Prepare options

            // We are grouping methods per their compiler options (float precision...etc)
            var methodGroups = new Dictionary <string, List <string> >();

            for (var i = 0; i < methodsToCompile.Count; i++)
            {
                var burstCompileTarget = methodsToCompile[i];
                if (!burstCompileTarget.IsSupported)
                {
                    continue;
                }

                var methodStr           = BurstCompilerService.GetMethodSignature(burstCompileTarget.Method);
                var methodFullSignature = methodStr + "--" + Hash128.Compute(methodStr);

                if (aotSettingsForTarget.DisableOptimisations)
                {
                    burstCompileTarget.Options.DisableOptimizations = true;
                }

                burstCompileTarget.Options.EnableBurstSafetyChecks = !aotSettingsForTarget.DisableSafetyChecks;

                string optionsAsStr;
                if (burstCompileTarget.TryGetOptionsAsString(false, out optionsAsStr))
                {
                    List <string> methodOptions;
                    if (!methodGroups.TryGetValue(optionsAsStr, out methodOptions))
                    {
                        methodOptions = new List <string>();
                        methodGroups.Add(optionsAsStr, methodOptions);
                    }
                    methodOptions.Add(GetOption(OptionAotMethod, methodFullSignature));
                }
            }

            var methodGroupOptions = new List <string>();

            // We should have something like this in the end:
            //
            // --group                1st group of method with the following shared options
            // --float-mode=xxx
            // --method=...
            // --method=...
            //
            // --group                2nd group of methods with the different shared options
            // --float-mode=yyy
            // --method=...
            // --method=...
            if (methodGroups.Count == 1)
            {
                var methodGroup = methodGroups.FirstOrDefault();
                // No need to create a group if we don't have multiple
                methodGroupOptions.Add(methodGroup.Key);
                foreach (var methodOption in methodGroup.Value)
                {
                    methodGroupOptions.Add(methodOption);
                }
            }
            else
            {
                foreach (var methodGroup in methodGroups)
                {
                    methodGroupOptions.Add(GetOption(OptionGroup));
                    methodGroupOptions.Add(methodGroup.Key);
                    foreach (var methodOption in methodGroup.Value)
                    {
                        methodGroupOptions.Add(methodOption);
                    }
                }
            }

            var commonOptions  = new List <string>();
            var targetCpu      = TargetCpu.Auto;
            var targetPlatform = GetTargetPlatformAndDefaultCpu(report.summary.platform, out targetCpu);

            commonOptions.Add(GetOption(OptionPlatform, targetPlatform));

            // TODO: Add support for configuring the optimizations/CPU
            // TODO: Add support for per method options

            var stagingFolder = Path.GetFullPath(TempStagingManaged);
            //Debug.Log($"Burst CompileAot - To Folder {stagingFolder}");

            // Prepare assembly folder list
            var assemblyFolders = new List <string>();

            assemblyFolders.Add(stagingFolder);

            var playerAssemblies = CompilationPipeline.GetAssemblies(AssembliesType.Player);

            foreach (var assembly in playerAssemblies)
            {
                foreach (var assemblyRef in assembly.compiledAssemblyReferences)
                {
                    // Exclude folders with assemblies already compiled in the `folder`
                    var assemblyName = Path.GetFileName(assemblyRef);
                    if (assemblyName != null && File.Exists(Path.Combine(stagingFolder, assemblyName)))
                    {
                        continue;
                    }

                    var directory = Path.GetDirectoryName(assemblyRef);
                    if (directory != null)
                    {
                        var fullPath = Path.GetFullPath(directory);
                        if (IsMonoReferenceAssemblyDirectory(fullPath) || IsDotNetStandardAssemblyDirectory(fullPath))
                        {
                            // Don't pass reference assemblies to burst because they contain methods without implementation
                            // If burst accidentally resolves them, it will emit calls to burst_abort.
                            fullPath = Path.Combine(EditorApplication.applicationContentsPath, "MonoBleedingEdge/lib/mono/unityaot");
                            fullPath = Path.GetFullPath(fullPath); // GetFullPath will normalize path separators to OS native format
                            if (!assemblyFolders.Contains(fullPath))
                            {
                                assemblyFolders.Add(fullPath);
                            }

                            fullPath = Path.Combine(fullPath, "Facades");
                            if (!assemblyFolders.Contains(fullPath))
                            {
                                assemblyFolders.Add(fullPath);
                            }
                        }
                        else if (!assemblyFolders.Contains(fullPath))
                        {
                            assemblyFolders.Add(fullPath);
                        }
                    }
                }
            }

            commonOptions.AddRange(assemblyFolders.Select(folder => GetOption(OptionAotAssemblyFolder, folder)));

            var combinations = new List <BurstOutputCombination>();

            if (targetPlatform == TargetPlatform.macOS)
            {
                // NOTE: OSX has a special folder for the plugin
                // Declared in GetStagingAreaPluginsFolder
                // PlatformDependent\OSXPlayer\Extensions\Managed\OSXDesktopStandalonePostProcessor.cs
                combinations.Add(new BurstOutputCombination("UnityPlayer.app/Contents/Plugins", targetCpu));
            }
            else if (targetPlatform == TargetPlatform.iOS)
            {
                var targetArchitecture = (IOSArchitecture)UnityEditor.PlayerSettings.GetArchitecture(report.summary.platformGroup);
                if (targetArchitecture == IOSArchitecture.ARMv7 || targetArchitecture == IOSArchitecture.Universal)
                {
                    // PlatformDependent\iPhonePlayer\Extensions\Common\BuildPostProcessor.cs
                    combinations.Add(new BurstOutputCombination("StaticLibraries", TargetCpu.ARMV7A_NEON32, DefaultLibraryName + "32"));
                }
                if (targetArchitecture == IOSArchitecture.ARM64 || targetArchitecture == IOSArchitecture.Universal)
                {
                    // PlatformDependent\iPhonePlayer\Extensions\Common\BuildPostProcessor.cs
                    combinations.Add(new BurstOutputCombination("StaticLibraries", TargetCpu.ARMV8A_AARCH64, DefaultLibraryName + "64"));
                }
            }
            else if (targetPlatform == TargetPlatform.Android)
            {
                // Set the ANDROID_NDK_ROOT so BCL knows where to find the Android toolchain
                if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ANDROID_NDK_ROOT")))
                {
                    var ndkRoot = EditorPrefs.GetString("AndroidNdkRoot");
                    if (!string.IsNullOrEmpty(ndkRoot))
                    {
                        Environment.SetEnvironmentVariable("ANDROID_NDK_ROOT", ndkRoot);
                    }
                }

                var androidTargetArch = UnityEditor.PlayerSettings.Android.targetArchitectures;
                if ((androidTargetArch & AndroidArchitecture.ARMv7) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/armeabi-v7a", TargetCpu.ARMV7A_NEON32));
                }
                if ((androidTargetArch & AndroidArchitecture.ARM64) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/arm64-v8a", TargetCpu.ARMV8A_AARCH64));
                }
                if ((androidTargetArch & AndroidArchitecture.X86) != 0)
                {
                    combinations.Add(new BurstOutputCombination("libs/x86", TargetCpu.X86_SSE2));
                }
            }
            else if (targetPlatform == TargetPlatform.UWP)
            {
                // TODO: Make it configurable for x86 (sse2, sse4)
                combinations.Add(new BurstOutputCombination("Plugins/x64", TargetCpu.X64_SSE4));
                combinations.Add(new BurstOutputCombination("Plugins/x86", TargetCpu.X86_SSE2));
                combinations.Add(new BurstOutputCombination("Plugins/ARM", TargetCpu.THUMB2_NEON32));
                combinations.Add(new BurstOutputCombination("Plugins/ARM64", TargetCpu.ARMV8A_AARCH64));
            }
            else
            {
                combinations.Add(new BurstOutputCombination("Data/Plugins/", targetCpu));
            }

            foreach (var combination in combinations)
            {
                // Gets the output folder
                var stagingOutputFolder = Path.GetFullPath(Path.Combine(TempStaging, combination.OutputPath));
                var outputFilePrefix    = Path.Combine(stagingOutputFolder, combination.LibraryName);

                var options = new List <string>(commonOptions);
                options.Add(GetOption(OptionAotOutputPath, outputFilePrefix));
                options.Add(GetOption(OptionTarget, combination.TargetCpu));

                if (targetPlatform == TargetPlatform.iOS)
                {
                    options.Add(GetOption(OptionStaticLinkage));
                }

                // finally add method group options
                options.AddRange(methodGroupOptions);

                var responseFile = Path.GetTempFileName();
                File.WriteAllLines(responseFile, options);

                //Debug.Log("Burst compile with response file: " + responseFile);

                try
                {
                    Runner.RunManagedProgram(Path.Combine(BurstLoader.RuntimePath, BurstAotCompilerExecutable), "--debug=true " + "@" + responseFile, Application.dataPath + "/..", new BclParser(), null);
                }
                catch (Exception e)
                {
                    Debug.LogError(e.ToString());
                }
            }
        }
Exemple #12
0
        static BurstLoader()
        {
            if (BurstCompilerOptions.ForceDisableBurstCompilation)
            {
                UnityEngine.Debug.LogWarning("[com.unity.burst] Burst is disabled entirely from the command line");
                return;
            }

            // This can be setup to get more diagnostics
            var debuggingStr = Environment.GetEnvironmentVariable("UNITY_BURST_DEBUG");

            IsDebugging = debuggingStr != null;
            if (IsDebugging)
            {
                UnityEngine.Debug.LogWarning("[com.unity.burst] Extra debugging is turned on.");
                int debuggingLevel;
                int.TryParse(debuggingStr, out debuggingLevel);
                if (debuggingLevel <= 0)
                {
                    debuggingLevel = 1;
                }
                DebuggingLevel = debuggingLevel;
            }

            // Try to load the runtime through an environment variable
            if (!UnityBurstRuntimePathOverwritten(out var path))
            {
                // Otherwise try to load it from the package itself
                path = Path.GetFullPath("Packages/com.unity.burst/.Runtime");
            }

            RuntimePath = path;

            if (IsDebugging)
            {
                UnityEngine.Debug.LogWarning($"[com.unity.burst] Runtime directory set to {RuntimePath}");
            }

            BurstCompilerService.Initialize(RuntimePath, TryGetOptionsFromMemberDelegate);

            // It's important that this call comes *after* BurstCompilerService.Initialize,
            // otherwise any calls from within EnsureSynchronized to BurstCompilerService,
            // such as BurstCompiler.Disable(), will silently fail.
            BurstEditorOptions.EnsureSynchronized();

            EditorApplication.quitting += OnEditorApplicationQuitting;

#if UNITY_2019_1_OR_NEWER
            CompilationPipeline.compilationStarted += OnCompilationStarted;
#endif

            CompilationPipeline.assemblyCompilationStarted  += OnAssemblyCompilationStarted;
            CompilationPipeline.assemblyCompilationFinished += OnAssemblyCompilationFinished;
            EditorApplication.playModeStateChanged          += EditorApplicationOnPlayModeStateChanged;
            AppDomain.CurrentDomain.DomainUnload            += OnDomainUnload;

            VersionUpdateCheck();

            BurstReflection.EnsureInitialized();

#if !UNITY_2019_3_OR_NEWER
            // Workaround to update the list of assembly folders as soon as possible
            // in order for the JitCompilerService to not fail with AssemblyResolveExceptions.
            // This workaround is only necessary for editors prior to 2019.3 (i.e. 2018.4),
            // because 2019.3+ include a fix on the Unity side.
            try
            {
                var assemblyList    = BurstReflection.AllEditorAssemblies;
                var assemblyFolders = new HashSet <string>();
                foreach (var assembly in assemblyList)
                {
                    try
                    {
                        var fullPath       = Path.GetFullPath(assembly.Location);
                        var assemblyFolder = Path.GetDirectoryName(fullPath);
                        if (!string.IsNullOrEmpty(assemblyFolder))
                        {
                            assemblyFolders.Add(assemblyFolder);
                        }
                    }
                    catch
                    {
                        // ignore
                    }
                }

                // Notify the compiler
                var assemblyFolderList = assemblyFolders.ToList();
                if (IsDebugging)
                {
                    UnityEngine.Debug.Log($"Burst - Change of list of assembly folders:\n{string.Join("\n", assemblyFolderList)}");
                }
                BurstCompiler.UpdateAssemblerFolders(assemblyFolderList);
            }
            catch
            {
                // ignore
            }
#endif

            // Notify the compiler about a domain reload
            if (IsDebugging)
            {
                UnityEngine.Debug.Log("Burst - Domain Reload");
            }

            // Notify the JitCompilerService about a domain reload
            BurstCompiler.DomainReload();

#if UNITY_2020_1_OR_NEWER
            BurstCompiler.OnProgress += OnProgress;
            BurstCompiler.SetProgressCallback();
#endif

#if !BURST_INTERNAL && !UNITY_DOTSPLAYER
            // Make sure that the X86 CSR function pointers are compiled
            Intrinsics.X86.CompileManagedCsrAccessors();
#endif

            // Make sure BurstRuntime is initialized
            BurstRuntime.Initialize();

            // Schedule upfront compilation of all methods in all assemblies,
            // with the goal of having as many methods as possible Burst-compiled
            // by the time the user enters PlayMode.
            if (!EditorApplication.isPlayingOrWillChangePlaymode)
            {
                MaybeTriggerEagerCompilation();
            }

#if UNITY_2020_1_OR_NEWER
            // Can't call Menu.AddMenuItem immediately, presumably because the menu controller isn't initialized yet.
            EditorApplication.CallDelayed(() => CreateDynamicMenuItems());
#endif
        }
Exemple #13
0
 internal static unsafe void Log(byte *message, int logType, byte *fileName, int lineNumber)
 {
     BurstCompilerService.Log((byte *)0, (BurstCompilerService.BurstLogType)logType, message, fileName, lineNumber);
 }