暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

BurstAotSettings.cs 32KB

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