暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BurstInspectorGUITests.cs 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using NUnit.Framework;
  6. using Unity.Burst.Editor;
  7. using UnityEditor;
  8. using UnityEngine;
  9. using UnityEngine.TestTools;
  10. using Unity.Collections;
  11. using Unity.Burst;
  12. using Unity.Jobs;
  13. using Unity.Jobs.LowLevel.Unsafe;
  14. [TestFixture]
  15. [UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor)]
  16. public class BurstInspectorGUITests
  17. {
  18. private readonly WaitUntil _waitForInitialized =
  19. new WaitUntil(() => EditorWindow.GetWindow<BurstInspectorGUI>()._initialized);
  20. private IEnumerator SelectJobAwaitLoad(string assemblyName)
  21. {
  22. EditorWindow.GetWindow<BurstInspectorGUI>()._treeView.TrySelectByDisplayName(assemblyName);
  23. return new WaitUntil(() =>
  24. EditorWindow.GetWindow<BurstInspectorGUI>()._textArea.IsTextSet(assemblyName)
  25. );
  26. }
  27. [UnitySetUp]
  28. public IEnumerator SetUp()
  29. {
  30. // Close down window if it's open, to start with a fresh inspector.
  31. EditorWindow.GetWindow<BurstInspectorGUI>().Close();
  32. EditorWindow.GetWindow<BurstInspectorGUI>().Show();
  33. // Make sure window is actually initialized before continuing.
  34. yield return _waitForInitialized;
  35. }
  36. [UnityTest]
  37. public IEnumerator TestInspectorOpenDuringDomainReloadDoesNotLogErrors()
  38. {
  39. // Show Inspector window
  40. EditorWindow.GetWindow<BurstInspectorGUI>().Show();
  41. Assert.IsTrue(EditorWindow.HasOpenInstances<BurstInspectorGUI>());
  42. // Ask for domain reload
  43. EditorUtility.RequestScriptReload();
  44. // Wait for the domain reload to be completed
  45. yield return new WaitForDomainReload();
  46. Assert.IsTrue(EditorWindow.HasOpenInstances<BurstInspectorGUI>());
  47. // Hide Inspector window
  48. EditorWindow.GetWindow<BurstInspectorGUI>().Close();
  49. Assert.IsFalse(EditorWindow.HasOpenInstances<BurstInspectorGUI>());
  50. }
  51. [UnityTest]
  52. public IEnumerator DisassemblerNotChangingUnexpectedlyTest()
  53. {
  54. const string jobName2 = "BurstReflectionTests.MyJob - (IJob)";
  55. const string jobName = "BurstInspectorGUITests.MyJob - (IJob)";
  56. // Selecting a specific assembly.
  57. yield return SelectJobAwaitLoad(jobName);
  58. var window = EditorWindow.GetWindow<BurstInspectorGUI>();
  59. try
  60. {
  61. // Sending event to set the displayname, to avoid it resetting _scrollPos because of target change.
  62. window.SendEvent(new Event()
  63. {
  64. type = EventType.Repaint,
  65. mousePosition = new Vector2(window.position.width / 2f, window.position.height / 2f)
  66. });
  67. yield return null;
  68. // Doing actual test work:
  69. var prev = new BurstDisassemblerWithCopy(window._burstDisassembler);
  70. window.SendEvent(new Event()
  71. {
  72. type = EventType.Repaint,
  73. mousePosition = new Vector2(window.position.width / 2f, window.position.height / 2f)
  74. });
  75. yield return null;
  76. Assert.IsTrue(prev.Equals(window._burstDisassembler),
  77. "Public fields changed in burstDisassembler even though they shouldn't");
  78. prev = new BurstDisassemblerWithCopy(window._burstDisassembler);
  79. window.SendEvent(new Event() { type = EventType.MouseUp, mousePosition = Vector2.zero });
  80. yield return null;
  81. Assert.IsTrue(prev.Equals(window._burstDisassembler),
  82. "Public fields changed in burstDisassembler even though they shouldn't");
  83. prev = new BurstDisassemblerWithCopy(window._burstDisassembler);
  84. yield return SelectJobAwaitLoad(jobName2);
  85. window = EditorWindow.GetWindow<BurstInspectorGUI>();
  86. window.SendEvent(new Event()
  87. {
  88. type = EventType.Repaint,
  89. mousePosition = new Vector2(window.position.width / 2f, window.position.height / 2f)
  90. });
  91. yield return null;
  92. Assert.IsFalse(prev.Equals(window._burstDisassembler), "Public fields of burstDisassembler did not change");
  93. }
  94. finally
  95. {
  96. window.Close();
  97. }
  98. }
  99. [UnityTest]
  100. public IEnumerator InspectorStallingLoadTest()
  101. {
  102. // Error was triggered by selecting a display name, filtering it out, and then doing a script recompilation.
  103. yield return SelectJobAwaitLoad("BurstInspectorGUITests.MyJob - (IJob)");
  104. var win = EditorWindow.GetWindow<BurstInspectorGUI>();
  105. win._searchFieldJobs.SetFocus();
  106. yield return null;
  107. // Simulate event for sending "a" as it will filter out the chosen job.
  108. win.SendEvent(Event.KeyboardEvent("a"));
  109. yield return null;
  110. // Send RequestScriptReload to try and trigger the bug
  111. // and wait for it to return
  112. EditorUtility.RequestScriptReload();
  113. yield return new WaitForDomainReload();
  114. win = EditorWindow.GetWindow<BurstInspectorGUI>();
  115. // Wait for it to actually initialize.
  116. yield return _waitForInitialized;
  117. Assert.IsTrue(win._initialized, "BurstInspector did not initialize properly after script reload");
  118. win.Close();
  119. }
  120. [UnityTest]
  121. public IEnumerator FontStyleDuringDomainReloadTest()
  122. {
  123. // Enter play mod
  124. yield return new EnterPlayMode();
  125. // Exit play mode
  126. yield return new ExitPlayMode();
  127. // Wait for the inspector to actually reload
  128. yield return _waitForInitialized;
  129. var inspectorWindow = EditorWindow.GetWindow<BurstInspectorGUI>();
  130. #if UNITY_2023_1_OR_NEWER
  131. Assert.AreEqual("RobotoMono-Regular", inspectorWindow._font.name);
  132. #else
  133. if (Application.platform == RuntimePlatform.WindowsEditor)
  134. {
  135. Assert.AreEqual("Consolas", inspectorWindow._font.name);
  136. }
  137. else
  138. {
  139. Assert.AreEqual("Courier", inspectorWindow._font.name);
  140. }
  141. #endif
  142. inspectorWindow.Close();
  143. }
  144. [UnityTest]
  145. public IEnumerator BranchHoverTest()
  146. {
  147. const string jobName = "BurstInspectorGUITests.MyJob - (IJob)";
  148. yield return SelectJobAwaitLoad(jobName);
  149. var info = SetupBranchTest();
  150. var window = EditorWindow.GetWindow<BurstInspectorGUI>();
  151. window.SendEvent(new Event() { type = EventType.MouseUp, mousePosition = info.mousePos });
  152. var branch = window._textArea.hoveredBranch;
  153. yield return null;
  154. // Close window to avoid it sending more events
  155. window.Close();
  156. Assert.AreNotEqual(branch, default(LongTextArea.Branch), "Mouse is not hovering any branch.");
  157. Assert.AreEqual(info.blockIdx.src, branch.Edge.OriginRef.BlockIndex);
  158. Assert.AreEqual(info.blockIdx.dst, branch.Edge.LineRef.BlockIndex);
  159. }
  160. [UnityTest]
  161. public IEnumerator ClickBranchTest()
  162. {
  163. const string jobName = "BurstInspectorGUITests.MyJob - (IJob)";
  164. yield return SelectJobAwaitLoad(jobName);
  165. var info = SetupBranchTest();
  166. var window = EditorWindow.GetWindow<BurstInspectorGUI>();
  167. // Seeing if clicking the branch takes us to a spot where branch is still hovered.
  168. window.SendEvent(new Event() { type = EventType.MouseDown, mousePosition = info.mousePos });
  169. var branch = window._textArea.hoveredBranch;
  170. yield return null;
  171. Assert.AreNotEqual(branch, default(LongTextArea.Branch), "Mouse is not hovering any branch.");
  172. Assert.AreEqual(info.blockIdx.src, branch.Edge.OriginRef.BlockIndex);
  173. Assert.AreEqual(info.blockIdx.dst, branch.Edge.LineRef.BlockIndex);
  174. // Going back again.
  175. window.SendEvent(new Event() { type = EventType.MouseDown, mousePosition = info.mousePos });
  176. var branch2 = window._textArea.hoveredBranch;
  177. yield return null;
  178. Assert.AreNotEqual(branch2, default(LongTextArea.Branch), "Mouse is not hovering any branch.");
  179. Assert.AreEqual(info.blockIdx.src, branch2.Edge.OriginRef.BlockIndex);
  180. Assert.AreEqual(info.blockIdx.dst, branch2.Edge.LineRef.BlockIndex);
  181. // Close window to avoid it sending more events.
  182. window.Close();
  183. }
  184. private struct InfoThingy
  185. {
  186. public (int src, int dst) blockIdx;
  187. public Vector2 mousePos;
  188. }
  189. private InfoThingy SetupBranchTest()
  190. {
  191. var window = EditorWindow.GetWindow<BurstInspectorGUI>();
  192. // Make sure we use fontSize 12:
  193. window.fontSizeIndex = 4;
  194. window._textArea.Invalidate();
  195. window.fixedFontStyle = null;
  196. // Force window size to actually show branch arrows.
  197. window.position = new Rect(window.position.x, window.position.y, 390, 405);
  198. // Sending event to set the displayname, to avoid it resetting _scrollPos because of target change.
  199. // Sending two events as initial guess for buttonbar width might be off, and it will be a precise calculation after second event.
  200. window.SendEvent(new Event() { type = EventType.Repaint, mousePosition = new Vector2(window.position.width / 2f, window.position.height / 2f) });
  201. window.SendEvent(new Event() { type = EventType.Repaint, mousePosition = new Vector2(window.position.width / 2f, window.position.height / 2f) });
  202. // Setting up for the test.
  203. // Finding an edge:
  204. int dstBlockIdx = -1;
  205. int srcBlockIdx = -1;
  206. int line = -1;
  207. for (int idx = 0; idx < window._burstDisassembler.Blocks.Count; idx++)
  208. {
  209. var block = window._burstDisassembler.Blocks[idx];
  210. if (block.Edges != null)
  211. {
  212. foreach (var edge in block.Edges)
  213. {
  214. if (edge.Kind == BurstDisassembler.AsmEdgeKind.OutBound)
  215. {
  216. dstBlockIdx = edge.LineRef.BlockIndex;
  217. line = window._textArea.blockLine[dstBlockIdx];
  218. if ((dstBlockIdx == idx + 1 && edge.LineRef.LineIndex == 0)) // pointing to next line
  219. {
  220. continue;
  221. }
  222. srcBlockIdx = idx;
  223. break;
  224. }
  225. }
  226. if (srcBlockIdx != -1)
  227. {
  228. break;
  229. }
  230. }
  231. }
  232. if (srcBlockIdx == -1)
  233. {
  234. window.Close();
  235. throw new System.Exception("No edges present in assembly for \"BurstInspectorGUITests.MyJob - (IJob)\"");
  236. }
  237. float dist = window._textArea.fontHeight * line;
  238. float x = (window.position.width - (window._inspectorView.width + BurstInspectorGUI._scrollbarThickness)) + window._textArea.horizontalPad - (2*window._textArea.fontWidth);
  239. // setting _ScrollPos so end of arrow is at bottom of screen, to make sure there is actually room for the scrolling.
  240. window._scrollPos = new Vector2(0, dist - window._inspectorView.height * 0.93f);
  241. // Setting mousePos to bottom of inspector view.
  242. float topOfInspectorToBranchArrow = window._buttonOverlapInspectorView + 66.5f;//66.5f is the size of space over the treeview of different jobs.
  243. var mousePos = new Vector2(x, topOfInspectorToBranchArrow + window._inspectorView.height - 0.5f*window._textArea.fontHeight);
  244. return new InfoThingy() { blockIdx = (srcBlockIdx, dstBlockIdx), mousePos = mousePos};
  245. }
  246. public static IEnumerable ValueSource
  247. {
  248. get
  249. {
  250. yield return "BurstInspectorGUITests.MyJob - (IJob)";
  251. yield return "BurstReflectionTests.GenericType`1.NestedGeneric`1[System.Int32,System.Single].TestMethod3()";
  252. yield return "BurstReflectionTests.GenericType`1.NestedNonGeneric[System.Int32].TestMethod2()";
  253. yield return "BurstReflectionTests.GenericParallelForJob`1[System.Int32] - (IJobParallelFor)";
  254. }
  255. }
  256. [UnityTest]
  257. public IEnumerator FocusCodeTest([ValueSource(nameof(ValueSource))] string job)
  258. {
  259. var win = EditorWindow.GetWindow<BurstInspectorGUI>();
  260. yield return SelectJobAwaitLoad(job);
  261. // Doesn't check that it's at the right spot, simply that it actually moves
  262. Assert.IsFalse(Mathf.Approximately(win._inspectorView.y, 0f), "Inspector view did not change");
  263. win.Close();
  264. }
  265. public static IEnumerable FocusCodeNotBranchesSource
  266. {
  267. get
  268. {
  269. yield return (1000, false);
  270. yield return (563, true);
  271. }
  272. }
  273. [UnityTest]
  274. public IEnumerator FocusCodeNotBranchesTest([ValueSource(nameof(FocusCodeNotBranchesSource))] (int, bool) input)
  275. {
  276. var (width, doFocus) = input;
  277. const string case1 = "BurstInspectorGUITests.BranchArrows - (IJob)";
  278. const string case2 = "BurstInspectorGUITests.BranchArrows2 - (IJob)";
  279. var win = EditorWindow.GetWindow<BurstInspectorGUI>();
  280. // Force window size to be small enough for it to position it more to the right.
  281. win.position = new Rect(win.position.x, win.position.y, width, 405);
  282. // Test one where it should focus.
  283. yield return SelectJobAwaitLoad(case1);
  284. var val1 = win._inspectorView.x;
  285. var result1 = Mathf.Approximately(val1, 0f);
  286. // Test two with no focus.
  287. win._assemblyKind = BurstInspectorGUI.AssemblyOptions.PlainWithDebugInformation;
  288. yield return SelectJobAwaitLoad(case2);
  289. var val2 = win._inspectorView.x;
  290. var result2 = Mathf.Approximately(val2, 0f);
  291. // Cleanup and test assertions.
  292. win.Close();
  293. Assert.AreEqual(doFocus, result1 == doFocus, $"Inspector view wrong.");
  294. //Assert.IsFalse(result1, $"Inspector view did not change (Is {val1}).");
  295. Assert.IsTrue(result2, $"Inspector view changed unexpectedly (Is {val2}).");
  296. }
  297. [UnityTest]
  298. public IEnumerator SelectionNotOutsideBoundsTest()
  299. {
  300. void MoveSelection(BurstInspectorGUI gui, LongTextArea.Direction dir)
  301. {
  302. switch (dir)
  303. {
  304. case LongTextArea.Direction.Down:
  305. gui._textArea.SelectAll();
  306. gui._textArea.MoveSelectionDown(gui._inspectorView, true);
  307. break;
  308. case LongTextArea.Direction.Right:
  309. gui._textArea.SelectAll();
  310. gui._textArea.MoveSelectionRight(gui._inspectorView, true);
  311. break;
  312. case LongTextArea.Direction.Left:
  313. gui._textArea.selectDragPos = Vector2.zero;
  314. gui._textArea.MoveSelectionLeft(gui._inspectorView, true);
  315. break;
  316. case LongTextArea.Direction.Up:
  317. gui._textArea.selectDragPos = Vector2.zero;
  318. gui._textArea.MoveSelectionUp(gui._inspectorView, true);
  319. break;
  320. }
  321. }
  322. var win = EditorWindow.GetWindow<BurstInspectorGUI>();
  323. yield return SelectJobAwaitLoad("BurstInspectorGUITests.MyJob - (IJob)");
  324. try
  325. {
  326. foreach (var dir in Enum.GetValues(typeof(LongTextArea.Direction)))
  327. {
  328. MoveSelection(win, (LongTextArea.Direction)dir);
  329. yield return null;
  330. // Check that no errors have happened.
  331. LogAssert.NoUnexpectedReceived();
  332. }
  333. }
  334. finally
  335. {
  336. win.Close();
  337. }
  338. }
  339. [UnityTest]
  340. public IEnumerator SelectionInAssemblySearchBarTest()
  341. {
  342. yield return SelectJobAwaitLoad("BurstInspectorGUITests.MyJob - (IJob)");
  343. var win = EditorWindow.GetWindow<BurstInspectorGUI>();
  344. win._searchFieldAssembly.SetFocus();
  345. yield return null;
  346. // Send events to input some text.
  347. win.SendEvent(Event.KeyboardEvent("a"));
  348. win.SendEvent(Event.KeyboardEvent("b"));
  349. yield return null;
  350. // Move select some using keyboard input
  351. win.SendEvent(Event.KeyboardEvent("left"));
  352. win.SendEvent(Event.KeyboardEvent("#right"));
  353. yield return null;
  354. // Do a copy
  355. var savedClipBoard = EditorGUIUtility.systemCopyBuffer;
  356. win.SendEvent(SystemInfo.operatingSystemFamily == OperatingSystemFamily.MacOSX
  357. ? Event.KeyboardEvent("%c")
  358. : Event.KeyboardEvent("^c"));
  359. yield return null;
  360. var copiedText = EditorGUIUtility.systemCopyBuffer;
  361. EditorGUIUtility.systemCopyBuffer = savedClipBoard;
  362. // Check that all is good
  363. win.Close();
  364. Assert.AreEqual("b", copiedText, "Copied text did not match expectation.");
  365. }
  366. [UnityTest]
  367. public IEnumerator GoToNextSearchTargetTest()
  368. {
  369. var active = -1;
  370. var nextActive = -1;
  371. yield return SelectJobAwaitLoad("BurstInspectorGUITests.MyJob - (IJob)");
  372. var win = EditorWindow.GetWindow<BurstInspectorGUI>();
  373. try
  374. {
  375. win._searchFieldAssembly.SetFocus();
  376. yield return null;
  377. // Do a search in the text.
  378. win.SendEvent(Event.KeyboardEvent("p"));
  379. win.SendEvent(Event.KeyboardEvent("u"));
  380. win.SendEvent(Event.KeyboardEvent("return"));
  381. yield return null;
  382. active = win._textArea._activeSearchHitIdx;
  383. // Select next search target.
  384. win.SendEvent(Event.KeyboardEvent("return"));
  385. yield return null;
  386. nextActive = win._textArea._activeSearchHitIdx;
  387. }
  388. finally
  389. {
  390. win.Close();
  391. }
  392. Assert.AreNotEqual(active, nextActive, "Active search target was not changed.");
  393. }
  394. [Test]
  395. public void CorrectFormattingOfAssembly()
  396. {
  397. EditorWindow.GetWindow<BurstInspectorGUI>().Close();
  398. const string assemblyName = "BurstInspectorGUITests.MyJob - (IJob)";
  399. var textArea = new LongTextArea();
  400. foreach (BurstTargetCpu target in Enum.GetValues(typeof(BurstTargetCpu)))
  401. {
  402. if (target == BurstTargetCpu.WASM32)
  403. {
  404. // We do not draw flow-lines for wasm yet, so skip this one.
  405. continue;
  406. }
  407. var disassembler = BurstInspectorTestUtil.GetDisassemblerAndText(assemblyName, 1, target, out var assembly);
  408. var asmKind = BurstInspectorGUI.FetchAsmKind(target, DisassemblyKind.Asm);
  409. textArea.SetText(
  410. "random",
  411. assembly,
  412. true,
  413. disassembler,
  414. disassembler.Initialize(
  415. assembly,
  416. asmKind
  417. )
  418. );
  419. // Check that it found branches. This indicates whether we formatted as the correct assembly kind.
  420. Assert.Greater(textArea.MaxLineDepth, 0, $"Failed with {target}");
  421. }
  422. }
  423. [UnityTest]
  424. public IEnumerator FocusSpecialCharacterCode()
  425. {
  426. var win = EditorWindow.GetWindow<BurstInspectorGUI>();
  427. yield return SelectJobAwaitLoad("BurstInspectorGUITests.CustomJobWithSpecialCharacter - (BurstInspectorGUITests.ICustomJob`1[System.Single])");
  428. // Check that there are no errors.
  429. LogAssert.NoUnexpectedReceived();
  430. win.Close();
  431. }
  432. [BurstCompile]
  433. private struct MyJob : IJob
  434. {
  435. [ReadOnly]
  436. public NativeArray<float> Inpút;
  437. [WriteOnly]
  438. public NativeArray<float> Output;
  439. public void Execute()
  440. {
  441. float result = 0.0f;
  442. for (int i = 0; i < Inpút.Length; i++)
  443. {
  444. result += Inpút[i];
  445. }
  446. Output[0] = result;
  447. }
  448. }
  449. [BurstCompile]
  450. private struct BranchArrows : IJob
  451. {
  452. [ReadOnly]
  453. public NativeArray<float> Inpút;
  454. [WriteOnly]
  455. public NativeArray<float> Output;
  456. public void Execute()
  457. {
  458. float result = 0.0f;
  459. for (int i = 0; i < Inpút.Length; i++)
  460. {
  461. if (Inpút[i] < 10) { result += 1; }
  462. else if (Inpút[i] < 20) { result += 2; }
  463. else if (Inpút[i] < 30) { result += 3; }
  464. else if (Inpút[i] < 40) { result += 4; }
  465. else if (Inpút[i] < 50) { result += 5; }
  466. else if (Inpút[i] < 60) { result += 6; }
  467. else if (Inpút[i] < 70) { result += 7; }
  468. else if (Inpút[i] < 80) { result += 8; }
  469. else if (Inpút[i] < 90) { result += 9; }
  470. result += Inpút[i];
  471. }
  472. Output[0] = result;
  473. }
  474. }
  475. [BurstCompile]
  476. private struct BranchArrows2 : IJob
  477. {
  478. [ReadOnly]
  479. public NativeArray<float> Inpút;
  480. [WriteOnly]
  481. public NativeArray<float> Output;
  482. public void Execute()
  483. {
  484. float result = 0.0f;
  485. for (int i = 0; i < Inpút.Length; i++)
  486. {
  487. if (Inpút[i] < 10) { result += 1; }
  488. else if (Inpút[i] < 20) { result += 2; }
  489. else if (Inpút[i] < 30) { result += 3; }
  490. else if (Inpút[i] < 40) { result += 4; }
  491. else if (Inpút[i] < 50) { result += 5; }
  492. else if (Inpút[i] < 60) { result += 6; }
  493. else if (Inpút[i] < 70) { result += 7; }
  494. else if (Inpút[i] < 80) { result += 8; }
  495. else if (Inpút[i] < 90) { result += 9; }
  496. result += Inpút[i];
  497. }
  498. Output[0] = result;
  499. }
  500. }
  501. private class BurstDisassemblerWithCopy : BurstDisassembler
  502. {
  503. public List<AsmBlock> BlocksCopy;
  504. public bool IsColoredCopy;
  505. public List<AsmLine> LinesCopy;
  506. public List<AsmToken> TokensCopy;
  507. public BurstDisassemblerWithCopy(BurstDisassembler disassembler) : base()
  508. {
  509. IsColoredCopy = disassembler.IsColored;
  510. BlocksCopy = new List<AsmBlock>(disassembler.Blocks);
  511. LinesCopy = new List<AsmLine>(disassembler.Lines);
  512. TokensCopy = new List<AsmToken>(disassembler.Tokens);
  513. }
  514. public bool Equals(BurstDisassembler other)
  515. {
  516. return IsColoredCopy == other.IsColored
  517. && BlocksCopy.SequenceEqual(other.Blocks)
  518. && LinesCopy.SequenceEqual(other.Lines)
  519. && TokensCopy.SequenceEqual(other.Tokens);
  520. }
  521. }
  522. [BurstCompile]
  523. public struct CustomJobWithSpecialCharacter : ICustomJob<float>
  524. {
  525. public void Execute(float test)
  526. {
  527. test = 5;
  528. }
  529. }
  530. [JobProducerType(typeof(CustomJobExtensions.JobStruct<,>))]
  531. private interface ICustomJob<T> where T : struct
  532. {
  533. void Execute(T item);
  534. }
  535. private static class CustomJobExtensions
  536. {
  537. public struct JobStruct<TJ, T>
  538. where TJ : struct, ICustomJob<T>
  539. where T : struct
  540. {
  541. [BurstCompile]
  542. public struct Data
  543. {
  544. public T additionalData;
  545. public TJ job;
  546. }
  547. private static void Execute(ref Data data)
  548. {
  549. data.job.Execute(data.additionalData);
  550. }
  551. }
  552. }
  553. private class CustomJobScheduler
  554. {
  555. private void ScheduleJob()
  556. {
  557. var job = new CustomJobWithSpecialCharacter();
  558. job.Execute(10);
  559. }
  560. }
  561. }