Keine Beschreibung
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

BurstPlatformAotSettings.cs 35KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. #if UNITY_EDITOR
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using System.IO;
  5. using System;
  6. using System.Text;
  7. using System.Text.RegularExpressions;
  8. using UnityEditor;
  9. using UnityEditor.Build;
  10. using UnityEditor.Build.Reporting;
  11. using UnityEngine;
  12. using UnityEngine.UIElements;
  13. namespace Unity.Burst.Editor
  14. {
  15. internal enum DebugDataKind
  16. {
  17. LineOnly,
  18. Full
  19. }
  20. internal enum AvailX86Targets
  21. {
  22. SSE2 = (int)BurstTargetCpu.X86_SSE2,
  23. SSE4 = (int)BurstTargetCpu.X86_SSE4,
  24. }
  25. [Flags]
  26. internal enum BitsetX86Targets
  27. {
  28. SSE2 = 1 << AvailX86Targets.SSE2,
  29. SSE4 = 1 << AvailX86Targets.SSE4,
  30. }
  31. internal enum AvailX64Targets
  32. {
  33. SSE2 = (int)BurstTargetCpu.X64_SSE2,
  34. SSE4 = (int)BurstTargetCpu.X64_SSE4,
  35. AVX = (int)BurstTargetCpu.AVX,
  36. AVX2 = (int)BurstTargetCpu.AVX2,
  37. }
  38. [Flags]
  39. internal enum BitsetX64Targets
  40. {
  41. SSE2 = 1 << AvailX64Targets.SSE2,
  42. SSE4 = 1 << AvailX64Targets.SSE4,
  43. AVX = 1 << AvailX64Targets.AVX,
  44. AVX2 = 1 << AvailX64Targets.AVX2,
  45. }
  46. internal enum AvailArm64Targets
  47. {
  48. ARMV8A = BurstTargetCpu.ARMV8A_AARCH64,
  49. ARMV8A_HALFFP = BurstTargetCpu.ARMV8A_AARCH64_HALFFP,
  50. ARMV9A = BurstTargetCpu.ARMV9A,
  51. }
  52. [Flags]
  53. internal enum BitsetArm64Targets
  54. {
  55. ARMV8A = 1 << AvailArm64Targets.ARMV8A,
  56. ARMV8A_HALFFP = 1 << AvailArm64Targets.ARMV8A_HALFFP,
  57. ARMV9A = 1 << AvailArm64Targets.ARMV9A,
  58. }
  59. [AttributeUsage(AttributeTargets.Field)]
  60. internal class BurstMetadataSettingAttribute : Attribute { }
  61. [AttributeUsage(AttributeTargets.Field)]
  62. internal class BurstCommonSettingAttribute : Attribute {}
  63. class BurstPlatformLegacySettings : ScriptableObject
  64. {
  65. [SerializeField]
  66. internal bool DisableOptimisations;
  67. [SerializeField]
  68. internal bool DisableSafetyChecks;
  69. [SerializeField]
  70. internal bool DisableBurstCompilation;
  71. BurstPlatformLegacySettings(BuildTarget target)
  72. {
  73. DisableSafetyChecks = true;
  74. DisableBurstCompilation = false;
  75. DisableOptimisations = false;
  76. }
  77. }
  78. // To add a setting,
  79. // Add a
  80. // [SerializeField] internal type settingname;
  81. // Add a
  82. // internal static readonly string settingname_DisplayName = "Name of option to be displayed in the editor (and searched for)";
  83. // Add a
  84. // internal static readonly string settingname_ToolTip = "tool tip information to display when hovering mouse
  85. // If the setting should be restricted to e.g. Standalone platform :
  86. //
  87. // Add a
  88. // internal static bool settingname_Display(BuildTarget selectedTarget, string architecture) {}
  89. //
  90. // Add a
  91. // internal static bool settingname_Serialise(BuildTarget selectedTarget) {}
  92. class BurstPlatformAotSettings : ScriptableObject
  93. {
  94. [SerializeField]
  95. [BurstMetadataSetting] // We always need version to be in our saved settings!
  96. internal int Version;
  97. [SerializeField]
  98. internal bool EnableBurstCompilation;
  99. [SerializeField]
  100. internal bool EnableOptimisations;
  101. [SerializeField]
  102. internal bool EnableSafetyChecks;
  103. [SerializeField]
  104. internal bool EnableDebugInAllBuilds;
  105. [SerializeField]
  106. internal DebugDataKind DebugDataKind;
  107. [SerializeField]
  108. internal bool UsePlatformSDKLinker;
  109. [SerializeField]
  110. internal bool EnableArmv9SecurityFeatures;
  111. [SerializeField]
  112. internal AvailX86Targets CpuMinTargetX32;
  113. [SerializeField]
  114. internal AvailX86Targets CpuMaxTargetX32;
  115. [SerializeField]
  116. internal AvailX64Targets CpuMinTargetX64;
  117. [SerializeField]
  118. internal AvailX64Targets CpuMaxTargetX64;
  119. [SerializeField]
  120. internal BitsetX86Targets CpuTargetsX32;
  121. [SerializeField]
  122. internal BitsetX64Targets CpuTargetsX64;
  123. [SerializeField]
  124. internal BitsetArm64Targets CpuTargetsArm64;
  125. [SerializeField]
  126. internal OptimizeFor OptimizeFor;
  127. [SerializeField]
  128. [BurstCommonSetting]
  129. internal string DisabledWarnings;
  130. internal static readonly string EnableDebugInAllBuilds_DisplayName = "Force Debug Information";
  131. internal static readonly string EnableDebugInAllBuilds_ToolTip = "Generates debug information for the Burst-compiled code, irrespective of if Development Mode is ticked. This can be used to generate symbols for release builds for platforms that need it.";
  132. internal static readonly string DebugDataKind_DisplayName = "Debug Information Kind";
  133. internal static readonly string DebugDataKind_ToolTip = "Choose which kind of debug information you want present in builds with debug information enabled.";
  134. internal static readonly string EnableOptimisations_DisplayName = "Enable Optimizations";
  135. internal static readonly string EnableOptimisations_ToolTip = "Enables all optimizations for the currently selected platform.";
  136. internal static readonly string EnableBurstCompilation_DisplayName = "Enable Burst Compilation";
  137. internal static readonly string EnableBurstCompilation_ToolTip = "Enables burst compilation for the selected platform.";
  138. internal static readonly string OptimizeFor_DisplayName = "Optimize For";
  139. internal static readonly string OptimizeFor_ToolTip = "Choose what optimization setting to compile Burst code for.";
  140. internal static readonly string DisabledWarnings_DisplayName = "Disabled Warnings*";
  141. internal static readonly string DisabledWarnings_ToolTip = "Burst warnings to disable (separated by ;).";
  142. internal static readonly string UsePlatformSDKLinker_DisplayName = "Use Platform SDK Linker";
  143. internal static readonly string UsePlatformSDKLinker_ToolTip = "Enabling this option will disable cross compilation support for desktops, and will require platform specific tools for Windows/Linux/Mac - use only if you encounter problems with the burst builtin solution.";
  144. // We do not support this option anymore, so the easiest thing is to just not display it.
  145. internal static bool UsePlatformSDKLinker_Display(BuildTarget selectedTarget, string architecture) => false;
  146. internal static bool UsePlatformSDKLinker_Serialise(BuildTarget selectedTarget) => false;
  147. internal static readonly string CpuTargetsX32_DisplayName = "Target 32Bit CPU Architectures";
  148. internal static readonly string CpuTargetsX32_ToolTip = "Use this to specify the set of target architectures to support for the currently selected platform.";
  149. internal static bool CpuTargetsX32_Display(BuildTarget selectedTarget, string architecture)
  150. {
  151. return (IsStandalone(selectedTarget) || selectedTarget == BuildTarget.WSAPlayer) && Has32BitSupport(selectedTarget);
  152. }
  153. internal static bool CpuTargetsX32_Serialise(BuildTarget selectedTarget)
  154. {
  155. return (IsStandalone(selectedTarget) || selectedTarget == BuildTarget.WSAPlayer) && Has32BitSupportForSerialise(selectedTarget);
  156. }
  157. internal static readonly string CpuTargetsX64_DisplayName = "Target 64Bit CPU Architectures";
  158. internal static readonly string CpuTargetsX64_ToolTip = "Use this to specify the target architectures to support for the currently selected platform.";
  159. internal static bool CpuTargetsX64_Display(BuildTarget selectedTarget, string architecture)
  160. {
  161. return (IsStandalone(selectedTarget) || selectedTarget == BuildTarget.WSAPlayer)
  162. && Has64BitSupport(selectedTarget)
  163. && (selectedTarget != BuildTarget.StandaloneOSX || architecture != "arm64");
  164. }
  165. internal static bool CpuTargetsX64_Serialise(BuildTarget selectedTarget)
  166. {
  167. return IsStandalone(selectedTarget) || selectedTarget == BuildTarget.WSAPlayer;
  168. }
  169. internal static readonly string CpuTargetsArm64_DisplayName = "Target Arm 64Bit CPU Architectures";
  170. internal static readonly string CpuTargetsArm64_ToolTip = "Use this to specify the target architectures to support for the currently selected platform.";
  171. internal static bool CpuTargetsArm64_Display(BuildTarget selectedTarget, string architecture)
  172. {
  173. return selectedTarget == BuildTarget.Android;
  174. }
  175. internal static bool CpuTargetsArm64_Serialise(BuildTarget selectedTarget)
  176. {
  177. return selectedTarget == BuildTarget.Android;
  178. }
  179. internal static bool IsStandalone(BuildTarget target)
  180. {
  181. switch (target)
  182. {
  183. case BuildTarget.StandaloneLinux64:
  184. case BuildTarget.StandaloneWindows:
  185. case BuildTarget.StandaloneWindows64:
  186. case BuildTarget.StandaloneOSX:
  187. return true;
  188. default:
  189. return false;
  190. }
  191. }
  192. BurstPlatformAotSettings(BuildTarget target)
  193. {
  194. InitialiseDefaults();
  195. }
  196. private const int DefaultVersion = 4;
  197. internal void InitialiseDefaults()
  198. {
  199. Version = DefaultVersion;
  200. EnableSafetyChecks = false;
  201. EnableBurstCompilation = true;
  202. EnableOptimisations = true;
  203. EnableDebugInAllBuilds = false;
  204. DebugDataKind = DebugDataKind.Full;
  205. UsePlatformSDKLinker = false; // Only applicable for desktop targets (Windows/Mac/Linux)
  206. CpuMinTargetX32 = 0;
  207. CpuMaxTargetX32 = 0;
  208. CpuMinTargetX64 = 0;
  209. CpuMaxTargetX64 = 0;
  210. CpuTargetsX32 = BitsetX86Targets.SSE2 | BitsetX86Targets.SSE4;
  211. CpuTargetsX64 = BitsetX64Targets.SSE2 | BitsetX64Targets.AVX2;
  212. CpuTargetsArm64 = BitsetArm64Targets.ARMV8A;
  213. DisabledWarnings = "";
  214. OptimizeFor = OptimizeFor.Default;
  215. }
  216. internal static string GetPath(BuildTarget? target)
  217. {
  218. if (target.HasValue)
  219. {
  220. return "ProjectSettings/BurstAotSettings_" + target.ToString() + ".json";
  221. }
  222. else
  223. {
  224. return "ProjectSettings/CommonBurstAotSettings.json";
  225. }
  226. }
  227. internal static BuildTarget? ResolveTarget(BuildTarget? target)
  228. {
  229. if (!target.HasValue)
  230. {
  231. return target;
  232. }
  233. // Treat the 32/64 platforms the same from the point of view of burst settings
  234. // since there is no real way to distinguish from the platforms selector
  235. if (target == BuildTarget.StandaloneWindows64 || target == BuildTarget.StandaloneWindows)
  236. return BuildTarget.StandaloneWindows;
  237. // 32 bit linux support was deprecated
  238. if (target == BuildTarget.StandaloneLinux64)
  239. return BuildTarget.StandaloneLinux64;
  240. return target;
  241. }
  242. private static bool IsOutputPathToBuildFolder(BuildSummary summary) =>
  243. Directory.Exists(summary.outputPath) // Path to either an executable or the specified build folder.
  244. && summary.platform != BuildTarget.StandaloneOSX; // For MacOSX the folder pointed to is the .app folder
  245. // that is contained within the build folder.
  246. private static string FetchBuildFolder(BuildSummary summary)
  247. {
  248. // Trouble is that it differs based on the build target whether summary refers to:
  249. // - A specific executable.
  250. // - The folder being build to.
  251. // No matter what, we want to place the debug information directory inside of this build
  252. // folder.
  253. var outputPath = summary.outputPath;
  254. return IsOutputPathToBuildFolder(summary)
  255. ? outputPath // outputPath = <path-to-build-directory>
  256. : Path.GetDirectoryName(outputPath); // outputPath = <path-to-executable>
  257. }
  258. internal static readonly string BurstMiscPathPostFix = "_BurstDebugInformation_DoNotShip";
  259. internal static string FetchOutputPath(BuildSummary summary, string productName)
  260. {
  261. var burstMiscFolderName = $"{RemoveIllegalPathChars(productName)}{BurstMiscPathPostFix}";
  262. var finalOutputPath = FetchBuildFolder(summary);
  263. return Path.Combine(finalOutputPath, burstMiscFolderName);
  264. }
  265. private static readonly Regex IllegalPathChars = new Regex("[/:\\\\*<>|?\"]");
  266. private static string RemoveIllegalPathChars(string name) => IllegalPathChars.Replace(name, "");
  267. internal static BurstPlatformAotSettings GetOrCreateSettings(BuildTarget? target)
  268. {
  269. target = ResolveTarget(target);
  270. var settings = CreateInstance<BurstPlatformAotSettings>();
  271. settings.InitialiseDefaults();
  272. string path = GetPath(target);
  273. var fileExists = File.Exists(path);
  274. var upgraded = false;
  275. if (fileExists)
  276. {
  277. var json = File.ReadAllText(path);
  278. settings = SerialiseIn(target, json, out upgraded);
  279. }
  280. if (!fileExists || upgraded)
  281. {
  282. // If the settings file didn't previously exist,
  283. // or it did exist but we've just upgraded it to a new version,
  284. // save it to disk now.
  285. settings.Save(target);
  286. }
  287. // Overwrite the settings with any that are common and shared between all settings.
  288. if (target.HasValue)
  289. {
  290. var commonSettings = GetOrCreateSettings(null);
  291. var platformFields = typeof(BurstPlatformAotSettings).GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
  292. foreach (var field in platformFields)
  293. {
  294. if (null != field.GetCustomAttribute<BurstCommonSettingAttribute>())
  295. {
  296. field.SetValue(settings, field.GetValue(commonSettings));
  297. }
  298. }
  299. }
  300. return settings;
  301. }
  302. delegate bool SerialiseItem(BuildTarget selectedPlatform);
  303. private static BurstPlatformAotSettings SerialiseIn(BuildTarget? target, string json, out bool upgraded)
  304. {
  305. var versioned = ScriptableObject.CreateInstance<BurstPlatformAotSettings>();
  306. EditorJsonUtility.FromJsonOverwrite(json, versioned);
  307. upgraded = false;
  308. if (versioned.Version == 0)
  309. {
  310. // Deal with pre versioned format
  311. var legacy = ScriptableObject.CreateInstance<BurstPlatformLegacySettings>();
  312. EditorJsonUtility.FromJsonOverwrite(json, legacy);
  313. // Legacy file, upgrade it
  314. versioned.InitialiseDefaults();
  315. versioned.EnableOptimisations = !legacy.DisableOptimisations;
  316. versioned.EnableBurstCompilation = !legacy.DisableBurstCompilation;
  317. versioned.EnableSafetyChecks = !legacy.DisableSafetyChecks;
  318. // Destroy the legacy object so Unity doesn't try to backup / restore it later during domain reload.
  319. ScriptableObject.DestroyImmediate(legacy);
  320. upgraded = true;
  321. }
  322. if (versioned.Version < 3)
  323. {
  324. // Upgrade the version first
  325. versioned.Version = 3;
  326. // Upgrade from min..max targets to bitset
  327. versioned.CpuTargetsX32 |= (BitsetX86Targets)(1 << (int)versioned.CpuMinTargetX32);
  328. versioned.CpuTargetsX32 |= (BitsetX86Targets)(1 << (int)versioned.CpuMaxTargetX32);
  329. versioned.CpuTargetsX64 |= (BitsetX64Targets)(1 << (int)versioned.CpuMinTargetX64);
  330. versioned.CpuTargetsX64 |= (BitsetX64Targets)(1 << (int)versioned.CpuMaxTargetX64);
  331. // Extra checks to add targets in the min..max range for 64-bit targets.
  332. switch (versioned.CpuMinTargetX64)
  333. {
  334. default:
  335. break;
  336. case AvailX64Targets.SSE2:
  337. switch (versioned.CpuMaxTargetX64)
  338. {
  339. default:
  340. break;
  341. case AvailX64Targets.AVX2:
  342. versioned.CpuTargetsX64 |= (BitsetX64Targets)(1 << (int)AvailX64Targets.AVX);
  343. goto case AvailX64Targets.AVX;
  344. case AvailX64Targets.AVX:
  345. versioned.CpuTargetsX64 |= (BitsetX64Targets)(1 << (int)AvailX64Targets.SSE4);
  346. break;
  347. }
  348. break;
  349. case AvailX64Targets.SSE4:
  350. switch (versioned.CpuMaxTargetX64)
  351. {
  352. default:
  353. break;
  354. case AvailX64Targets.AVX2:
  355. versioned.CpuTargetsX64 |= (BitsetX64Targets)(1 << (int)AvailX64Targets.AVX);
  356. break;
  357. }
  358. break;
  359. }
  360. // Wipe the old min/max targets
  361. versioned.CpuMinTargetX32 = 0;
  362. versioned.CpuMaxTargetX32 = 0;
  363. versioned.CpuMinTargetX64 = 0;
  364. versioned.CpuMaxTargetX64 = 0;
  365. upgraded = true;
  366. }
  367. if (versioned.Version < 4)
  368. {
  369. // Upgrade the version first.
  370. versioned.Version = 4;
  371. // When we upgrade we'll set the optimization level to default (which is, as expected, the default).
  372. versioned.OptimizeFor = OptimizeFor.Default;
  373. // This option has been removed as user-setting options, so switch them to false here.
  374. versioned.EnableSafetyChecks = false;
  375. upgraded = true;
  376. }
  377. // Otherwise should be a modern file with a valid version (we can use that to upgrade when the time comes)
  378. return versioned;
  379. }
  380. private static bool ShouldSerialiseOut(BuildTarget? target, FieldInfo field)
  381. {
  382. var method = typeof(BurstPlatformAotSettings).GetMethod(field.Name + "_Serialise", BindingFlags.Static | BindingFlags.NonPublic);
  383. if (method != null)
  384. {
  385. var shouldSerialise = (SerialiseItem)Delegate.CreateDelegate(typeof(SerialiseItem), method);
  386. if (!target.HasValue || !shouldSerialise(target.Value))
  387. {
  388. return false;
  389. }
  390. }
  391. // If we always need to write out the attribute, return now.
  392. if (null != field.GetCustomAttribute<BurstMetadataSettingAttribute>())
  393. {
  394. return true;
  395. }
  396. var isCommon = !target.HasValue;
  397. var hasCommonAttribute = null != field.GetCustomAttribute<BurstCommonSettingAttribute>();
  398. if ((isCommon && hasCommonAttribute) || (!isCommon && !hasCommonAttribute))
  399. {
  400. return true;
  401. }
  402. return false;
  403. }
  404. internal string SerialiseOut(BuildTarget? target)
  405. {
  406. // Version 2 and onwards serialise a custom object in order to avoid serialising all the settings.
  407. StringBuilder s = new StringBuilder();
  408. s.Append("{\n");
  409. s.Append(" \"MonoBehaviour\": {\n");
  410. var platformFields = typeof(BurstPlatformAotSettings).GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
  411. int total = 0;
  412. for (int i = 0; i < platformFields.Length; i++)
  413. {
  414. if (ShouldSerialiseOut(target, platformFields[i]))
  415. {
  416. total++;
  417. }
  418. }
  419. for (int i = 0; i < platformFields.Length; i++)
  420. {
  421. if (ShouldSerialiseOut(target, platformFields[i]))
  422. {
  423. s.Append($" \"{platformFields[i].Name}\": ");
  424. if (platformFields[i].FieldType.IsEnum)
  425. s.Append((int)platformFields[i].GetValue(this));
  426. else if (platformFields[i].FieldType == typeof(string))
  427. s.Append($"\"{platformFields[i].GetValue(this)}\"");
  428. else if (platformFields[i].FieldType == typeof(bool))
  429. s.Append(((bool)platformFields[i].GetValue(this)) ? "true" : "false");
  430. else
  431. s.Append((int)platformFields[i].GetValue(this));
  432. total--;
  433. if (total != 0)
  434. s.Append(",");
  435. s.Append("\n");
  436. }
  437. }
  438. s.Append(" }\n");
  439. s.Append("}\n");
  440. return s.ToString();
  441. }
  442. internal void Save(BuildTarget? target)
  443. {
  444. if (target.HasValue)
  445. {
  446. target = ResolveTarget(target);
  447. }
  448. var path = GetPath(target);
  449. if (!AssetDatabase.IsOpenForEdit(path))
  450. {
  451. if (!AssetDatabase.MakeEditable(path))
  452. {
  453. Debug.LogWarning($"Burst could not save AOT settings file {path}");
  454. return;
  455. }
  456. }
  457. File.WriteAllText(path, SerialiseOut(target));
  458. }
  459. internal static SerializedObject GetCommonSerializedSettings()
  460. {
  461. return new SerializedObject(GetOrCreateSettings(null));
  462. }
  463. internal static SerializedObject GetSerializedSettings(BuildTarget target)
  464. {
  465. return new SerializedObject(GetOrCreateSettings(target));
  466. }
  467. internal static bool Has32BitSupport(BuildTarget target)
  468. {
  469. switch (target)
  470. {
  471. case BuildTarget.StandaloneWindows:
  472. case BuildTarget.WSAPlayer:
  473. return true;
  474. default:
  475. return false;
  476. }
  477. }
  478. internal static bool Has32BitSupportForSerialise(BuildTarget target)
  479. {
  480. switch (target)
  481. {
  482. case BuildTarget.StandaloneWindows:
  483. case BuildTarget.StandaloneWindows64:
  484. case BuildTarget.WSAPlayer:
  485. return true;
  486. default:
  487. return false;
  488. }
  489. }
  490. internal static bool Has64BitSupport(BuildTarget target)
  491. {
  492. switch (target)
  493. {
  494. case BuildTarget.StandaloneWindows64:
  495. case BuildTarget.WSAPlayer:
  496. case BuildTarget.StandaloneOSX:
  497. return true;
  498. default:
  499. return false;
  500. }
  501. }
  502. private static BurstTargetCpu GetCpu(int v)
  503. {
  504. // https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog
  505. var r = ((v > 0xFFFF) ? 1 : 0) << 4; v >>= r;
  506. var shift = ((v > 0xFF) ? 1 : 0) << 3; v >>= shift; r |= shift;
  507. shift = ((v > 0xF) ? 1 : 0) << 2; v >>= shift; r |= shift;
  508. shift = ((v > 0x3) ? 1 : 0) << 1; v >>= shift; r |= shift;
  509. r |= (v >> 1);
  510. return (BurstTargetCpu)r;
  511. }
  512. private static IEnumerable<Enum> GetFlags(Enum input)
  513. {
  514. foreach (Enum value in Enum.GetValues(input.GetType()))
  515. {
  516. if (input.HasFlag(value))
  517. {
  518. yield return value;
  519. }
  520. }
  521. }
  522. internal TargetCpus GetDesktopCpu32Bit()
  523. {
  524. var cpus = new TargetCpus();
  525. foreach (var target in GetFlags(CpuTargetsX32))
  526. {
  527. cpus.Cpus.Add(GetCpu((int)(BitsetX86Targets)target));
  528. }
  529. // If no targets were specified just default to the oldest CPU supported.
  530. if (cpus.Cpus.Count == 0)
  531. {
  532. cpus.Cpus.Add(BurstTargetCpu.X86_SSE2);
  533. }
  534. return cpus;
  535. }
  536. internal TargetCpus GetDesktopCpu64Bit()
  537. {
  538. var cpus = new TargetCpus();
  539. foreach (var target in GetFlags(CpuTargetsX64))
  540. {
  541. cpus.Cpus.Add(GetCpu((int)(BitsetX64Targets)target));
  542. }
  543. // If no targets were specified just default to the oldest CPU supported.
  544. if (cpus.Cpus.Count == 0)
  545. {
  546. cpus.Cpus.Add(BurstTargetCpu.X64_SSE2);
  547. }
  548. return cpus;
  549. }
  550. internal TargetCpus GetAndroidCpuArm64()
  551. {
  552. var cpus = new TargetCpus();
  553. foreach (var target in GetFlags(CpuTargetsArm64))
  554. {
  555. cpus.Cpus.Add(GetCpu((int)(BitsetArm64Targets)target));
  556. }
  557. // If no targets were specified just default to the oldest CPU supported.
  558. if (cpus.Cpus.Count == 0)
  559. {
  560. cpus.Cpus.Add(BurstTargetCpu.ARMV8A_AARCH64);
  561. }
  562. return cpus;
  563. }
  564. }
  565. static class BurstAotSettingsIMGUIRegister
  566. {
  567. class BurstAotSettingsProvider : SettingsProvider
  568. {
  569. SerializedObject[] m_PlatformSettings;
  570. SerializedProperty[][] m_PlatformProperties;
  571. DisplayItem[][] m_PlatformVisibility;
  572. GUIContent[][] m_PlatformToolTips;
  573. BuildPlatform[] m_ValidPlatforms;
  574. SerializedObject m_CommonPlatformSettings;
  575. delegate bool DisplayItem(BuildTarget selectedTarget, string architecture);
  576. static bool DefaultShow(BuildTarget selectedTarget, string architecture)
  577. {
  578. return true;
  579. }
  580. static bool DefaultHide(BuildTarget selectedTarget, string architecture)
  581. {
  582. return false;
  583. }
  584. public BurstAotSettingsProvider()
  585. : base("Project/Burst AOT Settings", SettingsScope.Project, null)
  586. {
  587. int a;
  588. m_ValidPlatforms = BuildPlatforms.instance.GetValidPlatforms(true).ToArray();
  589. var platformFields = typeof(BurstPlatformAotSettings).GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
  590. int numPlatformFields = platformFields.Length;
  591. int numKeywords = numPlatformFields;
  592. var tempKeywords = new string[numKeywords];
  593. for (a = 0; a < numPlatformFields; a++)
  594. {
  595. tempKeywords[a] = typeof(BurstPlatformAotSettings).GetField(platformFields[a].Name + "_ToolTip", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as string;
  596. }
  597. keywords = new HashSet<string>(tempKeywords);
  598. m_PlatformSettings = new SerializedObject[m_ValidPlatforms.Length];
  599. m_PlatformProperties = new SerializedProperty[m_ValidPlatforms.Length][];
  600. m_PlatformVisibility = new DisplayItem[m_ValidPlatforms.Length][];
  601. m_PlatformToolTips = new GUIContent[m_ValidPlatforms.Length][];
  602. m_CommonPlatformSettings = null;
  603. }
  604. public override void OnActivate(string searchContext, VisualElement rootElement)
  605. {
  606. var platformFields = typeof(BurstPlatformAotSettings).GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
  607. for (int p = 0; p < m_ValidPlatforms.Length; p++)
  608. {
  609. InitialiseSettingsForCommon(platformFields);
  610. InitialiseSettingsForPlatform(p, platformFields);
  611. }
  612. }
  613. private void InitialiseSettingsForCommon(FieldInfo[] commonFields)
  614. {
  615. m_CommonPlatformSettings = BurstPlatformAotSettings.GetCommonSerializedSettings();
  616. }
  617. private void InitialiseSettingsForPlatform(int platform, FieldInfo[] platformFields)
  618. {
  619. if (m_ValidPlatforms[platform].targetGroup == BuildTargetGroup.Standalone)
  620. m_PlatformSettings[platform] = BurstPlatformAotSettings.GetSerializedSettings(EditorUserBuildSettings.selectedStandaloneTarget);
  621. else
  622. m_PlatformSettings[platform] = BurstPlatformAotSettings.GetSerializedSettings(m_ValidPlatforms[platform].defaultTarget);
  623. m_PlatformProperties[platform] = new SerializedProperty[platformFields.Length];
  624. m_PlatformToolTips[platform] = new GUIContent[platformFields.Length];
  625. m_PlatformVisibility[platform] = new DisplayItem[platformFields.Length];
  626. for (int i = 0; i < platformFields.Length; i++)
  627. {
  628. m_PlatformProperties[platform][i] = m_PlatformSettings[platform].FindProperty(platformFields[i].Name);
  629. var displayName = typeof(BurstPlatformAotSettings).GetField(platformFields[i].Name + "_DisplayName", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as string;
  630. var toolTip = typeof(BurstPlatformAotSettings).GetField(platformFields[i].Name + "_ToolTip", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as string;
  631. m_PlatformToolTips[platform][i] = EditorGUIUtility.TrTextContent(displayName, toolTip);
  632. var method = typeof(BurstPlatformAotSettings).GetMethod(platformFields[i].Name + "_Display", BindingFlags.Static | BindingFlags.NonPublic);
  633. if (method == null)
  634. {
  635. if (displayName == null)
  636. {
  637. m_PlatformVisibility[platform][i] = DefaultHide;
  638. }
  639. else
  640. {
  641. m_PlatformVisibility[platform][i] = DefaultShow;
  642. }
  643. }
  644. else
  645. {
  646. m_PlatformVisibility[platform][i] = (DisplayItem)Delegate.CreateDelegate(typeof(DisplayItem), method);
  647. }
  648. }
  649. }
  650. private string FetchStandaloneTargetName()
  651. {
  652. switch (EditorUserBuildSettings.selectedStandaloneTarget)
  653. {
  654. case BuildTarget.StandaloneOSX:
  655. return "Mac OS X"; // Matches the Build Settings Dialog names
  656. case BuildTarget.StandaloneWindows:
  657. case BuildTarget.StandaloneWindows64:
  658. return "Windows";
  659. default:
  660. return "Linux";
  661. }
  662. }
  663. public override void OnGUI(string searchContext)
  664. {
  665. var rect = EditorGUILayout.BeginVertical();
  666. EditorGUIUtility.labelWidth = rect.width / 2;
  667. int selectedPlatform = EditorGUILayout.BeginPlatformGrouping(m_ValidPlatforms, null);
  668. // During a build and other cases, the settings object can become invalid, if it does, we re-build it for the current platform
  669. // this fixes the settings failing to save if modified after a build has finished, and the settings were still open
  670. if (!m_PlatformSettings[selectedPlatform].isValid)
  671. {
  672. var platformFields = typeof(BurstPlatformAotSettings).GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
  673. InitialiseSettingsForCommon(platformFields);
  674. // If the selected platform is invalid, it means all of them will be. So we do a pass to reinitialize all now.
  675. for (var platform = 0; platform < m_PlatformSettings.Length; platform++)
  676. {
  677. InitialiseSettingsForPlatform(platform, platformFields);
  678. }
  679. }
  680. var selectedTarget = m_ValidPlatforms[selectedPlatform].defaultTarget;
  681. if (m_ValidPlatforms[selectedPlatform].targetGroup == BuildTargetGroup.Standalone)
  682. selectedTarget = EditorUserBuildSettings.selectedStandaloneTarget;
  683. var buildTargetName = BuildPipeline.GetBuildTargetName(selectedTarget);
  684. var architecture = EditorUserBuildSettings.GetPlatformSettings(buildTargetName, "Architecture").ToLowerInvariant();
  685. if (m_ValidPlatforms[selectedPlatform].targetGroup == BuildTargetGroup.Standalone)
  686. {
  687. // Note burst treats Windows and Windows32 as the same target from a settings point of view (same for linux)
  688. // So we only display the standalone platform
  689. EditorGUILayout.LabelField(EditorGUIUtility.TrTextContent("Target Platform", "Shows the currently selected standalone build target, can be switched in the Build Settings dialog"), EditorGUIUtility.TrTextContent(FetchStandaloneTargetName()));
  690. }
  691. for (int i = 0; i < m_PlatformProperties[selectedPlatform].Length; i++)
  692. {
  693. if (m_PlatformVisibility[selectedPlatform][i](selectedTarget, architecture))
  694. {
  695. EditorGUILayout.PropertyField(m_PlatformProperties[selectedPlatform][i], m_PlatformToolTips[selectedPlatform][i]);
  696. }
  697. }
  698. if (m_ValidPlatforms[selectedPlatform].targetGroup == BuildTargetGroup.Android)
  699. EditorGUILayout.HelpBox("Armv9A (SVE2) target CPU architecture is experimental", MessageType.Warning);
  700. EditorGUILayout.EndPlatformGrouping();
  701. EditorGUILayout.EndVertical();
  702. EditorGUILayout.LabelField("* Shared setting common across all platforms");
  703. if (m_PlatformSettings[selectedPlatform].hasModifiedProperties)
  704. {
  705. m_PlatformSettings[selectedPlatform].ApplyModifiedPropertiesWithoutUndo();
  706. var commonAotSettings = ((BurstPlatformAotSettings)m_CommonPlatformSettings.targetObject);
  707. var platformAotSettings = ((BurstPlatformAotSettings)m_PlatformSettings[selectedPlatform].targetObject);
  708. var platformFields = typeof(BurstPlatformAotSettings).GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
  709. foreach (var field in platformFields)
  710. {
  711. if (null != field.GetCustomAttribute<BurstCommonSettingAttribute>())
  712. {
  713. field.SetValue(commonAotSettings, field.GetValue(platformAotSettings));
  714. foreach (var platformSetting in m_PlatformSettings)
  715. {
  716. field.SetValue(platformSetting.targetObject, field.GetValue(commonAotSettings));
  717. }
  718. }
  719. }
  720. commonAotSettings.Save(null);
  721. platformAotSettings.Save(selectedTarget);
  722. }
  723. }
  724. }
  725. [SettingsProvider]
  726. public static SettingsProvider CreateBurstAotSettingsProvider()
  727. {
  728. return new BurstAotSettingsProvider();
  729. }
  730. }
  731. }
  732. #endif