initial commit

This commit is contained in:
Jo 2025-01-07 02:06:59 +01:00
parent 6715289efe
commit 788c3389af
37645 changed files with 2526849 additions and 80 deletions

View file

@ -0,0 +1,189 @@
using System;
using System.Text;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
using NUnit.Framework;
using Unity.Burst.Editor;
using UnityEngine;
using Unity.Burst;
using Random = System.Random;
[TestFixture]
public class BurstDisassemblerCoreInstructionTests
{
// Use chooser enum instead of BurstDisassembler.AsmKind because of accessibility level.
public enum Chooser
{
ARM,
INTEL,
LLVMIR,
Wasm
}
[Test]
[TestCase(Chooser.ARM)]
[TestCase(Chooser.INTEL)]
// [TestCase(Chooser.LLVMIR)]
[TestCase(Chooser.Wasm)]
public void TestInfo(Chooser provider)
{
BurstDisassembler.AsmTokenKindProvider tokenProvider;
switch (provider)
{
case Chooser.ARM:
tokenProvider = BurstDisassembler.ARM64AsmTokenKindProvider.Instance;
break;
case Chooser.INTEL:
tokenProvider = BurstDisassembler.X86AsmTokenKindProvider.Instance;
break;
case Chooser.Wasm:
tokenProvider = BurstDisassembler.WasmAsmTokenKindProvider.Instance;
break;
default:
throw new Exception("Oops you forgot to add a switch case in the test *quirky smiley*.");
}
var tokenProviderT = typeof(BurstDisassembler.AsmTokenKindProvider);
var field = tokenProviderT.GetField("_tokenKinds",
BindingFlags.Instance | BindingFlags.NonPublic);
Assert.NotNull(field, "Could not find _tokenKinds field in AsmTokenKindProvider");
var allTokens = (Dictionary<StringSlice, BurstDisassembler.AsmTokenKind>)field.GetValue(tokenProvider);
var tokensToTest =
from tok in allTokens.Keys
where allTokens.TryGetValue(tok, out var kind)
&& kind != BurstDisassembler.AsmTokenKind.Qualifier
&& kind != BurstDisassembler.AsmTokenKind.Register
select tok.ToString();
var count = 0;
foreach (var token in tokensToTest)
{
var res = false;
switch (provider)
{
case Chooser.ARM:
res = BurstDisassembler.ARM64InstructionInfo.GetARM64Info(token, out var _);
break;
case Chooser.INTEL:
res = BurstDisassembler.X86AsmInstructionInfo.GetX86InstructionInfo(token, out var _);
break;
case Chooser.LLVMIR:
res = BurstDisassembler.LLVMIRInstructionInfo.GetLLVMIRInfo(token, out var _);
break;
case Chooser.Wasm:
res = BurstDisassembler.WasmInstructionInfo.GetWasmInfo(token, out var _);
break;
}
if (!res)
{
Debug.Log($"Token \"{token}\" from {provider} does not have information associated.");
count++;
}
}
Assert.Zero(count, $"{provider.ToString()} is missing information for {count} token(s).");
}
/// <summary>
/// Tests whether all instructions in available burst jobs are displayed correctly.
/// </summary>
[Test]
[TestCase(Chooser.ARM)]
[TestCase(Chooser.INTEL)]
[TestCase(Chooser.Wasm)]
public void TestInstructionsPresent(Chooser asmKind)
{
BurstTargetCpu targetCpu;
BurstDisassembler.AsmKind targetKind;
switch (asmKind)
{
case Chooser.INTEL:
targetCpu = BurstTargetCpu.X64_SSE4;
targetKind = BurstDisassembler.AsmKind.Intel;
break;
case Chooser.ARM:
targetCpu = BurstTargetCpu.ARMV7A_NEON32;
targetKind = BurstDisassembler.AsmKind.ARM;
break;
default: // WASM as LLVMIR is not tested.
targetCpu = BurstTargetCpu.WASM32;
targetKind = BurstDisassembler.AsmKind.Wasm;
break;
}
// Find all possible burst compile targets.
var jobList = BurstReflection.FindExecuteMethods(
BurstReflection.EditorAssembliesThatCanPossiblyContainJobs,
BurstReflectionAssemblyOptions.None).CompileTargets;
var missingInstructions = new Dictionary<string, string>();
var disassembler = new BurstDisassembler();
foreach (var target in jobList)
{
// Get disassembly of target.
var options = new StringBuilder();
target.Options.TryGetOptions(target.JobType, true, out var defaultOptions);
options.AppendLine(defaultOptions);
// Disables the 2 current warnings generated from code (since they clutter up the inspector display)
// BC1370 - throw inside code not guarded with ConditionalSafetyCheck attribute
// BC1322 - loop intrinsic on loop that has been optimised away
options.AppendLine($"{BurstCompilerOptions.GetOption(BurstCompilerOptions.OptionDisableWarnings, "BC1370;BC1322")}");
options.AppendLine($"{BurstCompilerOptions.GetOption(BurstCompilerOptions.OptionTarget, Enum.GetNames(typeof(BurstTargetCpu))[(int)targetCpu])}");
options.AppendLine($"{BurstCompilerOptions.GetOption(BurstCompilerOptions.OptionDebug, "0")}");
var baseOptions = options.ToString();
var append = BurstInspectorGUI.GetDisasmOptions()[(int)DisassemblyKind.Asm];
// Setup disAssembler with the job:
var text = BurstInspectorGUI.GetDisassembly(target.Method, baseOptions + append);
// Bail out if there was a Burst compiler error, because we'll have all sorts of unexpected tokens.
if (BurstInspectorGUI.IsBurstError(text))
{
continue;
}
text = text.TrimStart('\n');
Assert.IsTrue(disassembler.Initialize(text, targetKind, true, false), "Could not initialize disassembler.");
// Get all tokens labeled as AsmTokenKind.Identifier that do not start with '.' nor ends on ':'.
// If this number exceeds 0 we are missing instructions (I believe).
const int INSTRUCTION_PRE_PADDING = 8;
var tokens =
(from tok in disassembler.Tokens
where tok.Kind == BurstDisassembler.AsmTokenKind.Identifier
&& !disassembler.GetTokenAsText(tok).StartsWith(".")
&& !disassembler.GetTokenAsText(tok).EndsWith(":")
&& text[tok.Position - INSTRUCTION_PRE_PADDING - 1] == '\n'
select tok).ToList();
foreach (var token in tokens)
{
if (missingInstructions.ContainsKey(token.ToString(text)))
{
continue;
}
missingInstructions.Add(token.ToString(text), target.GetDisplayName());
}
}
// Convey result.
if (missingInstructions.Count > 0)
{
foreach (var itm in missingInstructions)
{
var token = itm.Key;
var name = itm.Value;
Debug.Log($"Token \"{token}\" was not recognised as instruction for {targetKind} (Found in job {name}).");
}
Assert.Fail($"{missingInstructions.Count} missing instructions, see log. Add missing instructions and call both this test and {nameof(TestInfo)}.");
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c68d1e883c8136a89133cc095391d26b
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,383 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Reflection;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
using Unity.Burst;
using Unity.Burst.Editor;
using UnityEditorInternal;
using System.Runtime.CompilerServices;
public class BurstDisassemblerTests
{
private BurstDisassembler _disassembler;
[OneTimeSetUp]
public void SetUp()
{
_disassembler = new BurstDisassembler();
}
private static string GetThisFilePath([CallerFilePath] string path = null) => path;
// A Test behaves as an ordinary method
[Test]
public void GetBlockIdxFromTextIdxTest()
{
var thisPath = Path.GetDirectoryName(GetThisFilePath());
Assert.IsTrue(_disassembler.Initialize(
File.ReadAllText(Path.Combine(thisPath, "burstTestTarget.txt")),
BurstDisassembler.AsmKind.Intel,
false,
false));
for (int blockIdx = 0; blockIdx < _disassembler.Blocks.Count; blockIdx++)
{
int blockStart = 0;
for (int i = 0; i < blockIdx; i++)
{
blockStart += _disassembler.GetOrRenderBlockToText(i).Length;
}
var blockStr = _disassembler.GetOrRenderBlockToText(blockIdx);
int blockEnd = blockStart + blockStr.Length - 1;
Assert.AreEqual((blockIdx, blockStart, blockEnd),
_disassembler.GetBlockIdxFromTextIdx(blockStart + 1),
$"Block index was wrong for block with label {blockStr.Substring(0, blockStr.IndexOf('\n'))}");
}
}
[Test]
public void InstantiateRegistersUsedTest()
{
Assert.IsTrue(_disassembler.Initialize(simpleAssembly, BurstDisassembler.AsmKind.Intel));
var regsUsed = _disassembler._registersUsedAtLine;
// Match against expected:
var expectedLines = from l in expected select l.lineNr;
var failed = expectedLines.Except(regsUsed._linesRegisters.Keys);
failed = failed.Concat(regsUsed._linesRegisters.Keys.Except(expectedLines)).Distinct();
if (failed.Any())
{
// Not exact match
foreach (var f in failed)
{
Debug.Log($"lineNumber {f} failed");
}
Assert.Fail();
}
}
[Test]
public void CleanRegisterListTest()
{
Assert.IsTrue(_disassembler.Initialize(simpleAssembly, BurstDisassembler.AsmKind.Intel));
var regs = new List<string> { "rcx", "ecx", "rax" };
var output = _disassembler._registersUsedAtLine.CleanRegs(regs);
var expected = new List<string> { "rcx", "rax" };
Assert.AreEqual(output, expected);
}
[Test]
public void IndexOfRegisterTest()
{
var assembly =
"\n" +
" nop\n" +
" movsxd rcx, cx\n" +
" mov rax, qword ptr [rbp - 16]";
Assert.IsTrue(_disassembler.Initialize(assembly, BurstDisassembler.AsmKind.Intel));
string[,] regs =
{
{ "rcx", "cx" },
{ "rax", "rbp" }
};
string[] lines =
{
" movsxd rcx, cx\n",
" mov rax, qword ptr [rbp - 16]"
};
for (var i = 0; i < 2; i++)
{
var line = lines[i];
var reg = regs[i, 0];
var asmLine = _disassembler.Lines[i+1];
var output = _disassembler.GetRegisterTokenIndex(asmLine, reg);
var regIdx = _disassembler.Tokens[output].AlignedPosition - _disassembler.Tokens[asmLine.TokenIndex].AlignedPosition;
var expected = line.IndexOf(reg) + 1;
Assert.AreEqual(expected, regIdx, $"Failed for line \"{line}\"");
reg = regs[i, 1];
output = _disassembler.GetRegisterTokenIndex(asmLine, reg, output + 1);
regIdx = _disassembler.Tokens[output].AlignedPosition - _disassembler.Tokens[asmLine.TokenIndex].AlignedPosition;
expected = line.IndexOf(reg, expected + 1) + 1;
Assert.AreEqual(expected, regIdx, $"Failed for line \"{line}\"");
}
}
[Test]
[TestCase("x86", new [] {"rdx","edx","dx","dl"}, "dl")]
[TestCase("arm", new [] {"wsp", "sp"},"sp")]
[TestCase("arm", new [] {"v0.2d", "s0", "q0", "h0", "d0", "b0"}, "b0")]
[TestCase("arm", new [] {"w0","x0"}, "x0")]
public void RegisterEqualityTest(string assemblyName, string[] assemblyLine, string register)
{
BurstDisassembler.AsmTokenKindProvider tokenProvider = BurstDisassembler.ARM64AsmTokenKindProvider.Instance;
if (assemblyName == "x86")
{
tokenProvider = BurstDisassembler.X86AsmTokenKindProvider.Instance;
}
foreach (var reg in assemblyLine)
{
Assert.IsTrue(tokenProvider.RegisterEqual(reg, register), $"{reg} == {register}");
}
// Some special cases:
tokenProvider = BurstDisassembler.ARM64AsmTokenKindProvider.Instance;
Assert.IsFalse(tokenProvider.RegisterEqual("w8", "x0"), $"w8 != x0");
Assert.IsFalse(tokenProvider.RegisterEqual("w0", "q0"), "w0 != q0");
Assert.IsFalse(tokenProvider.RegisterEqual("x0", "q0"), "x0 != q0");
}
[Test]
public void RegisterEqualTest()
{
// Only tests for x86, as the others are trivial.
Assert.IsTrue(_disassembler.Initialize(simpleAssembly, BurstDisassembler.AsmKind.Intel));
// Get all register strings:
var tokenProvider = BurstDisassembler.X86AsmTokenKindProvider.Instance;
var tokenProviderT = typeof(BurstDisassembler.AsmTokenKindProvider);
var field = tokenProviderT.GetField("_tokenKinds",
BindingFlags.Instance | BindingFlags.NonPublic);
Assert.NotNull(field, "Could not find _tokenKinds field in AsmTokenKindProvider");
var allTokens = (Dictionary<StringSlice, BurstDisassembler.AsmTokenKind>)field.GetValue(tokenProvider);
var tokensToTest =
from tok in allTokens.Keys
where allTokens.TryGetValue(tok, out var kind)
&& kind == BurstDisassembler.AsmTokenKind.Register
select tok.ToString();
// Test that equality works for all registers:
try
{
foreach (var reg in tokensToTest)
{
// Simply check whether all registers are processable:
tokenProvider.RegisterEqual(reg, "rax");
}
}
catch (Exception e)
{
Assert.Fail($"Not all registers works for register equality (x86). {e}");
}
}
[Test]
public void InstructionAlignmentTest()
{
var assembly =
"\n" + // newline as BurstDisassembler ignores first line
" push rbp\n" +
" .seh_pushreg rbp\n" +
" sub rsp, 32\n";
(int, char)[] expectedPositions =
{
(1,' '), (10, 'p'), (14, ' '), (24, 'r'), (27, '\n'),
(28, ' '), (37, '.'), (49, ' '), (50, 'r'), (53, '\n'),
(54, ' '), (63, 's'), (66, ' '), (77, 'r'), (80, ','), (82, '3'), (84, '\n')
};
Assert.IsTrue(_disassembler.Initialize(assembly, BurstDisassembler.AsmKind.Intel));
var builder = new StringBuilder();
for (int i = 0; i < _disassembler.Blocks.Count; i++)
{
var text = _disassembler.GetOrRenderBlockToTextUncached(i, false);
builder.Append(text);
}
var output = builder.ToString();
for (var i = 0; i < expectedPositions.Length; i++)
{
Assert.AreEqual(expectedPositions[i].Item1, _disassembler.Tokens[i].AlignedPosition);
}
foreach (var (idx, c) in expectedPositions)
{
// -1 as token index for some reason aren't zero indexed.
Assert.AreEqual(c, output[idx-1], $"Token position for index {idx} was wrong.");
}
}
[Test]
public void X86AsmTokenProviderSimdKindTest()
{
var tp = BurstDisassembler.X86AsmTokenKindProvider.Instance;
BurstDisassembler.SIMDkind actual = tp.SimdKind(new StringSlice("vsqrtsd"));
var expected = BurstDisassembler.SIMDkind.Scalar;
Assert.AreEqual(expected, actual);
actual = tp.SimdKind(new StringSlice("vroundpd"));
expected = BurstDisassembler.SIMDkind.Packed;
Assert.AreEqual(expected, actual);
actual = tp.SimdKind(new StringSlice("xsaves"));
expected = BurstDisassembler.SIMDkind.Infrastructure;
Assert.AreEqual(expected,actual);
}
[Test]
public void ARMAsmTokenProviderSimdKindTest()
{
var tp = BurstDisassembler.ARM64AsmTokenKindProvider.Instance;
BurstDisassembler.SIMDkind actual = tp.SimdKind(new StringSlice("vaddw"));
var expected = BurstDisassembler.SIMDkind.Scalar;
Assert.AreEqual(expected, actual);
actual = tp.SimdKind(new StringSlice("vadd.i8"));
expected = BurstDisassembler.SIMDkind.Packed;
Assert.AreEqual(expected, actual);
}
private string GetFirstColorTag(string line)
{
const string colorTag = "#XXXXXX";
const string tag = "<color=";
int idx = line.IndexOf('<');
return line.Substring(idx + tag.Length, colorTag.Length);
}
private const string ARMsimdAssembly =
"\n" +
" ldr r0, [sp, #12]\n" +
" vldr s0, [sp, #20]\n" +
" vstr s0, [sp, #4]\n" +
" ldr r1, [sp, #24]\n" +
" vldr s0, [sp, #4]\n" +
" vmov s2, r0\n" +
" vadd.f32 s0, s0, s2\n" +
" vstr s0, [sp, #20]";
private const string X86SimdAssembly =
"\n" +
" mov rcx, qword ptr [rbp - 32]\n" +
" vmovss xmm0, dword ptr [rbp - 12]\n" +
" vmovss dword ptr [rbp - 40], xmm0\n" +
" mov edx, dword ptr [rbp - 8]\n" +
" call \"Unity.Collections.NativeArray`1<float>.get_Item(Unity.Collections.NativeArray`1<float>* this, int index) -> float_c303f72c9cc472e2ef84a442ead69ef2 from Unity.Burst.Editor.Tests, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null\"\n" +
" vmovaps xmm1, xmm0\n" +
" vmovss xmm0, dword ptr [rbp - 40]\n" +
" vaddss xmm0, xmm0, xmm1\n" +
" vmovss dword ptr [rbp - 12], xmm0\n" +
" vzeroall";
[Test]
[TestCase(X86SimdAssembly, 0, BurstDisassembler.DarkColorInstructionSIMDScalar, 1)]
[TestCase(X86SimdAssembly, 0, BurstDisassembler.DarkColorInstructionSIMDPacked, 5)]
[TestCase(X86SimdAssembly, 0, BurstDisassembler.DarkColorInstructionSIMD, 9)]
[TestCase(ARMsimdAssembly, 1, BurstDisassembler.DarkColorInstructionSIMDScalar, 1)]
[TestCase(ARMsimdAssembly, 1, BurstDisassembler.DarkColorInstructionSIMDPacked, 6)]
public void AssemblyColouringSmellTest(string asm, int asmkind, string colorTag, int lineIdx)
{
_disassembler.Initialize(asm, (BurstDisassembler.AsmKind)asmkind, true, true, true);
var line = _disassembler.Lines[lineIdx];
_disassembler._output.Clear();
_disassembler.RenderLine(ref line, true);
var lineString = _disassembler._output.ToString();
_disassembler._output.Clear();
Assert.AreEqual(colorTag, GetFirstColorTag(lineString));
}
private List<(int lineNr, List<string>)> expected = new List<(int lineNr, List<string>)>
{
(2, new List<string> { "rbp" }),
(3, new List<string> { "rbp" }),
(4, new List<string> { "rsp" }),
(6, new List<string> { "rbp", "rsp" }),
(7, new List<string> { "rbp" }),
(11, new List<string> { "rsp" }),
(12, new List<string> { "rbp" }),
(26, new List<string> { "rbp" }),
(27, new List<string> { "rbp" }),
(28, new List<string> { "rsp" }),
(30, new List<string> { "rbp", "rsp" }),
(31, new List<string> { "rbp" }),
(36, new List<string> { "rsp" }),
(37, new List<string> { "rbp" }),
};
private string simpleAssembly =
"\n" + // newline as BurstDisassembler ignores first line
".Lfunc_begin0:\n" +
".seh_proc 589a9d678dbb1201e550a054238fad11\n" +
" push rbp\n" +
" .seh_pushreg rbp\n" +
" sub rsp, 32\n" +
" .seh_stackalloc 32\n" +
" lea rbp, [rsp + 32]\n" +
" .seh_setframe rbp, 32\n" +
" .seh_endprologue\n" +
" call A.B.DoIt\n" +
" nop\n" +
" add rsp, 32\n" +
" pop rbp\n" +
" ret\n" +
" .Lfunc_end0:\n" +
" .seh_endproc\n" +
" \n" +
" .def burst.initialize;\n" +
" .scl 2;\n" +
" .type 32;\n" +
" .endef\n" +
" .globl burst.initialize\n" +
" .p2align 4, 0x90\n" +
" burst.initialize:\n" +
" .Lfunc_begin1:\n" +
" .seh_proc burst.initialize\n" +
" push rbp\n" +
" .seh_pushreg rbp\n" +
" sub rsp, 32\n" +
" .seh_stackalloc 32\n" +
" lea rbp, [rsp + 32]\n" +
" .seh_setframe rbp, 32\n" +
" .seh_endprologue\n" +
" call burst.initialize.externals\n" +
" call burst.initialize.statics\n" +
" nop\n" +
" add rsp, 32\n" +
" pop rbp\n" +
" ret\n" +
" .Lfunc_end1:\n" +
" .seh_endproc\n" +
" \n" +
" .def burst.initialize.externals;\n" +
" .scl 2;\n" +
" .type 32;\n" +
" .endef\n" +
" .globl burst.initialize.externals\n" +
" .p2align 4, 0x90";
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 35ff2f449e6f335cb4f69ebb36ecf3e5
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,588 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Unity.Burst.Editor;
using UnityEditor;
using UnityEngine;
using UnityEngine.TestTools;
using Unity.Collections;
using Unity.Burst;
using Unity.Jobs;
[TestFixture]
[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor)]
public class BurstInspectorGUITests
{
private readonly WaitUntil _waitForInitialized =
new WaitUntil(() => EditorWindow.GetWindow<BurstInspectorGUI>()._initialized);
private IEnumerator SelectJobAwaitLoad(string assemblyName)
{
EditorWindow.GetWindow<BurstInspectorGUI>()._treeView.TrySelectByDisplayName(assemblyName);
return new WaitUntil(() =>
EditorWindow.GetWindow<BurstInspectorGUI>()._textArea.IsTextSet(assemblyName)
);
}
[UnitySetUp]
public IEnumerator SetUp()
{
// Close down window if it's open, to start with a fresh inspector.
EditorWindow.GetWindow<BurstInspectorGUI>().Close();
EditorWindow.GetWindow<BurstInspectorGUI>().Show();
// Make sure window is actually initialized before continuing.
yield return _waitForInitialized;
}
[UnityTest]
public IEnumerator TestInspectorOpenDuringDomainReloadDoesNotLogErrors()
{
// Show Inspector window
EditorWindow.GetWindow<BurstInspectorGUI>().Show();
Assert.IsTrue(EditorWindow.HasOpenInstances<BurstInspectorGUI>());
// Ask for domain reload
EditorUtility.RequestScriptReload();
// Wait for the domain reload to be completed
yield return new WaitForDomainReload();
Assert.IsTrue(EditorWindow.HasOpenInstances<BurstInspectorGUI>());
// Hide Inspector window
EditorWindow.GetWindow<BurstInspectorGUI>().Close();
Assert.IsFalse(EditorWindow.HasOpenInstances<BurstInspectorGUI>());
}
[UnityTest]
public IEnumerator DisassemblerNotChangingUnexpectedlyTest()
{
const string jobName2 = "BurstReflectionTests.MyJob - (IJob)";
const string jobName = "BurstInspectorGUITests.MyJob - (IJob)";
// Selecting a specific assembly.
yield return SelectJobAwaitLoad(jobName);
var window = EditorWindow.GetWindow<BurstInspectorGUI>();
try
{
// Sending event to set the displayname, to avoid it resetting _scrollPos because of target change.
window.SendEvent(new Event()
{
type = EventType.Repaint,
mousePosition = new Vector2(window.position.width / 2f, window.position.height / 2f)
});
yield return null;
// Doing actual test work:
var prev = new BurstDisassemblerWithCopy(window._burstDisassembler);
window.SendEvent(new Event()
{
type = EventType.Repaint,
mousePosition = new Vector2(window.position.width / 2f, window.position.height / 2f)
});
yield return null;
Assert.IsTrue(prev.Equals(window._burstDisassembler),
"Public fields changed in burstDisassembler even though they shouldn't");
prev = new BurstDisassemblerWithCopy(window._burstDisassembler);
window.SendEvent(new Event() { type = EventType.MouseUp, mousePosition = Vector2.zero });
yield return null;
Assert.IsTrue(prev.Equals(window._burstDisassembler),
"Public fields changed in burstDisassembler even though they shouldn't");
prev = new BurstDisassemblerWithCopy(window._burstDisassembler);
yield return SelectJobAwaitLoad(jobName2);
window = EditorWindow.GetWindow<BurstInspectorGUI>();
window.SendEvent(new Event()
{
type = EventType.Repaint,
mousePosition = new Vector2(window.position.width / 2f, window.position.height / 2f)
});
yield return null;
Assert.IsFalse(prev.Equals(window._burstDisassembler), "Public fields of burstDisassembler did not change");
}
finally
{
window.Close();
}
}
[UnityTest]
public IEnumerator InspectorStallingLoadTest()
{
// Error was triggered by selecting a display name, filtering it out, and then doing a script recompilation.
yield return SelectJobAwaitLoad("BurstInspectorGUITests.MyJob - (IJob)");
var win = EditorWindow.GetWindow<BurstInspectorGUI>();
win._searchFieldJobs.SetFocus();
yield return null;
// Simulate event for sending "a" as it will filter out the chosen job.
win.SendEvent(Event.KeyboardEvent("a"));
yield return null;
// Send RequestScriptReload to try and trigger the bug
// and wait for it to return
EditorUtility.RequestScriptReload();
yield return new WaitForDomainReload();
win = EditorWindow.GetWindow<BurstInspectorGUI>();
// Wait for it to actually initialize.
yield return _waitForInitialized;
Assert.IsTrue(win._initialized, "BurstInspector did not initialize properly after script reload");
win.Close();
}
[UnityTest]
public IEnumerator FontStyleDuringDomainReloadTest()
{
// Enter play mod
yield return new EnterPlayMode();
// Exit play mode
yield return new ExitPlayMode();
// Wait for the inspector to actually reload
yield return _waitForInitialized;
var inspectorWindow = EditorWindow.GetWindow<BurstInspectorGUI>();
#if UNITY_2023_1_OR_NEWER
Assert.AreEqual("RobotoMono-Regular", inspectorWindow._font.name);
#else
if (Application.platform == RuntimePlatform.WindowsEditor)
{
Assert.AreEqual("Consolas", inspectorWindow._font.name);
}
else
{
Assert.AreEqual("Courier", inspectorWindow._font.name);
}
#endif
inspectorWindow.Close();
}
[UnityTest]
public IEnumerator BranchHoverTest()
{
const string jobName = "BurstInspectorGUITests.MyJob - (IJob)";
yield return SelectJobAwaitLoad(jobName);
var info = SetupBranchTest();
var window = EditorWindow.GetWindow<BurstInspectorGUI>();
window.SendEvent(new Event() { type = EventType.MouseUp, mousePosition = info.mousePos });
var branch = window._textArea.hoveredBranch;
yield return null;
// Close window to avoid it sending more events
window.Close();
Assert.AreNotEqual(branch, default(LongTextArea.Branch), "Mouse is not hovering any branch.");
Assert.AreEqual(info.blockIdx.src, branch.Edge.OriginRef.BlockIndex);
Assert.AreEqual(info.blockIdx.dst, branch.Edge.LineRef.BlockIndex);
}
[UnityTest]
public IEnumerator ClickBranchTest()
{
const string jobName = "BurstInspectorGUITests.MyJob - (IJob)";
yield return SelectJobAwaitLoad(jobName);
var info = SetupBranchTest();
var window = EditorWindow.GetWindow<BurstInspectorGUI>();
// Seeing if clicking the branch takes us to a spot where branch is still hovered.
window.SendEvent(new Event() { type = EventType.MouseDown, mousePosition = info.mousePos });
var branch = window._textArea.hoveredBranch;
yield return null;
Assert.AreNotEqual(branch, default(LongTextArea.Branch), "Mouse is not hovering any branch.");
Assert.AreEqual(info.blockIdx.src, branch.Edge.OriginRef.BlockIndex);
Assert.AreEqual(info.blockIdx.dst, branch.Edge.LineRef.BlockIndex);
// Going back again.
window.SendEvent(new Event() { type = EventType.MouseDown, mousePosition = info.mousePos });
var branch2 = window._textArea.hoveredBranch;
yield return null;
Assert.AreNotEqual(branch2, default(LongTextArea.Branch), "Mouse is not hovering any branch.");
Assert.AreEqual(info.blockIdx.src, branch2.Edge.OriginRef.BlockIndex);
Assert.AreEqual(info.blockIdx.dst, branch2.Edge.LineRef.BlockIndex);
// Close window to avoid it sending more events.
window.Close();
}
private struct InfoThingy
{
public (int src, int dst) blockIdx;
public Vector2 mousePos;
}
private InfoThingy SetupBranchTest()
{
var window = EditorWindow.GetWindow<BurstInspectorGUI>();
// Make sure we use fontSize 12:
window.fontSizeIndex = 4;
window._textArea.Invalidate();
window.fixedFontStyle = null;
// Force window size to actually show branch arrows.
window.position = new Rect(window.position.x, window.position.y, 390, 405);
// Sending event to set the displayname, to avoid it resetting _scrollPos because of target change.
// Sending two events as initial guess for buttonbar width might be off, and it will be a precise calculation after second event.
window.SendEvent(new Event() { type = EventType.Repaint, mousePosition = new Vector2(window.position.width / 2f, window.position.height / 2f) });
window.SendEvent(new Event() { type = EventType.Repaint, mousePosition = new Vector2(window.position.width / 2f, window.position.height / 2f) });
// Setting up for the test.
// Finding an edge:
int dstBlockIdx = -1;
int srcBlockIdx = -1;
int line = -1;
for (int idx = 0; idx < window._burstDisassembler.Blocks.Count; idx++)
{
var block = window._burstDisassembler.Blocks[idx];
if (block.Edges != null)
{
foreach (var edge in block.Edges)
{
if (edge.Kind == BurstDisassembler.AsmEdgeKind.OutBound)
{
dstBlockIdx = edge.LineRef.BlockIndex;
line = window._textArea.blockLine[dstBlockIdx];
if ((dstBlockIdx == idx + 1 && edge.LineRef.LineIndex == 0)) // pointing to next line
{
continue;
}
srcBlockIdx = idx;
break;
}
}
if (srcBlockIdx != -1)
{
break;
}
}
}
if (srcBlockIdx == -1)
{
window.Close();
throw new System.Exception("No edges present in assembly for \"BurstInspectorGUITests.MyJob - (IJob)\"");
}
float dist = window._textArea.fontHeight * line;
float x = (window.position.width - (window._inspectorView.width + BurstInspectorGUI._scrollbarThickness)) + window._textArea.horizontalPad - (2*window._textArea.fontWidth);
// setting _ScrollPos so end of arrow is at bottom of screen, to make sure there is actually room for the scrolling.
window._scrollPos = new Vector2(0, dist - window._inspectorView.height * 0.93f);
// Setting mousePos to bottom of inspector view.
float topOfInspectorToBranchArrow = window._buttonOverlapInspectorView + 66.5f;//66.5f is the size of space over the treeview of different jobs.
var mousePos = new Vector2(x, topOfInspectorToBranchArrow + window._inspectorView.height - 0.5f*window._textArea.fontHeight);
return new InfoThingy() { blockIdx = (srcBlockIdx, dstBlockIdx), mousePos = mousePos};
}
public static IEnumerable ValueSource
{
get
{
yield return "BurstInspectorGUITests.MyJob - (IJob)";
yield return "BurstReflectionTests.GenericType`1.NestedGeneric`1[System.Int32,System.Single].TestMethod3()";
yield return "BurstReflectionTests.GenericType`1.NestedNonGeneric[System.Int32].TestMethod2()";
yield return "BurstReflectionTests.GenericParallelForJob`1[System.Int32] - (IJobParallelFor)";
}
}
[UnityTest]
public IEnumerator FocusCodeTest([ValueSource(nameof(ValueSource))] string job)
{
var win = EditorWindow.GetWindow<BurstInspectorGUI>();
yield return SelectJobAwaitLoad(job);
// Doesn't check that it's at the right spot, simply that it actually moves
Assert.IsFalse(Mathf.Approximately(win._inspectorView.y, 0f), "Inspector view did not change");
win.Close();
}
public static IEnumerable FocusCodeNotBranchesSource
{
get
{
yield return (1000, false);
yield return (563, true);
}
}
[UnityTest]
public IEnumerator FocusCodeNotBranchesTest([ValueSource(nameof(FocusCodeNotBranchesSource))] (int, bool) input)
{
var (width, doFocus) = input;
const string case1 = "BurstInspectorGUITests.BranchArrows - (IJob)";
const string case2 = "BurstInspectorGUITests.BranchArrows2 - (IJob)";
var win = EditorWindow.GetWindow<BurstInspectorGUI>();
// Force window size to be small enough for it to position it more to the right.
win.position = new Rect(win.position.x, win.position.y, width, 405);
// Test one where it should focus.
yield return SelectJobAwaitLoad(case1);
var val1 = win._inspectorView.x;
var result1 = Mathf.Approximately(val1, 0f);
// Test two with no focus.
win._assemblyKind = BurstInspectorGUI.AssemblyOptions.PlainWithDebugInformation;
yield return SelectJobAwaitLoad(case2);
var val2 = win._inspectorView.x;
var result2 = Mathf.Approximately(val2, 0f);
// Cleanup and test assertions.
win.Close();
Assert.AreEqual(doFocus, result1 == doFocus, $"Inspector view wrong.");
//Assert.IsFalse(result1, $"Inspector view did not change (Is {val1}).");
Assert.IsTrue(result2, $"Inspector view changed unexpectedly (Is {val2}).");
}
[UnityTest]
public IEnumerator SelectionNotOutsideBoundsTest()
{
void MoveSelection(BurstInspectorGUI gui, LongTextArea.Direction dir)
{
switch (dir)
{
case LongTextArea.Direction.Down:
gui._textArea.SelectAll();
gui._textArea.MoveSelectionDown(gui._inspectorView, true);
break;
case LongTextArea.Direction.Right:
gui._textArea.SelectAll();
gui._textArea.MoveSelectionRight(gui._inspectorView, true);
break;
case LongTextArea.Direction.Left:
gui._textArea.selectDragPos = Vector2.zero;
gui._textArea.MoveSelectionLeft(gui._inspectorView, true);
break;
case LongTextArea.Direction.Up:
gui._textArea.selectDragPos = Vector2.zero;
gui._textArea.MoveSelectionUp(gui._inspectorView, true);
break;
}
}
var win = EditorWindow.GetWindow<BurstInspectorGUI>();
yield return SelectJobAwaitLoad("BurstInspectorGUITests.MyJob - (IJob)");
try
{
foreach (var dir in Enum.GetValues(typeof(LongTextArea.Direction)))
{
MoveSelection(win, (LongTextArea.Direction)dir);
yield return null;
// Check that no errors have happened.
LogAssert.NoUnexpectedReceived();
}
}
finally
{
win.Close();
}
}
[UnityTest]
public IEnumerator SelectionInAssemblySearchBarTest()
{
yield return SelectJobAwaitLoad("BurstInspectorGUITests.MyJob - (IJob)");
var win = EditorWindow.GetWindow<BurstInspectorGUI>();
win._searchFieldAssembly.SetFocus();
yield return null;
// Send events to input some text.
win.SendEvent(Event.KeyboardEvent("a"));
win.SendEvent(Event.KeyboardEvent("b"));
yield return null;
// Move select some using keyboard input
win.SendEvent(Event.KeyboardEvent("left"));
win.SendEvent(Event.KeyboardEvent("#right"));
yield return null;
// Do a copy
var savedClipBoard = EditorGUIUtility.systemCopyBuffer;
win.SendEvent(SystemInfo.operatingSystemFamily == OperatingSystemFamily.MacOSX
? Event.KeyboardEvent("%c")
: Event.KeyboardEvent("^c"));
yield return null;
var copiedText = EditorGUIUtility.systemCopyBuffer;
EditorGUIUtility.systemCopyBuffer = savedClipBoard;
// Check that all is good
win.Close();
Assert.AreEqual("b", copiedText, "Copied text did not match expectation.");
}
[UnityTest]
public IEnumerator GoToNextSearchTargetTest()
{
var active = -1;
var nextActive = -1;
yield return SelectJobAwaitLoad("BurstInspectorGUITests.MyJob - (IJob)");
var win = EditorWindow.GetWindow<BurstInspectorGUI>();
try
{
win._searchFieldAssembly.SetFocus();
yield return null;
// Do a search in the text.
win.SendEvent(Event.KeyboardEvent("p"));
win.SendEvent(Event.KeyboardEvent("u"));
win.SendEvent(Event.KeyboardEvent("return"));
yield return null;
active = win._textArea._activeSearchHitIdx;
// Select next search target.
win.SendEvent(Event.KeyboardEvent("return"));
yield return null;
nextActive = win._textArea._activeSearchHitIdx;
}
finally
{
win.Close();
}
Assert.AreNotEqual(active, nextActive, "Active search target was not changed.");
}
[BurstCompile]
private struct MyJob : IJob
{
[ReadOnly]
public NativeArray<float> Inpút;
[WriteOnly]
public NativeArray<float> Output;
public void Execute()
{
float result = 0.0f;
for (int i = 0; i < Inpút.Length; i++)
{
result += Inpút[i];
}
Output[0] = result;
}
}
[BurstCompile]
private struct BranchArrows : IJob
{
[ReadOnly]
public NativeArray<float> Inpút;
[WriteOnly]
public NativeArray<float> Output;
public void Execute()
{
float result = 0.0f;
for (int i = 0; i < Inpút.Length; i++)
{
if (Inpút[i] < 10) { result += 1; }
else if (Inpút[i] < 20) { result += 2; }
else if (Inpút[i] < 30) { result += 3; }
else if (Inpút[i] < 40) { result += 4; }
else if (Inpút[i] < 50) { result += 5; }
else if (Inpút[i] < 60) { result += 6; }
else if (Inpút[i] < 70) { result += 7; }
else if (Inpút[i] < 80) { result += 8; }
else if (Inpút[i] < 90) { result += 9; }
result += Inpút[i];
}
Output[0] = result;
}
}
[BurstCompile]
private struct BranchArrows2 : IJob
{
[ReadOnly]
public NativeArray<float> Inpút;
[WriteOnly]
public NativeArray<float> Output;
public void Execute()
{
float result = 0.0f;
for (int i = 0; i < Inpút.Length; i++)
{
if (Inpút[i] < 10) { result += 1; }
else if (Inpút[i] < 20) { result += 2; }
else if (Inpút[i] < 30) { result += 3; }
else if (Inpút[i] < 40) { result += 4; }
else if (Inpút[i] < 50) { result += 5; }
else if (Inpút[i] < 60) { result += 6; }
else if (Inpút[i] < 70) { result += 7; }
else if (Inpút[i] < 80) { result += 8; }
else if (Inpút[i] < 90) { result += 9; }
result += Inpút[i];
}
Output[0] = result;
}
}
private class BurstDisassemblerWithCopy : BurstDisassembler
{
public List<AsmBlock> BlocksCopy;
public bool IsColoredCopy;
public List<AsmLine> LinesCopy;
public List<AsmToken> TokensCopy;
public BurstDisassemblerWithCopy(BurstDisassembler disassembler) : base()
{
IsColoredCopy = disassembler.IsColored;
BlocksCopy = new List<AsmBlock>(disassembler.Blocks);
LinesCopy = new List<AsmLine>(disassembler.Lines);
TokensCopy = new List<AsmToken>(disassembler.Tokens);
}
public bool Equals(BurstDisassembler other)
{
return IsColoredCopy == other.IsColored
&& BlocksCopy.SequenceEqual(other.Blocks)
&& LinesCopy.SequenceEqual(other.Lines)
&& TokensCopy.SequenceEqual(other.Tokens);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5c2988be6da139988b149bb3b60dc9ca
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,14 @@
using NUnit.Framework;
using Unity.Burst.Editor;
public class BurstMathTests
{
[Test]
[TestCase(1f, 3f, 3f, true)]
[TestCase(1f, 3f, 2f, true)]
[TestCase(1f, 3f, 3.00001f, false)]
public void WithinRangeTest(float start, float end, float num, bool res)
{
Assert.That(BurstMath.WithinRange(start, end, num), Is.EqualTo(res));
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6a647d1cecc83c4eaf9750af7ae6a1d0
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,280 @@
using System;
using NUnit.Framework;
using Unity.Burst.Editor;
using Unity.Burst;
using Unity.Jobs;
using System.Collections.Generic;
using System.Linq;
using UnityEditor.IMGUI.Controls;
public class BurstMethodTreeViewTests
{
/*
Consists of a tree looking like:
Root
BurstMethodTreeViewTests
Job1
TestMethod1
Job2
TestMethod1
Job3
TestMethod1(System.IntPtr)
Job4
TestMethod1
Job5 - (IJob)
*/
private BurstMethodTreeView _treeView;
private List<BurstCompileTarget> _targets;
private string _filter;
[SetUp]
public void SetUp()
{
_filter = string.Empty;
_treeView = new BurstMethodTreeView(
new TreeViewState(),
() => _filter,
() => (true, true)
);
string name = "TestMethod1";
_targets = new List<BurstCompileTarget>
{
new BurstCompileTarget(typeof(Job1).GetMethod(name), typeof(Job1), null, true),
new BurstCompileTarget(typeof(Job2).GetMethod(name), typeof(Job2), null, true),
new BurstCompileTarget(typeof(Job3).GetMethod(name), typeof(Job3), null, true),
new BurstCompileTarget(typeof(Job4).GetMethod(name), typeof(Job4), null, true),
new BurstCompileTarget(typeof(Job5).GetMethod("Execute"), typeof(Job5), typeof(IJob), false),
};
}
private void testEquality<T>(List<T> exp, List<T> act)
{
Assert.AreEqual(exp.Count, act.Count, "List length did not match.");
if (exp is List<TreeViewItem> elist && act is List<TreeViewItem> alist)
{
for (int i = 0; i < act.Count; i++)
{
Assert.IsTrue(alist[i].CompareTo(elist[i]) == 0,
$"expected: {elist[i].displayName}\nactual: {alist[i].displayName}");
}
}
else
{
for (int i = 0; i < act.Count; i++)
{
Assert.AreEqual(exp[i], act[i], $"list items did not match at index {i}");
}
}
}
[Test]
public void ProcessNewItemTest()
{
// Test for method containing . in name:
List<StringSlice> oldNameSpace = new List<StringSlice>();
int idJ = 0;
var (idn, newtarget, nameSpace) =
BurstMethodTreeView.ProcessNewItem(0, ++idJ, _targets[2], oldNameSpace);
Assert.AreEqual(-2, idn);
var expTargets = new List<TreeViewItem>
{
new TreeViewItem(-1, 0, $"{nameof(BurstMethodTreeViewTests)}"),
new TreeViewItem(-2,1,$"{nameof(Job3)}"),
new TreeViewItem(1, 2, "TestMethod1(System.IntPtr)")
};
var expNS = new List<StringSlice>
{
new StringSlice($"{nameof(BurstMethodTreeViewTests)}"),
new StringSlice($"{nameof(Job3)}")
};
testEquality(expTargets, newtarget);
testEquality(expNS, nameSpace);
// Test for method with . and with thing in namespace:
(idn, newtarget, nameSpace) = BurstMethodTreeView.ProcessNewItem(idn, ++idJ, _targets[2], nameSpace);
Assert.AreEqual(-2, idn); // no new non-leafs added.
expTargets = new List<TreeViewItem>
{
new TreeViewItem(2, 2, "TestMethod1(System.IntPtr)")
};
testEquality(expTargets, newtarget);
testEquality(expNS, nameSpace);
// Test with IJob instead of static method:
(idn, newtarget, nameSpace) = BurstMethodTreeView.ProcessNewItem(0, ++idJ, _targets[4], oldNameSpace);
Assert.AreEqual(-1, idn); // no new non-leafs added.
expTargets = new List<TreeViewItem>
{
new TreeViewItem(-1, 0, $"{nameof(BurstMethodTreeViewTests)}"),
new TreeViewItem(2, 2, $"{nameof(Job5)} - ({nameof(IJob)})")
};
expNS = new List<StringSlice> { new StringSlice($"{nameof(BurstMethodTreeViewTests)}"), };
testEquality(expTargets, newtarget);
testEquality(expNS, nameSpace);
}
private readonly (string, string[])[] _findNameSpacesTestInput =
{
("Burst.Compiler.IL.Tests.TestGenerics+GenericStructOuter2`2+GenericStructInner`1[[Burst.Compiler.IL.Tests.TestGenerics+MyValueData1, Unity.Burst.Tests.UnitTests, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null],[Burst.Compiler.IL.Tests.TestGenerics+MyValueData2, Unity.Burst.Tests.UnitTests, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null],[Burst.Compiler.IL.Tests.TestGenerics+MyValueData2, Unity.Burst.Tests.UnitTests, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]",
new []{ "Burst.Compiler.IL.Tests.TestGenerics", "GenericStructOuter2`2" })
};
[Test]
public void ExtractNameSpacesTest()
{
foreach (var (displayName, expectedNameSpaces) in _findNameSpacesTestInput)
{
var (nameSpaces, methodNameIdx) = BurstMethodTreeView.ExtractNameSpaces(displayName);
Assert.AreEqual(2, nameSpaces.Count, "Amount of namespaces found is wrong.");
int len = expectedNameSpaces.Length;
int expectedNSIdx = 0;
for (int i = 0; i < len; i++)
{
expectedNSIdx += expectedNameSpaces[i].Length + 1;
Assert.AreEqual(expectedNameSpaces[i], nameSpaces[i].ToString(), "Wrong namespace name retrieval.");
}
Assert.AreEqual(expectedNSIdx, methodNameIdx, "Wrong index of method name.");
}
}
[Test]
public void InitializeTest()
{
const int numNodes = 1 + 5; // Root + internal nodes.
_treeView.Initialize(_targets, false);
Assert.AreEqual(numNodes, _treeView.GetExpanded().Count, "All menu items should be expanded");
_treeView.SetExpanded(-2, false);
Assert.AreEqual(numNodes-1, _treeView.GetExpanded().Count, "First Job should be folded.");
_treeView.Initialize(_targets, true);
Assert.AreEqual(numNodes-1, _treeView.GetExpanded().Count);
}
[Test]
public void BuildRootTest()
{
_treeView.Initialize(_targets, false);
int dexp = 0;
int idNexp = -1;
int idLexp = 1;
foreach (TreeViewItem twi in _treeView.GetRows())
{
Assert.AreEqual(dexp++, twi.depth, $"Depth of item \"{twi}\" was wrong.");
if (dexp > 2) { dexp = 1; }
Assert.AreEqual(twi.hasChildren ? idNexp-- : idLexp++, twi.id, $"ID of item \"{twi}\" was wrong.");
}
}
[Test]
public void GetSelection()
{
_treeView.Initialize(_targets, false);
IList<int> actual = _treeView.GetSelection();
Assert.IsEmpty(actual, "Selection count wrong.");
_treeView.SelectAllRows();
actual = _treeView.GetSelection();
Assert.IsEmpty(actual, "Selection count wrong. Multirow selection not allowed.");
_treeView.SetSelection(new List<int> { -2 });
actual = _treeView.GetSelection();
Assert.AreEqual(0, actual.Count, "Selection count wrong. Label selection not allowed.");
_treeView.SetSelection(new List<int> { 1 });
actual = _treeView.GetSelection();
Assert.AreEqual(1, actual.Count, "Selection count wrong.");
Assert.AreEqual(1, actual[0], "Selection ID wrong.");
}
[Test]
public void TrySelectByDisplayNameTest()
{
const string name = "BurstMethodTreeViewTests.Job1.TestMethod1()";
_treeView.Initialize(_targets, false);
Assert.IsFalse(_treeView.TrySelectByDisplayName("Not present"));
Assert.IsTrue(_treeView.TrySelectByDisplayName(name), "TreeView Could not find method.");
}
[Test]
public void ProcessEntireTestProject()
{
// Make it filter out some jobs:
_filter = "Unity";
// Get all target jobs!
var assemblyList = BurstReflection.EditorAssembliesThatCanPossiblyContainJobs;
var result = BurstReflection.FindExecuteMethods(assemblyList, BurstReflectionAssemblyOptions.None).CompileTargets;
result.Sort((left, right) => string.Compare(left.GetDisplayName(), right.GetDisplayName(), StringComparison.Ordinal));
// Initialize the tree view:
_treeView.Initialize(result, false);
// Check if everything is good and ready:
var visibleJobs = _treeView.GetRows().Where(twi => !twi.hasChildren);
foreach (TreeViewItem twi in visibleJobs)
{
var actual = result[twi.id - 1];
var expected = twi.displayName;
Assert.IsTrue(actual.GetDisplayName().Contains(expected), $"Retrieved the wrong target base on id.\nGot \"{actual.GetDisplayName()}\"\nExpected \"{expected}\"");
}
}
[BurstCompile]
private struct Job1
{
[BurstCompile]
public static void TestMethod1() { }
}
[BurstCompile]
private struct Job2
{
[BurstCompile]
public static void TestMethod1() { }
}
[BurstCompile]
private struct Job3
{
[BurstCompile]
public static void TestMethod1(System.IntPtr ptr) { }
}
[BurstCompile]
private struct Job4
{
[BurstCompile]
public static void TestMethod1() { }
}
[BurstCompile]
private struct Job5 : IJob
{
public void Execute() { }
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dec061e3cbd730ce8117c465ee02452c
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,197 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using Unity.Burst;
using Unity.Burst.Editor;
using Unity.Jobs;
// This concrete generic type is only referenced in this assembly-level attribute,
// not anywhere else in code. This is to test that such types can be picked up
// by BurstReflection.
[assembly: BurstReflectionTests.RegisterGenericJobType(typeof(BurstReflectionTests.GenericParallelForJob<int>))]
[TestFixture]
public class BurstReflectionTests
{
private List<System.Reflection.Assembly> _assemblies;
[OneTimeSetUp]
public void SetUp()
{
_assemblies = BurstReflection.EditorAssembliesThatCanPossiblyContainJobs;
}
[Test]
public void CanGetAssemblyList()
{
Assert.That(_assemblies, Has.Count.GreaterThan(0));
}
[Test]
[TestCase("BurstReflectionTests.MyJob - (IJob)")]
[TestCase("BurstReflectionTests.MyGenericJob`1[System.Int32] - (IJob)")]
[TestCase("BurstReflectionTests.MyGenericJob2`1[System.Int32] - (BurstReflectionTests.IMyGenericJob`1[System.Int32])")]
[TestCase("BurstReflectionTests.MyGenericJob2`1[System.Double] - (BurstReflectionTests.IMyGenericJob`1[System.Double])")]
[TestCase("BurstReflectionTests.NonGenericType.TestMethod1()")]
[TestCase("BurstReflectionTests.GenericType`1[System.Int32].TestMethod1()")]
[TestCase("BurstReflectionTests.GenericType`1.NestedNonGeneric[System.Int32].TestMethod2()")]
[TestCase("BurstReflectionTests.GenericType`1.NestedGeneric`1[System.Int32,System.Single].TestMethod3()")]
[TestCase("BurstReflectionTests.MyGenericJobSeparateAssembly`1[System.Int32] - (BurstReflectionTestsSeparateAssembly.IMyGenericJobSeparateAssembly`1[System.Int32])")]
[TestCase("BurstReflectionTests.GenericParallelForJob`1[System.Int32] - (IJobParallelFor)")]
public void CanFindJobType(string compileTargetName)
{
var result = BurstReflection.FindExecuteMethods(_assemblies, BurstReflectionAssemblyOptions.None);
Assert.That(result.LogMessages, Is.Empty);
var compileTarget = result.CompileTargets.Find(x => x.GetDisplayName() == compileTargetName);
Assert.That(compileTarget, Is.Not.Null);
}
[BurstCompile]
private struct MyJob : IJob
{
public void Execute() { }
}
[BurstCompile]
private struct MyGenericJob<T> : IJob
{
public void Execute() { }
private static void UseConcreteType()
{
new MyGenericJob<int>().Execute();
}
}
[Unity.Jobs.LowLevel.Unsafe.JobProducerType(typeof(MyJobProducer<,>))]
private interface IMyGenericJob<T>
{
void Execute();
}
[BurstCompile]
private struct MyGenericJob2<T> : IMyGenericJob<T>
{
public void Execute() { }
private static void UseConcreteType()
{
new MyGenericJob2<int>().Execute();
}
}
private static class MyJobProducer<TJob, T>
{
public static void Execute(ref TJob job)
{
}
}
private struct MyGenericJob2Wrapper<T1, T2>
{
public MyGenericJob2<T2> Job;
private static void UseConcreteType()
{
var x = new MyGenericJob2Wrapper<float, double>();
x.Job.Execute();
}
}
[BurstCompile]
private struct NonGenericType
{
[BurstCompile]
public static void TestMethod1() { }
}
[BurstCompile]
private struct GenericType<T>
{
public static Action Delegate1;
public static Action Delegate2;
public static Action Delegate3;
[BurstCompile]
public static void TestMethod1() { }
[BurstCompile]
public class NestedNonGeneric
{
[BurstCompile]
public static void TestMethod2() { }
}
[BurstCompile]
public class NestedGeneric<T2>
{
[BurstCompile]
public static void TestMethod3() { }
}
private static void UseConcreteType()
{
// Store the delegates to static fields to avoid
// them being optimized-away in Release builds
Delegate1 = GenericType<int>.TestMethod1;
Delegate2 = GenericType<int>.NestedNonGeneric.TestMethod2;
Delegate3 = GenericType<int>.NestedGeneric<float>.TestMethod3;
}
}
[BurstCompile]
private struct MyGenericJobSeparateAssembly<T> : BurstReflectionTestsSeparateAssembly.IMyGenericJobSeparateAssembly<T>
{
public void Execute() { }
private static void UseConcreteType()
{
new MyGenericJobSeparateAssembly<int>().Execute();
}
}
[Test]
[TestCase("BurstReflectionTests.GenericMethodContainer.GenericMethod(T)")]
public void ExcludesGenericMethods(string compileTargetName)
{
var result = BurstReflection.FindExecuteMethods(_assemblies, BurstReflectionAssemblyOptions.None);
Assert.That(result.LogMessages, Is.Empty);
var compileTarget = result.CompileTargets.Find(x => x.GetDisplayName() == compileTargetName);
Assert.That(compileTarget, Is.Null);
}
[BurstCompile]
private static class GenericMethodContainer
{
[BurstCompile]
private static void GenericMethod<T>(T p)
{
}
}
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal class RegisterGenericJobTypeAttribute : Attribute
{
public Type ConcreteType;
public RegisterGenericJobTypeAttribute(Type type)
{
ConcreteType = type;
}
}
[BurstCompile]
internal struct GenericParallelForJob<T> : IJobParallelFor
where T : struct
{
public void Execute(int index)
{
throw new System.NotImplementedException();
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fde1edfe51dc3deaa53f0952dddf2b02
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,131 @@
using System;
using System.Text;
using System.Text.RegularExpressions;
using NUnit.Framework;
using Unity.Burst;
using Unity.Burst.Editor;
public class BurstStringSearchTests
{
private BurstDisassembler GetDisassemblerandText(string compileTargetName, int debugLvl, out string textToRender)
{
// Get target job assembly:
var assemblies = BurstReflection.EditorAssembliesThatCanPossiblyContainJobs;
var result = BurstReflection.FindExecuteMethods(assemblies, BurstReflectionAssemblyOptions.None);
var compileTarget = result.CompileTargets.Find(x => x.GetDisplayName() == compileTargetName);
Assert.IsTrue(compileTarget != default, $"Could not find compile target: {compileTarget}");
BurstDisassembler disassembler = new BurstDisassembler();
var options = new StringBuilder();
compileTarget.Options.TryGetOptions(compileTarget.JobType, true, out string defaultOptions);
options.AppendLine(defaultOptions);
// Disables the 2 current warnings generated from code (since they clutter up the inspector display)
// BC1370 - throw inside code not guarded with ConditionalSafetyCheck attribute
// BC1322 - loop intrinsic on loop that has been optimised away
options.AppendLine($"{BurstCompilerOptions.GetOption(BurstCompilerOptions.OptionDisableWarnings, "BC1370;BC1322")}");
options.AppendLine($"{BurstCompilerOptions.GetOption(BurstCompilerOptions.OptionTarget, BurstTargetCpu.X64_SSE4)}");
options.AppendLine($"{BurstCompilerOptions.GetOption(BurstCompilerOptions.OptionDebug, $"{debugLvl}")}");
var baseOptions = options.ToString();
var append = BurstInspectorGUI.GetDisasmOptions()[(int)DisassemblyKind.Asm];
// Setup disAssembler with the job:
compileTarget.RawDisassembly = BurstInspectorGUI.GetDisassembly(compileTarget.Method, baseOptions + append);
textToRender = compileTarget.RawDisassembly.TrimStart('\n');
return disassembler;
}
[Test]
public void FindLineNrTest()
{
// Load in a test text
var disassembler = GetDisassemblerandText("BurstInspectorGUITests.MyJob - (IJob)", 1, out string textToRender);
disassembler.Initialize(textToRender, BurstDisassembler.AsmKind.Intel, true, true);
var text = disassembler.GetOrRenderBlockToText(0);
// Call find line nr for:
// first line
// Around middle
// Last line
Assert.AreEqual(0, BurstStringSearch.FindLineNr(text, text.IndexOf('\n') - 1), "Couldn't find line 0");
Assert.AreEqual(2, BurstStringSearch.FindLineNr(text, text.IndexOf('\n', text.IndexOf('\n') + 1) + 1), "Couldn't find line in middle");
Assert.AreEqual(disassembler.Blocks[0].Length-1, BurstStringSearch.FindLineNr(text, text.Length-1), "Couldn't find last line");
}
[Test]
public void GetEndIndexOfPlainLineTest()
{
Assert.AreEqual(("This\nIs\nPerfect".Length-1, 6),
BurstStringSearch.GetEndIndexOfPlainLine("This\nIs\nPerfect", 2),
"Failed finding in well formed string");
const string text1 = "No line endings";
Assert.AreEqual((text1.Length-1, text1.Length-1),
BurstStringSearch.GetEndIndexOfPlainLine(text1, 0),
"Failed for missing line ending");
const string text2 = "No Line endings too many lines";
Assert.Throws<ArgumentOutOfRangeException>(() => BurstStringSearch.GetEndIndexOfPlainLine(text2, 2),
"Failed for missing line ending and too high line number");
const string text3 = "Line ending\n";
Assert.AreEqual((text3.Length-1, text3.Length-1),
BurstStringSearch.GetEndIndexOfPlainLine(text3, 0),
"Failed with line ending");
const string text4 = "Line ending too many lines\n";
Assert.Throws<ArgumentOutOfRangeException>(() => BurstStringSearch.GetEndIndexOfPlainLine(text4, 2),
"Failed with line endings and too high line number");
}
[Test]
public void FindMatchTest()
{
_ = GetDisassemblerandText("BurstInspectorGUITests.MyJob - (IJob)", 2, out var textToRender);
var expectedNormal = textToRender.IndexOf("def");
var tmp = Regex.Match(textToRender, @"\bdef\b");
var expectedWhole = tmp.Success ? tmp.Index : -1;
// Normal search
Assert.AreEqual((expectedNormal, 3),
BurstStringSearch.FindMatch(textToRender,
new SearchCriteria("def", false, false, false), default),
"Standard search failed"); // standard search: Match def in .endef
Assert.AreEqual((expectedWhole, 3),
BurstStringSearch.FindMatch(textToRender,
new SearchCriteria("def", false, true, false), default),
"Standard whole words failed"); // whole word search: Match def in .def
// Regex search
const RegexOptions opt = RegexOptions.CultureInvariant;
Assert.AreEqual((expectedNormal, 3),
BurstStringSearch.FindMatch(textToRender,
new SearchCriteria("def", false, false, true),
new Regex("def", opt | RegexOptions.IgnoreCase)),
"Regex search failed"); // standard search: Match def in .endef
Assert.AreEqual((expectedWhole, tmp.Success ? 3 : 0),
BurstStringSearch.FindMatch(textToRender,
new SearchCriteria(@"\bdef\b", false, true, true),
new Regex(@"\bdef\b", opt)),
"Regex whole word failed"); // whole word search: Match def in .def
// Across lines and blocks
Assert.AreEqual((12, 4),
BurstStringSearch.FindMatch(textToRender,
new SearchCriteria(@"t[\n]+..", false, false, true),
new Regex(@"t[\n]+..", opt | RegexOptions.IgnoreCase)),
"Regex across lines failed");
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2d306d2ea7783099abe61e86c377ca92
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,712 @@
using System;
using System.Collections;
using NUnit.Framework;
using UnityEngine;
using Unity.Jobs.LowLevel.Unsafe;
using UnityEngine.TestTools;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using System.Threading;
using System.Diagnostics;
using UnityEditor;
using Debug = UnityEngine.Debug;
using System.Text.RegularExpressions;
using Unity.Profiling;
using UnityEditor.Compilation;
using System.IO;
[TestFixture]
public class EditModeTest
{
private const int MaxIterations = 500;
[UnityTest]
public IEnumerator CheckBurstJobEnabledDisabled()
{
BurstCompiler.Options.EnableBurstCompileSynchronously = true;
try
{
foreach(var item in CheckBurstJobDisabled()) yield return item;
foreach(var item in CheckBurstJobEnabled()) yield return item;
}
finally
{
BurstCompiler.Options.EnableBurstCompilation = true;
}
}
private IEnumerable CheckBurstJobEnabled()
{
BurstCompiler.Options.EnableBurstCompilation = true;
yield return null;
using (var jobTester = new BurstJobTester2())
{
var result = jobTester.Calculate();
Assert.AreNotEqual(0.0f, result);
}
}
private IEnumerable CheckBurstJobDisabled()
{
BurstCompiler.Options.EnableBurstCompilation = false;
yield return null;
using (var jobTester = new BurstJobTester2())
{
var result = jobTester.Calculate();
Assert.AreEqual(0.0f, result);
}
}
[UnityTest]
public IEnumerator CheckJobWithNativeArray()
{
BurstCompiler.Options.EnableBurstCompileSynchronously = true;
BurstCompiler.Options.EnableBurstCompilation = true;
yield return null;
var job = new BurstJobTester2.MyJobCreatingAndDisposingNativeArray()
{
Length = 128,
Result = new NativeArray<int>(16, Allocator.TempJob)
};
var handle = job.Schedule();
handle.Complete();
try
{
Assert.AreEqual(job.Length, job.Result[0]);
}
finally
{
job.Result.Dispose();
}
}
#if UNITY_BURST_BUG_FUNCTION_POINTER_FIXED
[UnityTest]
public IEnumerator CheckBurstFunctionPointerException()
{
BurstCompiler.Options.EnableBurstCompileSynchronously = true;
BurstCompiler.Options.EnableBurstCompilation = true;
yield return null;
using (var jobTester = new BurstJobTester())
{
var exception = Assert.Throws<InvalidOperationException>(() => jobTester.CheckFunctionPointer());
StringAssert.Contains("Exception was thrown from a function compiled with Burst", exception.Message);
}
}
#endif
[BurstCompile(CompileSynchronously = true)]
private struct HashTestJob : IJob
{
public NativeArray<int> Hashes;
public void Execute()
{
Hashes[0] = BurstRuntime.GetHashCode32<int>();
Hashes[1] = TypeHashWrapper.GetIntHash();
Hashes[2] = BurstRuntime.GetHashCode32<TypeHashWrapper.SomeStruct<int>>();
Hashes[3] = TypeHashWrapper.GetGenericHash<int>();
}
}
[Test]
public static void TestTypeHash()
{
HashTestJob job = new HashTestJob
{
Hashes = new NativeArray<int>(4, Allocator.TempJob)
};
job.Schedule().Complete();
var hash0 = job.Hashes[0];
var hash1 = job.Hashes[1];
var hash2 = job.Hashes[2];
var hash3 = job.Hashes[3];
job.Hashes.Dispose();
Assert.AreEqual(hash0, hash1, "BurstRuntime.GetHashCode32<int>() has returned two different hashes");
Assert.AreEqual(hash2, hash3, "BurstRuntime.GetHashCode32<SomeStruct<int>>() has returned two different hashes");
}
[UnityTest]
public IEnumerator CheckSafetyChecksWithDomainReload()
{
{
var job = new SafetyCheckJobWithDomainReload();
{
// Run with safety-checks true
BurstCompiler.Options.EnableBurstSafetyChecks = true;
job.Result = new NativeArray<int>(1, Allocator.TempJob);
try
{
var handle = job.Schedule();
handle.Complete();
Assert.AreEqual(2, job.Result[0]);
}
finally
{
job.Result.Dispose();
}
}
{
// Run with safety-checks false
BurstCompiler.Options.EnableBurstSafetyChecks = false;
job.Result = new NativeArray<int>(1, Allocator.TempJob);
bool hasException = false;
try
{
var handle = job.Schedule();
handle.Complete();
Assert.AreEqual(1, job.Result[0]);
}
catch
{
hasException = true;
throw;
}
finally
{
job.Result.Dispose();
if (hasException)
{
BurstCompiler.Options.EnableBurstSafetyChecks = true;
}
}
}
}
// Ask for domain reload
EditorUtility.RequestScriptReload();
// Wait for the domain reload to be completed
yield return new WaitForDomainReload();
{
// The safety checks should have been disabled by the previous code
Assert.False(BurstCompiler.Options.EnableBurstSafetyChecks);
// Restore safety checks
BurstCompiler.Options.EnableBurstSafetyChecks = true;
}
}
[BurstCompile(CompileSynchronously = true)]
private struct DebugLogJob : IJob
{
public int Value;
public void Execute()
{
UnityEngine.Debug.Log($"This is a string logged from a job with burst with the following {Value}");
}
}
[Test]
public static void TestDebugLog()
{
var job = new DebugLogJob
{
Value = 256
};
job.Schedule().Complete();
}
[BurstCompile(CompileSynchronously = true, Debug = true)]
struct DebugLogErrorJob : IJob
{
public void Execute()
{
UnityEngine.Debug.LogError("X");
}
}
[UnityTest]
public IEnumerator DebugLogError()
{
LogAssert.Expect(LogType.Error, "X");
var jobData = new DebugLogErrorJob();
jobData.Run();
yield return null;
}
[BurstCompile(CompileSynchronously = true)]
private struct SafetyCheckJobWithDomainReload : IJob
{
public NativeArray<int> Result;
public void Execute()
{
Result[0] = 1;
SetResultWithSafetyChecksOnly();
}
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
private void SetResultWithSafetyChecksOnly()
{
Result[0] = 2;
}
}
[Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
private static void SafelySetSomeBool(ref bool b)
{
b = true;
}
[BurstCompile(DisableSafetyChecks = false)]
private struct EnabledSafetyChecksJob : IJob
{
[WriteOnly] public NativeArray<int> WasHit;
public void Execute()
{
var b = false;
SafelySetSomeBool(ref b);
WasHit[0] = b ? 1 : 0;
}
}
[BurstCompile(DisableSafetyChecks = true)]
private struct DisabledSafetyChecksJob : IJob
{
[WriteOnly] public NativeArray<int> WasHit;
public void Execute()
{
var b = false;
SafelySetSomeBool(ref b);
WasHit[0] = b ? 1 : 0;
}
}
[UnityTest]
public IEnumerator CheckSafetyChecksOffGloballyAndOnInJob()
{
BurstCompiler.Options.EnableBurstSafetyChecks = false;
BurstCompiler.Options.ForceEnableBurstSafetyChecks = false;
yield return null;
var job = new EnabledSafetyChecksJob()
{
WasHit = new NativeArray<int>(1, Allocator.TempJob)
};
job.Schedule().Complete();
try
{
// Safety checks are off globally which overwrites the job having safety checks on.
Assert.AreEqual(0, job.WasHit[0]);
}
finally
{
job.WasHit.Dispose();
}
}
[UnityTest]
public IEnumerator CheckSafetyChecksOffGloballyAndOffInJob()
{
BurstCompiler.Options.EnableBurstSafetyChecks = false;
BurstCompiler.Options.ForceEnableBurstSafetyChecks = false;
yield return null;
var job = new DisabledSafetyChecksJob()
{
WasHit = new NativeArray<int>(1, Allocator.TempJob)
};
job.Schedule().Complete();
try
{
// Safety checks are off globally and off in job.
Assert.AreEqual(0, job.WasHit[0]);
}
finally
{
job.WasHit.Dispose();
}
}
[UnityTest]
public IEnumerator CheckSafetyChecksOnGloballyAndOnInJob()
{
BurstCompiler.Options.EnableBurstSafetyChecks = true;
BurstCompiler.Options.ForceEnableBurstSafetyChecks = false;
yield return null;
var job = new EnabledSafetyChecksJob()
{
WasHit = new NativeArray<int>(1, Allocator.TempJob)
};
job.Schedule().Complete();
try
{
// Safety checks are on globally and on in job.
Assert.AreEqual(1, job.WasHit[0]);
}
finally
{
job.WasHit.Dispose();
}
}
[UnityTest]
public IEnumerator CheckSafetyChecksOnGloballyAndOffInJob()
{
BurstCompiler.Options.EnableBurstSafetyChecks = true;
BurstCompiler.Options.ForceEnableBurstSafetyChecks = false;
yield return null;
var job = new DisabledSafetyChecksJob()
{
WasHit = new NativeArray<int>(1, Allocator.TempJob)
};
job.Schedule().Complete();
try
{
// Safety checks are on globally but off in job.
Assert.AreEqual(0, job.WasHit[0]);
}
finally
{
job.WasHit.Dispose();
}
}
[UnityTest]
public IEnumerator CheckForceSafetyChecksWorks()
{
BurstCompiler.Options.ForceEnableBurstSafetyChecks = true;
yield return null;
var job = new DisabledSafetyChecksJob()
{
WasHit = new NativeArray<int>(1, Allocator.TempJob)
};
job.Schedule().Complete();
try
{
// Even though the job has set disabled safety checks, the menu item 'Force On'
// has been set which overrides any other requested behaviour.
Assert.AreEqual(1, job.WasHit[0]);
}
finally
{
job.WasHit.Dispose();
}
}
[UnityTest]
public IEnumerator CheckSharedStaticWithDomainReload()
{
// Check that on a first access, SharedStatic is always empty
AssertTestSharedStaticEmpty();
// Fill with some data
TestSharedStatic.SharedValue.Data = new TestSharedStatic(1, 2, 3, 4);
Assert.AreEqual(1, TestSharedStatic.SharedValue.Data.Value1);
Assert.AreEqual(2, TestSharedStatic.SharedValue.Data.Value2);
Assert.AreEqual(3, TestSharedStatic.SharedValue.Data.Value3);
Assert.AreEqual(4, TestSharedStatic.SharedValue.Data.Value4);
// Ask for domain reload
EditorUtility.RequestScriptReload();
// Wait for the domain reload to be completed
yield return new WaitForDomainReload();
// Make sure that after a domain reload everything is initialized back to zero
AssertTestSharedStaticEmpty();
}
private static void AssertTestSharedStaticEmpty()
{
Assert.AreEqual(0, TestSharedStatic.SharedValue.Data.Value1);
Assert.AreEqual(0, TestSharedStatic.SharedValue.Data.Value2);
Assert.AreEqual(0, TestSharedStatic.SharedValue.Data.Value3);
Assert.AreEqual(0, TestSharedStatic.SharedValue.Data.Value4);
}
private struct TestSharedStatic
{
public static readonly SharedStatic<TestSharedStatic> SharedValue = SharedStatic<TestSharedStatic>.GetOrCreate<TestSharedStatic>();
public TestSharedStatic(int value1, long value2, long value3, long value4)
{
Value1 = value1;
Value2 = value2;
Value3 = value3;
Value4 = value4;
}
public int Value1;
public long Value2;
public long Value3;
public long Value4;
}
static EditModeTest()
{
// UnityEngine.Debug.Log("Domain Reload");
}
[BurstCompile]
private static class FunctionPointers
{
public delegate int SafetyChecksDelegate();
[BurstCompile(DisableSafetyChecks = false)]
public static int WithSafetyChecksEnabled()
{
var b = false;
SafelySetSomeBool(ref b);
return b ? 1 : 0;
}
[BurstCompile(DisableSafetyChecks = true)]
public static int WithSafetyChecksDisabled()
{
var b = false;
SafelySetSomeBool(ref b);
return b ? 1 : 0;
}
}
[UnityTest]
public IEnumerator CheckSafetyChecksOffGloballyAndOffInFunctionPointer()
{
BurstCompiler.Options.EnableBurstSafetyChecks = false;
BurstCompiler.Options.ForceEnableBurstSafetyChecks = false;
yield return null;
var funcPtr = BurstCompiler.CompileFunctionPointer<FunctionPointers.SafetyChecksDelegate>(FunctionPointers.WithSafetyChecksDisabled);
// Safety Checks are off globally and off in the job.
Assert.AreEqual(0, funcPtr.Invoke());
}
[UnityTest]
public IEnumerator CheckSafetyChecksOffGloballyAndOnInFunctionPointer()
{
BurstCompiler.Options.EnableBurstSafetyChecks = false;
BurstCompiler.Options.ForceEnableBurstSafetyChecks = false;
yield return null;
var funcPtr = BurstCompiler.CompileFunctionPointer<FunctionPointers.SafetyChecksDelegate>(FunctionPointers.WithSafetyChecksEnabled);
// Safety Checks are off globally and on in job, but the global setting takes precedence.
Assert.AreEqual(0, funcPtr.Invoke());
}
[UnityTest]
public IEnumerator CheckSafetyChecksOnGloballyAndOffInFunctionPointer()
{
BurstCompiler.Options.EnableBurstSafetyChecks = true;
BurstCompiler.Options.ForceEnableBurstSafetyChecks = false;
yield return null;
var funcPtr = BurstCompiler.CompileFunctionPointer<FunctionPointers.SafetyChecksDelegate>(FunctionPointers.WithSafetyChecksDisabled);
// Safety Checks are on globally and off in the job, so the job takes predence.
Assert.AreEqual(0, funcPtr.Invoke());
}
[UnityTest]
public IEnumerator CheckSafetyChecksOnGloballyAndOnInFunctionPointer()
{
BurstCompiler.Options.EnableBurstSafetyChecks = true;
BurstCompiler.Options.ForceEnableBurstSafetyChecks = false;
yield return null;
var funcPtr = BurstCompiler.CompileFunctionPointer<FunctionPointers.SafetyChecksDelegate>(FunctionPointers.WithSafetyChecksEnabled);
// Safety Checks are on globally and on in the job.
Assert.AreEqual(1, funcPtr.Invoke());
}
[UnityTest]
public IEnumerator CheckFunctionPointerForceSafetyChecksWorks()
{
BurstCompiler.Options.ForceEnableBurstSafetyChecks = true;
yield return null;
var funcPtr = BurstCompiler.CompileFunctionPointer<FunctionPointers.SafetyChecksDelegate>(FunctionPointers.WithSafetyChecksDisabled);
// Even though the job has set disabled safety checks, the menu item 'Force On'
// has been set which overrides any other requested behaviour.
Assert.AreEqual(1, funcPtr.Invoke());
}
[BurstCompile(CompileSynchronously = true)]
private struct DebugDrawLineJob : IJob
{
public void Execute()
{
Debug.DrawLine(new Vector3(0, 0, 0), new Vector3(5, 0, 0), Color.green);
}
}
[Test]
public void TestDebugDrawLine()
{
var job = new DebugDrawLineJob();
job.Schedule().Complete();
}
[BurstCompile]
private static class ProfilerMarkerWrapper
{
private static readonly ProfilerMarker StaticMarker = new ProfilerMarker("TestStaticBurst");
[BurstCompile(CompileSynchronously = true)]
public static int CreateAndUseProfilerMarker(int start)
{
using (StaticMarker.Auto())
{
var p = new ProfilerMarker("TestBurst");
p.Begin();
var result = 0;
for (var i = start; i < start + 100000; i++)
{
result += i;
}
p.End();
return result;
}
}
}
private delegate int IntReturnIntDelegate(int param);
[Test]
public void TestCreateProfilerMarker()
{
var fp = BurstCompiler.CompileFunctionPointer<IntReturnIntDelegate>(ProfilerMarkerWrapper.CreateAndUseProfilerMarker);
fp.Invoke(5);
}
[BurstCompile]
private static class EnsureAssemblyBuilderDoesNotInvalidFunctionPointers
{
[BurstDiscard]
private static void MessOnManaged(ref int x) => x = 42;
[BurstCompile(CompileSynchronously = true)]
public static int WithBurst()
{
int x = 13;
MessOnManaged(ref x);
return x;
}
}
#if !UNITY_2023_1_OR_NEWER
[Test]
public void TestAssemblyBuilder()
{
var preBuilder = EnsureAssemblyBuilderDoesNotInvalidFunctionPointers.WithBurst();
Assert.AreEqual(13, preBuilder);
var tempDirectory = Path.GetTempPath();
var script = Path.Combine(tempDirectory, "BurstGeneratedAssembly.cs");
File.WriteAllText(script, @"
using Unity.Burst;
namespace BurstGeneratedAssembly
{
[BurstCompile]
public static class MyStuff
{
[BurstCompile(CompileSynchronously = true)]
public static int BurstedFunction(int x) => x + 1;
}
}
");
var dll = Path.Combine(tempDirectory, "BurstGeneratedAssembly.dll");
var builder = new AssemblyBuilder(dll, script);
Assert.IsTrue(builder.Build());
// Busy wait for the build to be done.
while (builder.status != AssemblyBuilderStatus.Finished)
{
Assert.AreEqual(preBuilder, EnsureAssemblyBuilderDoesNotInvalidFunctionPointers.WithBurst());
Thread.Sleep(10);
}
Assert.AreEqual(preBuilder, EnsureAssemblyBuilderDoesNotInvalidFunctionPointers.WithBurst());
}
#endif
[UnityTest]
public IEnumerator CheckChangingScriptOptimizationMode()
{
static void CheckBurstIsEnabled()
{
using (var jobTester = new BurstJobTester2())
{
var result = jobTester.Calculate();
Assert.AreNotEqual(0.0f, result);
}
}
CheckBurstIsEnabled();
// Switch scripting code optimization mode from Release to Debug.
Assert.AreEqual(CodeOptimization.Release, CompilationPipeline.codeOptimization);
CompilationPipeline.codeOptimization = CodeOptimization.Debug;
// Wait for the domain reload to be completed
yield return new WaitForDomainReload();
CheckBurstIsEnabled();
// Set scripting code optimization mode back to Release.
CompilationPipeline.codeOptimization = CodeOptimization.Release;
// Wait for the domain reload to be completed
yield return new WaitForDomainReload();
CheckBurstIsEnabled();
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 581193df6bcc393285dee7fedd436195
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,777 @@
using System;
using System.Reflection;
using NUnit.Framework;
using UnityEngine;
using UnityEditor;
using Unity.Burst.Editor;
using System.Text;
using Unity.Burst;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine.TestTools.Utils;
using System.Runtime.CompilerServices;
[TestFixture]
public class LongTextAreaTests
{
private LongTextArea _textArea;
[OneTimeSetUp]
public void SetUp()
{
_textArea = new LongTextArea();
}
[Test]
[TestCase("", " push rbp\n .seh_pushreg rbp\n", 7, true)]
[TestCase("<color=#CCCCCC>", " push rbp\n .seh_pushreg rbp\n", 25, true)]
[TestCase("<color=#d7ba7d>", " push rbp\n .seh_pushreg rbp\n", 21 + 15 + 8 + 15, true)]
[TestCase("", "\n# hulahop hejsa\n", 5, false)]
public void GetStartingColorTagTest(string tag, string text, int textIdx, bool syntaxHighlight)
{
var disAssembler = new BurstDisassembler();
_textArea.SetText("", text, true, disAssembler, disAssembler.Initialize(text, BurstDisassembler.AsmKind.Intel, true, syntaxHighlight));
if (!_textArea.CopyColorTags) _textArea.ChangeCopyMode();
Assert.That(_textArea.GetStartingColorTag(0, textIdx), Is.EqualTo(tag));
}
[Test]
[TestCase("", " push rbp\n .seh_pushreg rbp\n", 7, true)]
[TestCase("</color>", " push rbp\n .seh_pushreg rbp\n", 25, true)]
[TestCase("</color>", " push rbp\n .seh_pushreg rbp\n", 21 + 15 + 8 + 15, true)]
[TestCase("", " push rbp\n .seh_pushreg rbp\n", 14 + 15 + 8, true)]
[TestCase("", "\n# hulahop hejsa\n", 5, false)]
public void GetEndingColorTagTest(string tag, string text, int textIdx, bool syntaxHighlight)
{
var disAssembler = new BurstDisassembler();
_textArea.SetText("", text, true, disAssembler, disAssembler.Initialize(text, BurstDisassembler.AsmKind.Intel, true, syntaxHighlight));
if (!_textArea.CopyColorTags) _textArea.ChangeCopyMode();
Assert.That(_textArea.GetEndingColorTag(0, textIdx), Is.EqualTo(tag));
}
[Test]
[TestCase("<color=#FFFF00>hulahop</color> <color=#DCDCAA>hejsa</color>\n", 0, 16, 16)]
[TestCase("<color=#FFFF00>hulahop</color>\n <color=#DCDCAA>hejsa</color>\n", 1, 40, 9)]
[TestCase("<color=#FFFF00>hulahop</color>\n <color=#DCDCAA>hejsa</color>\n hej", 2, 67, 3)]
[TestCase("<color=#FFFF00>hulahop</color> <color=#DCDCAA>hejsa</color>", 0, 15, 15)]
[TestCase("\n <color=#4EC9B0>je</color> <color=#d4d4d4>.LBB11_4</color>", 1, 34, 33)]
// Test cases for when on enhanced text and not coloured.
[TestCase("hulahop hejsa\n", 0, 16, 16)]
[TestCase("hulahop\n hejsa\n", 1, 17, 9)]
[TestCase("hulahop\n hejsa\n hej", 2, 21, 3)]
[TestCase("hulahop hejsa", 0, 15, 15)]
public void GetEndIndexOfColoredLineTest(string text, int line, int resTotal, int resRel)
{
Assert.That(_textArea.GetEndIndexOfColoredLine(text, line), Is.EqualTo((resTotal, resRel)));
}
[Test]
[TestCase("hulahop hejsa\n", 0, 16, 16)]
[TestCase("hulahop\n hejsa\n", 1, 17, 9)]
[TestCase("hulahop\n hejsa\n hej", 2, 21, 3)]
[TestCase("hulahop hejsa", 0, 15, 15)]
[TestCase("\nhulahop hejsa", 1, 16, 15)]
public void GetEndIndexOfPlainLineTest(string text, int line, int resTotal, int resRel)
{
Assert.That(_textArea.GetEndIndexOfPlainLine(text, line), Is.EqualTo((resTotal, resRel)));
}
[Test]
[TestCase("<color=#FFFF00>hulahop</color>\n <color=#DCDCAA>hejsa</color>\n hej", 2, 2, 0)]
[TestCase("<color=#FFFF00>hulahop</color>\n <color=#DCDCAA>hejsa</color>\n hej", 1, 5, 15)]
[TestCase("<color=#FFFF00>hulahop</color> <color=#DCDCAA>hejsa</color>:", 0, 17, 46)]
public void BumpSelectionXByColortagTest(string text, int lineNum, int charsIn, int colourTagFiller)
{
var (idxTotal, idxRel) = _textArea.GetEndIndexOfColoredLine(text, lineNum);
Assert.That(_textArea.BumpSelectionXByColorTag(text, idxTotal - idxRel, charsIn), Is.EqualTo(charsIn + colourTagFiller));
}
[Test]
[TestCase(" push rbp\n .seh_pushreg rbp\n", false)]
[TestCase(" push rbp\n .seh_pushreg rbp\n", true)]
public void SelectAllTest(string text, bool useDisassembler)
{
if (useDisassembler)
{
var disAssembler = new BurstDisassembler();
_textArea.SetText("", text, true, disAssembler, disAssembler.Initialize(text, BurstDisassembler.AsmKind.Intel));
_textArea.LayoutEnhanced(GUIStyle.none, Rect.zero, true);
}
else
{
_textArea.SetText("", text, true, null, false);
}
_textArea.selectPos = new Vector2(2, 2);
// There is no inserted comments or similar in my test example, so finalAreaSize, should be equivalent for the two.
_textArea.finalAreaSize = new Vector2(7.5f * text.Length, 15.2f);
_textArea.SelectAll();
Assert.That(_textArea.selectPos, Is.EqualTo(Vector2.zero));
Assert.That(_textArea.selectDragPos, Is.EqualTo(new Vector2(7.5f * text.Length, 15.2f)));
if (!useDisassembler)
{
Assert.That(_textArea.textSelectionIdx, Is.EqualTo((0, text.Length)));
}
}
private BurstDisassembler GetDisassemblerandText(string compileTargetName, int debugLvl, out string textToRender)
{
// Get target job assembly:
var assemblies = BurstReflection.EditorAssembliesThatCanPossiblyContainJobs;
var result = BurstReflection.FindExecuteMethods(assemblies, BurstReflectionAssemblyOptions.None);
var compileTarget = result.CompileTargets.Find(x => x.GetDisplayName() == compileTargetName);
Assert.IsTrue(compileTarget != default, $"Could not find compile target: {compileTarget}");
BurstDisassembler disassembler = new BurstDisassembler();
var options = new StringBuilder();
compileTarget.Options.TryGetOptions(compileTarget.JobType, true, out string defaultOptions);
options.AppendLine(defaultOptions);
// Disables the 2 current warnings generated from code (since they clutter up the inspector display)
// BC1370 - throw inside code not guarded with ConditionalSafetyCheck attribute
// BC1322 - loop intrinsic on loop that has been optimised away
options.AppendLine($"{BurstCompilerOptions.GetOption(BurstCompilerOptions.OptionDisableWarnings, "BC1370;BC1322")}");
options.AppendLine($"{BurstCompilerOptions.GetOption(BurstCompilerOptions.OptionTarget, BurstTargetCpu.X64_SSE4)}");
options.AppendLine($"{BurstCompilerOptions.GetOption(BurstCompilerOptions.OptionDebug, $"{debugLvl}")}");
var baseOptions = options.ToString();
var append = BurstInspectorGUI.GetDisasmOptions()[(int)DisassemblyKind.Asm];
// Setup disAssembler with the job:
compileTarget.RawDisassembly = BurstInspectorGUI.GetDisassembly(compileTarget.Method, baseOptions + append);
textToRender = compileTarget.RawDisassembly.TrimStart('\n');
return disassembler;
}
[Test]
[TestCase(true, true, 2)]
[TestCase(true, true, 1)]
[TestCase(true, false, 2)]
[TestCase(true, false, 1)]
[TestCase(false, true, 2)]
[TestCase(false, true, 1)]
[TestCase(false, false, 2)]
[TestCase(false, false, 1)]
public void CopyAllTest(bool useDisassembler, bool coloured, int debugLvl)
{
// Get target job assembly:
var disassembler = new BurstDisassembler();
var thisPath = Path.GetDirectoryName(GetThisFilePath());
var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
if (useDisassembler)
{
_textArea.SetText("", textToRender, true, disassembler, disassembler.Initialize(textToRender, BurstDisassembler.AsmKind.Intel, true, coloured));
_textArea.ExpandAllBlocks();
var builder = new StringBuilder();
for (int i = 0; i < disassembler.Blocks.Count; i++)
{
builder.Append(disassembler.GetOrRenderBlockToText(i));
}
textToRender = builder.ToString();
}
else
{
_textArea.SetText("", textToRender, true, null, false);
}
_textArea.Layout(GUIStyle.none, _textArea.horizontalPad);
_textArea.SelectAll();
_textArea.DoSelectionCopy();
Assert.AreEqual(textToRender, EditorGUIUtility.systemCopyBuffer);
}
[Test]
public void CopyAllTextWithoutColorTagsTest()
{
// Setup:
var disassembler = new BurstDisassembler();
var thisPath = Path.GetDirectoryName(GetThisFilePath());
var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
_textArea.SetText("", textToRender, true, disassembler,
disassembler.Initialize(
textToRender,
BurstDisassembler.AsmKind.Intel));
_textArea.Layout(GUIStyle.none, _textArea.horizontalPad);
_textArea.LayoutEnhanced(GUIStyle.none, Rect.zero, true);
// Actual test to reproduce error:
_textArea.ChangeCopyMode();
_textArea.SelectAll();
Assert.DoesNotThrow(_textArea.DoSelectionCopy);
}
[Test]
public void CopyTextAfterSelectionMovedTest()
{
// Setup:
const bool sbm = true;
var wa = Rect.zero;
var disassembler = new BurstDisassembler();
var thisPath = Path.GetDirectoryName(GetThisFilePath());
var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
_textArea.SetText("", textToRender, true, disassembler,
disassembler.Initialize(
textToRender,
BurstDisassembler.AsmKind.Intel));
_textArea.Layout(GUIStyle.none, _textArea.horizontalPad);
_textArea.LayoutEnhanced(GUIStyle.none, Rect.zero, sbm);
// Actual test to reproduce error:
_textArea.ChangeCopyMode();
_textArea.MoveSelectionDown(wa, sbm);
_textArea.MoveSelectionDown(wa, sbm);
_textArea.MoveSelectionLeft(wa, sbm);
Assert.DoesNotThrow(_textArea.DoSelectionCopy);
_textArea.MoveSelectionRight(wa, sbm);
Assert.DoesNotThrow(_textArea.DoSelectionCopy);
}
[Test]
public void CopyTextIdenticalWithAndWithoutColorTags()
{
// We don't wanna go messing with the users system buffer. At least if user didn't break anything.
var savedSystemBuffer = EditorGUIUtility.systemCopyBuffer;
// Get target job assembly:
var disassembler = new BurstDisassembler();
var thisPath = Path.GetDirectoryName(GetThisFilePath());
var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
_textArea.SetText("", textToRender, true, disassembler,
disassembler.Initialize(
textToRender,
BurstDisassembler.AsmKind.Intel));
_textArea.Layout(GUIStyle.none, _textArea.horizontalPad);
_textArea.LayoutEnhanced(GUIStyle.none, Rect.zero, true);
for (var i=0; i<disassembler.Blocks[0].Length+50; i++) _textArea.MoveSelectionDown(Rect.zero, true);
_textArea.LayoutEnhanced(GUIStyle.none, Rect.zero, true);
_textArea.UpdateEnhancedSelectTextIdx(_textArea.horizontalPad);
_textArea.DoSelectionCopy();
var copiedText1 = EditorGUIUtility.systemCopyBuffer;
_textArea.ChangeCopyMode();
_textArea.DoSelectionCopy();
var copiedText2 = EditorGUIUtility.systemCopyBuffer;
var regx = new Regex(@"(<color=#[0-9A-Za-z]*>)|(</color>)");
if (!_textArea.CopyColorTags)
{
(copiedText1, copiedText2) = (copiedText2, copiedText1);
}
copiedText2 = regx.Replace(copiedText2, "");
EditorGUIUtility.systemCopyBuffer = savedSystemBuffer;
Assert.AreEqual(copiedText1, copiedText2,
"Copy with color tags did not match copy without " +
"(Color tags is removed from the copy to make it comparable with the color-tag-less copy).");
}
// Disabled due to https://jira.unity3d.com/browse/BUR-2207
[Test]
[TestCase(true)]
[TestCase(false)]
public void KeepingSelectionWhenMovingTest(bool useDisassembler)
{
const string jobName = "BurstInspectorGUITests.MyJob - (IJob)";
BurstDisassembler disassembler = new BurstDisassembler();
var thisPath = Path.GetDirectoryName(GetThisFilePath());
var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
Rect workingArea = new Rect();
if (useDisassembler)
{
_textArea.SetText(jobName, textToRender, true, disassembler, disassembler.Initialize(textToRender, BurstDisassembler.AsmKind.Intel));
_textArea.LayoutEnhanced(GUIStyle.none, workingArea, true);
}
else
{
_textArea.SetText(jobName, textToRender, false, null, false);
}
_textArea.Layout(GUIStyle.none, _textArea.horizontalPad);
Assert.IsFalse(_textArea.HasSelection);
Vector2 start = _textArea.selectDragPos;
if (useDisassembler) start.x = _textArea.horizontalPad + _textArea.fontWidth / 2;
// Horizontal movement:
_textArea.MoveSelectionRight(workingArea, true);
Assert.IsTrue(_textArea.HasSelection);
Assert.AreEqual(start + new Vector2(_textArea.fontWidth, 0), _textArea.selectDragPos);
_textArea.MoveSelectionLeft(workingArea, true);
Assert.IsTrue(_textArea.HasSelection);
Assert.AreEqual(start, _textArea.selectDragPos);
// Vertical movement:
_textArea.MoveSelectionDown(workingArea, true);
Assert.IsTrue(_textArea.HasSelection);
Assert.AreEqual(start + new Vector2(0, _textArea.fontHeight), _textArea.selectDragPos);
_textArea.MoveSelectionUp(workingArea, true);
Assert.IsTrue(_textArea.HasSelection);
Assert.AreEqual(start, _textArea.selectDragPos);
}
[Test]
public void GetFragNrFromBlockIdxTest()
{
var disassembler = new BurstDisassembler();
var thisPath = Path.GetDirectoryName(GetThisFilePath());
var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
_textArea.SetText("", textToRender, true, disassembler,
disassembler.Initialize(textToRender, BurstDisassembler.AsmKind.Intel, false, false));
var garbageVariable = 0f;
var numBlocks = disassembler.Blocks.Count;
// Want to get the last fragment possible
var expectedFragNr = 0;
for (var i = 0; i < _textArea.blocksFragmentsPlain.Length-1; i++)
{
expectedFragNr += _textArea.GetPlainFragments(i).Count;
}
Assert.AreEqual(expectedFragNr, _textArea.GetFragNrFromBlockIdx(numBlocks-1, 0, 0, ref garbageVariable));
Assert.AreEqual(3, _textArea.GetFragNrFromBlockIdx(3, 1, 1, ref garbageVariable));
}
[Test]
public void GetFragNrFromEnhancedTextIdxTest()
{
const string jobName = "BurstJobTester2.MyJob - (IJob)";
var disassembler = new BurstDisassembler();
var thisPath = Path.GetDirectoryName(GetThisFilePath());
var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
_textArea.SetText(jobName, textToRender, true, disassembler,
disassembler.Initialize(textToRender, BurstDisassembler.AsmKind.Intel, false, false));
var garbageVariable = 0f;
const int blockIdx = 2;
var fragments = _textArea.RecomputeFragmentsFromBlock(blockIdx);
var text = _textArea.GetText;
var expectedFrag = blockIdx + fragments.Count - 1;
var info = disassembler.BlockIdxs[blockIdx];
var extraFragLen = fragments.Count > 1
? fragments[0].text.Length + 1 // job only contains 2 fragments at max
: 0;
var idx = info.startIdx + extraFragLen + 1;
var expected = (expectedFrag, info.startIdx + extraFragLen);
var actual = _textArea.GetFragNrFromEnhancedTextIdx(idx, 0, 0, 0, ref garbageVariable);
Assert.AreEqual(expected, actual);
}
[Test]
[TestCase(true)]
[TestCase(false)]
public void SearchTextEnhancedTest(bool colored)
{
var disassembler = new BurstDisassembler();
var thisPath = Path.GetDirectoryName(GetThisFilePath());
var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
_textArea.SetText("", textToRender, true, disassembler, disassembler.Initialize(textToRender, BurstDisassembler.AsmKind.Intel, true, colored));
var workingArea = new Rect(0, 0, 10, 10);
_textArea.SearchText(new SearchCriteria(".Ltmp.:", true, false, true), new Regex(@"\.Ltmp.:"), ref workingArea);
Assert.AreEqual(10, _textArea.NrSearchHits);
// Check that they are filled out probably
int nr = 0;
foreach (var fragHits in _textArea.searchHits.Values)
{
foreach (var hit in fragHits)
{
Assert.AreEqual((0, 7, nr++), hit);
}
}
}
[Test]
public void SelectOnOneLineTest()
{
const string testCase = "\n<color=#d4d4d4>.Ltmp12</color>: ...";
var disassembler = new BurstDisassembler();
_textArea.SetText("", testCase, false, disassembler, disassembler.Initialize(testCase, BurstDisassembler.AsmKind.Intel));
// Set fontWidth and fontHeight
_textArea.Layout(GUIStyle.none, 20f);
// Set selection markers.
// Error happened when selection started at the lowest point of a line.
_textArea.selectPos = new Vector2(0, _textArea.fontHeight);
// Select further down to make sure it wont be switched with selectPos.
_textArea.selectDragPos = new Vector2(10 * _textArea.fontWidth, _textArea.fontHeight*2);
// Hopefully it wont throw anything
Assert.DoesNotThrow(() =>
_textArea.PrepareInfoForSelection(0, 0, _textArea.fontHeight,
new LongTextArea.Fragment() { text = testCase.TrimStart('\n'), lineCount = 1 },
_textArea.GetEndIndexOfColoredLine));
}
[Test]
public void GetLineHighlightTest()
{
const float hPad = 20f;
const int linePressed = 4 + 13;
// Get target job assembly:
var disassembler = new BurstDisassembler();
var thisPath = Path.GetDirectoryName(GetThisFilePath());
var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
// Set up dependencies for GetLineHighlight(.)
_textArea.SetText("", textToRender, true, disassembler,
disassembler.Initialize(
textToRender,
BurstDisassembler.AsmKind.Intel)
);
_textArea.Layout(GUIStyle.none, hPad);
_textArea.LayoutEnhanced(GUIStyle.none,
new Rect(0,0, _textArea.fontWidth*50,_textArea.fontHeight*50),
false
);
// Setup simple cache.
var cache = new LongTextArea.LineRegRectsCache();
var rect = _textArea.GetLineHighlight(ref cache, hPad, linePressed);
Assert.IsFalse(cache.IsRegistersCached(linePressed));
Assert.IsTrue(cache.IsLineHighlightCached(linePressed, false));
var expectedX = hPad;
var b = 0;
for (; b < disassembler.Blocks.Count; b++)
{
if (disassembler.Blocks[b].LineIndex > linePressed)
{
b--;
break;
}
}
var expectedY = (_textArea.blockLine[b] + (linePressed - disassembler.Blocks[b].LineIndex)) * _textArea.fontHeight + _textArea.fontHeight;
var lineStr = _textArea.GetLineString(disassembler.Lines[linePressed]);
var lineLen = lineStr.Length * _textArea.fontWidth;
var expected = new Rect(expectedX,
expectedY,
lineLen,
2f
);
var result = Mathf.Approximately(expectedX, rect.x)
&& Mathf.Approximately(expectedY, rect.y)
&& Mathf.Approximately(lineLen, rect.width)
&& Mathf.Approximately(2f, rect.height);
Assert.IsTrue(result, $"line highlight for \"{lineStr}\" was wrong.\nExpected: {expected}\nBut was: {rect}");
}
[Test]
public void GetRegRectsTest()
{
#region Initialize-test-states
const float hPad = 20f;
const int linePressed = 8 + 13;
// Get target job assembly:
var disassembler = new BurstDisassembler();
var thisPath = Path.GetDirectoryName(GetThisFilePath());
var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
// Set up dependencies for GetLineHighlight(.)
_textArea.SetText("", textToRender, true, disassembler,
disassembler.Initialize(
textToRender,
BurstDisassembler.AsmKind.Intel)
);
// Setting up variables to determine view size:
_textArea.Layout(GUIStyle.none, hPad);
_textArea.LayoutEnhanced(GUIStyle.none, Rect.zero, false);
#endregion
// Find the block index to put within view:
var blockIdx = disassembler.Blocks.Count/2;
for (; blockIdx > 0; blockIdx--)
{
// Take the first block where we know the lastLine will be in the next block.
if (!_textArea._folded[blockIdx + 1] && disassembler.Blocks[blockIdx].Length >= 5) break;
}
// Initialize states with regards to view:
_textArea.Layout(GUIStyle.none, hPad);
_textArea.LayoutEnhanced(GUIStyle.none,
new Rect(0,0, _textArea.fontWidth*100,_textArea.fontHeight*(_textArea.blockLine[blockIdx]+1)),
false
);
#region Function-to-test-call
var cache = new LongTextArea.LineRegRectsCache();
var registersUsed = new List<string> { "rbp", "rsp" };
var rects = _textArea.GetRegisterRects(hPad, ref cache, linePressed, registersUsed);
#endregion
#region Expected-variables
var lastLine = disassembler.Blocks[_textArea._renderBlockEnd+1].LineIndex + 4;
var expectedRbp =
(from pair in disassembler._registersUsedAtLine._linesRegisters.TakeWhile(x => x.Key < lastLine)
where pair.Value.Contains("rbp") && disassembler.Lines[pair.Key].Kind != BurstDisassembler.AsmLineKind.Directive
select pair);
var expectedRsp =
(from pair in disassembler._registersUsedAtLine._linesRegisters.TakeWhile(x => x.Key < lastLine)
where pair.Value.Contains("rsp") && disassembler.Lines[pair.Key].Kind != BurstDisassembler.AsmLineKind.Directive
select pair);
// Check that they are correctly placed!
// Only check the last here, as under development the "hardest" behaviour was from within the lowest blocks.
var lastRectLineIdx = expectedRbp.Last().Key;
var lastRectLine = disassembler.Lines[lastRectLineIdx];
var lastRectLineStr = _textArea.GetLineString(lastRectLine);
var expectedX = lastRectLineStr.Substring(0, lastRectLineStr.IndexOf("rbp")).Length * _textArea.fontWidth + hPad + 2f;
#endregion
Assert.IsTrue(cache.IsRegistersCached(linePressed), "Register Rect cache not probarly setup.");
Assert.IsFalse(cache.IsLineHighlightCached(linePressed, false), "Line highlight cache faultily set to cached.");
Assert.AreEqual(2, rects.Length, "Register Rect cache does not have correct number of registered registers.");
Assert.AreEqual(expectedRbp.Count(), rects[0].Count, "Did not find all \"rbp\" registers.");
Assert.AreEqual(expectedRsp.Count(), rects[1].Count, "Did not find all \"rsp\" registers.");
Assert.That(rects[0][rects[0].Count - 1].x, Is.EqualTo(expectedX).Using(FloatEqualityComparer.Instance),
"Wrong x position for last found \"rbp\" rect.");
// Note: Does not check Y position, as this is highly dependent on architecture, making it annoyingly hard
// to reason about.
}
[Test]
public void RegsRectCacheTest()
{
const float hPad = 20f;
const int linePressed = 8 + 13;
// Get target job assembly:
var disassembler = new BurstDisassembler();
var thisPath = Path.GetDirectoryName(GetThisFilePath());
var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
// Set up dependencies for GetLineHighlight(.)
_textArea.SetText("", textToRender, true, disassembler,
disassembler.Initialize(
textToRender,
BurstDisassembler.AsmKind.Intel)
);
_textArea.Layout(GUIStyle.none, hPad);
var yStart = 0f;
var yHeight = _textArea.fontHeight*44;
_textArea.LayoutEnhanced(GUIStyle.none,
new Rect(0,yStart, _textArea.fontWidth*100,yHeight),
false
);
var cache = new LongTextArea.LineRegRectsCache();
var registersUsed = new List<string> { "rbp", "rsp" };
var rects = _textArea.GetRegisterRects(hPad, ref cache, linePressed, registersUsed);
Assert.IsTrue(cache.IsRegistersCached(linePressed));
var cachedItems =
(from elm in rects
select elm.Count).Sum();
yStart = yHeight;
_textArea.Layout(GUIStyle.none, hPad);
_textArea.LayoutEnhanced(GUIStyle.none,
new Rect(0,yStart, _textArea.fontWidth*100,yHeight),
false
);
rects = _textArea.GetRegisterRects(hPad, ref cache, linePressed, registersUsed);
Assert.IsTrue(cache.IsRegistersCached(linePressed));
var cachedItems2 =
(from elm in rects
select elm.Count).Sum();
Assert.IsTrue(cachedItems2 >= cachedItems);
}
[Test]
[TestCase("\n xor r9d, r9d\n", "r9d")]
[TestCase("\n push edx rdx\n", "rdx")]
public void SameRegisterUsedTwiceTest(string line, string reg)
{
const float hPad = 20f;
const int linePressed = 0;
// Get target job assembly:
var disassembler = new BurstDisassembler();
// Set up dependencies for GetLineHighlight(.)
_textArea.SetText("", line, true, disassembler,
disassembler.Initialize(
line,
BurstDisassembler.AsmKind.Intel)
);
_textArea.Layout(GUIStyle.none, hPad);
var yStart = 0f;
var yHeight = _textArea.fontHeight;
_textArea.LayoutEnhanced(GUIStyle.none,
new Rect(0,yStart, _textArea.fontWidth*100,yHeight),
false
);
var cache = new LongTextArea.LineRegRectsCache();
var registersUsed = new List<string> { reg };
var rects = _textArea.GetRegisterRects(hPad, ref cache, linePressed, registersUsed);
Assert.IsTrue(cache.IsRegistersCached(linePressed));
Assert.IsTrue(rects.Length == 1);
Assert.IsTrue(rects[0].Count == 2, "Did not find exactly both registers.");
}
/// <summary>
/// This test should check whether line press information is cleared when it is necessary.
/// It does not check whether it is unnecessarily cleared.
/// </summary>
[Test]
public void ClearLinePressTest()
{
void SetupCache(float pad, int lineNr, ref LongTextArea.LineRegRectsCache cache, List<string> regsUsed)
{
_textArea._pressedLine = lineNr;
_ = _textArea.GetRegisterRects(pad, ref cache, lineNr, regsUsed);
_ = _textArea.GetLineHighlight(ref cache, pad, lineNr);
}
// Test setup:
var registersUsed = new List<string> { "rbp", "rsp" };
const float hPad = 20f;
const int linePressed = 4 + 13;
var disassembler = new BurstDisassembler();
var thisPath = Path.GetDirectoryName(GetThisFilePath());
Assert.NotNull(thisPath, "Could not retrieve path for current directory.");
var textToRender = File.ReadAllText(Path.Combine(thisPath, _burstJobPath));
// Set up dependencies for GetLineHighlight(.)
_textArea.SetText("", textToRender, true, disassembler,
disassembler.Initialize(
textToRender,
BurstDisassembler.AsmKind.Intel)
);
// Setting up variables to determine view size:
_textArea.Layout(GUIStyle.none, hPad);
_textArea.LayoutEnhanced(GUIStyle.none, Rect.zero, false);
var blockIdx = _textArea.GetLinesBlockIdx(linePressed);
_textArea.Layout(GUIStyle.none, hPad);
_textArea.LayoutEnhanced(GUIStyle.none,
new Rect(0,0, _textArea.fontWidth*100,_textArea.fontHeight*(_textArea.blockLine[blockIdx]+1)),
false);
void TestCache(bool isLineRect, bool isRect, bool isLine, string msg)
{
Assert.AreEqual(isLineRect,
_textArea._lineRegCache.IsLineHighlightCached(linePressed, _textArea._folded[blockIdx]),
msg + " Line highlight failed.");
Assert.AreEqual(isRect,
_textArea._lineRegCache.IsRegistersCached(linePressed),
msg + " Register cache failed.");
msg += " Line press failed.";
if (!isLine)
{
Assert.AreEqual(-1, _textArea._pressedLine, msg);
}
else
{
Assert.AreNotEqual(-1, _textArea._pressedLine, msg);
}
SetupCache(hPad, linePressed, ref _textArea._lineRegCache, registersUsed);
}
SetupCache(hPad, linePressed, ref _textArea._lineRegCache, registersUsed);
TestCache(true, true, true, "Initial setup failed.");
// Following changes should result in clearing everything, as assembly text might have changed:
// * Expand all.
_textArea.ExpandAllBlocks();
TestCache(false, false, false, "Expanding blocks failed.");
// * Focus code.
_textArea.FocusCodeBlocks();
TestCache(false, false, false, "Focusing code blocks failed.");
// * disassembly kind, Target change, Safety check changes, Assembly kind changes e.g. by amount of debug info.
_textArea.SetText("", textToRender, true, disassembler,
disassembler.Initialize(
textToRender,
BurstDisassembler.AsmKind.Intel)
);
TestCache(false, false, false, "Setting up new text failed.");
// Following changes should only result in Rec change clear, as line number still resembles same line:
// * Font size.
_textArea.Invalidate();
TestCache(false, false, true, "Changing font size failed.");
// * Show branch flow.
_textArea.LayoutEnhanced(GUIStyle.none,
new Rect(0,0, _textArea.fontWidth*100,_textArea.fontHeight*(_textArea.blockLine[blockIdx]+1)),
true);
TestCache(false, false, true, "Changing font size failed.");
// * Smell test (This will however clear everything as ´SetText()´ required).
// Hence tested in the cases for fill clear.
}
private static string GetThisFilePath([CallerFilePath] string path = null) => path;
private readonly string _burstJobPath = "burstTestTarget.txt";
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b866f2ae2314368d97e916270883416e
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fa45014e48e13a5ea49fd421043ee143
folderAsset: yes

View file

@ -0,0 +1,16 @@
public class BurstReflectionTestsSeparateAssembly
{
[Unity.Jobs.LowLevel.Unsafe.JobProducerType(typeof(MyJobProducerSeparateAssembly<,>))]
public interface IMyGenericJobSeparateAssembly<T>
{
void Execute();
}
private static class MyJobProducerSeparateAssembly<TJob, T>
{
public static void Execute(ref TJob job)
{
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9c07004be90d3814b9a09f7d08b26eb1
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,19 @@
{
"name": "SeparateAssembly",
"references": [
"Unity.Burst"
],
"includePlatforms": [],
"optionalUnityReferences": [
"TestAssemblies"
],
"excludePlatforms": [],
"allowUnsafeCode": true,
"overrideReferences": true,
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
"noEngineReferences": false
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3ce0cf2654ad3464aa58eb2e27f77f0d
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,16 @@
using Unity.Burst;
public static class TypeHashWrapper
{
public static int GetIntHash()
{
return BurstRuntime.GetHashCode32<int>();
}
public static int GetGenericHash<T>()
{
return BurstRuntime.GetHashCode32<SomeStruct<T>>();
}
public struct SomeStruct<T> { }
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 581a69eadade3f4985faa44d7b02aa3d
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,36 @@
using System;
using NUnit.Framework;
using Unity.Burst.Editor;
public class StringSliceTests
{
private const string _someText = "This is some text we are going to take StringSlice from.";
private const string _target = "StringSlice";
private readonly StringSlice _ssTarget = new StringSlice(_someText, _someText.IndexOf(_target, StringComparison.InvariantCulture), _target.Length);
[Test]
public void StringSliceStringRepresentationTest()
{
Assert.AreEqual(_target, _ssTarget.ToString());
Assert.AreEqual('S', _ssTarget[0]);
Assert.IsTrue(_ssTarget == new StringSlice(_target));
}
[Test]
public void StartsWithTest()
{
Assert.IsFalse(_ssTarget.StartsWith("This"));
Assert.IsTrue(_ssTarget.StartsWith("S"));
Assert.IsTrue(_ssTarget.StartsWith(_target));
}
[Test]
public void ContainsTest()
{
Assert.IsFalse(_ssTarget.Contains('T'));
Assert.IsFalse(_ssTarget.Contains('s'));
Assert.IsTrue(_ssTarget.Contains('S'));
Assert.IsTrue(_ssTarget.Contains('g'));
Assert.IsTrue(_ssTarget.Contains('e'));
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8361860cac3b3a12bc041994c9c1638c
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,28 @@
{
"name": "Unity.Burst.Editor.Tests",
"references": [
"Unity.Burst",
"Unity.Mathematics",
"Unity.Burst.Tests.UnitTests",
"SeparateAssembly",
"Unity.Burst.Editor"
],
"optionalUnityReferences": [
"TestAssemblies"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": true,
"overrideReferences": true,
"precompiledReferences": [
"nunit.framework.dll"
],
"autoReferenced": false,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
"noEngineReferences": false
}

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 15ce69d7d9d9370c9704e0797a0ab06b
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,662 @@
.text
.def @feat.00;
.scl 3;
.type 0;
.endef
.globl @feat.00
.set @feat.00, 0
.intel_syntax noprefix
.file "main"
.def burst.initialize;
.scl 2;
.type 32;
.endef
.globl burst.initialize
.p2align 4, 0x90
burst.initialize:
.Lfunc_begin0:
.seh_proc burst.initialize
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
.seh_endprologue
pop rbp
ret
.Lfunc_end0:
.seh_endproc
.def burst.initialize.externals;
.scl 2;
.type 32;
.endef
.globl burst.initialize.externals
.p2align 4, 0x90
burst.initialize.externals:
.Lfunc_begin1:
.seh_proc burst.initialize.externals
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
.seh_endprologue
pop rbp
ret
.Lfunc_end1:
.seh_endproc
.def burst.initialize.statics;
.scl 2;
.type 32;
.endef
.globl burst.initialize.statics
.p2align 4, 0x90
burst.initialize.statics:
.Lfunc_begin2:
.seh_proc burst.initialize.statics
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
.seh_endprologue
pop rbp
ret
.Lfunc_end2:
.seh_endproc
.def d675c2aa053244579b646ec09368a505;
.scl 2;
.type 32;
.endef
.globl d675c2aa053244579b646ec09368a505
.p2align 4, 0x90
d675c2aa053244579b646ec09368a505:
.Lfunc_begin3:
.seh_proc d675c2aa053244579b646ec09368a505
push rbp
.seh_pushreg rbp
sub rsp, 48
.seh_stackalloc 48
lea rbp, [rsp + 48]
.seh_setframe rbp, 48
.seh_endprologue
mov eax, dword ptr [rbp + 48]
mov dword ptr [rsp + 32], eax
call "Unity.Jobs.IJobExtensions.JobStruct`1<BurstInspectorGUITests.MyJob>.Execute(ref BurstInspectorGUITests.MyJob data, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) -> void_930e313844f708dd8e72e0cb41431524 from UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
nop
add rsp, 48
pop rbp
ret
.Lfunc_end3:
.seh_endproc
.def "Unity.Jobs.IJobExtensions.JobStruct`1<BurstInspectorGUITests.MyJob>.Execute(ref BurstInspectorGUITests.MyJob data, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) -> void_930e313844f708dd8e72e0cb41431524 from UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
.scl 3;
.type 32;
.endef
.p2align 4, 0x90
"Unity.Jobs.IJobExtensions.JobStruct`1<BurstInspectorGUITests.MyJob>.Execute(ref BurstInspectorGUITests.MyJob data, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) -> void_930e313844f708dd8e72e0cb41431524 from UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null":
.Lfunc_begin4:
.cv_func_id 0
.cv_file 1 "C:\\UnitySrc\\unity\\Runtime\\Jobs\\Managed\\IJob.cs"
.cv_loc 0 1 57 0
.seh_proc "Unity.Jobs.IJobExtensions.JobStruct`1<BurstInspectorGUITests.MyJob>.Execute(ref BurstInspectorGUITests.MyJob data, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) -> void_930e313844f708dd8e72e0cb41431524 from UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
push rbp
.seh_pushreg rbp
mov rbp, rsp
.seh_setframe rbp, 0
.seh_endprologue
.Ltmp0:
.cv_file 2 "C:\\UnitySrc\\unity\\Runtime\\Export\\NativeArray\\NativeArray.cs"
.cv_inline_site_id 1 within 0 inlined_at 1 58 0
.cv_file 3 "C:\\UnitySrc\\burst\\src\\com.unity.burst\\Tests\\Editor\\BurstInspectorGUITests.cs"
.cv_inline_site_id 2 within 1 inlined_at 3 393 0
.cv_loc 2 2 130 0
mov eax, dword ptr [rcx + 8]
test rax, rax
.Ltmp1:
.cv_loc 1 3 393 0
je .LBB4_1
mov rdx, qword ptr [rcx]
vxorps xmm0, xmm0, xmm0
.p2align 4, 0x90
.LBB4_3:
.cv_loc 1 3 395 0
vaddss xmm0, xmm0, dword ptr [rdx]
.cv_loc 1 3 393 0
add rdx, 4
dec rax
jne .LBB4_3
jmp .LBB4_4
.LBB4_1:
vxorps xmm0, xmm0, xmm0
.LBB4_4:
.Ltmp2:
.cv_inline_site_id 3 within 1 inlined_at 3 397 0
.cv_loc 3 2 194 0
mov rax, qword ptr [rcx + 48]
vmovss dword ptr [rax], xmm0
.Ltmp3:
.cv_loc 0 1 59 0
pop rbp
ret
.Ltmp4:
.Lfunc_end4:
.seh_endproc
.section .drectve,"yn"
.ascii " /EXPORT:\"burst.initialize\""
.ascii " /EXPORT:\"burst.initialize.externals\""
.ascii " /EXPORT:\"burst.initialize.statics\""
.ascii " /EXPORT:d675c2aa053244579b646ec09368a505"
.section .debug$S,"dr"
.p2align 2
.long 4
.long 241
.long .Ltmp6-.Ltmp5
.Ltmp5:
.short .Ltmp8-.Ltmp7
.Ltmp7:
.short 4353
.long 0
.byte 0
.p2align 2
.Ltmp8:
.short .Ltmp10-.Ltmp9
.Ltmp9:
.short 4412
.long 0
.short 208
.short 0
.short 0
.short 91
.short 0
.short 14006
.short 0
.short 0
.short 0
.asciz "Burst 0.0.91.0 (Frontend Version : 040e20f6-d3e4-45d8-b45b-06c6d673cedb)"
.p2align 2
.Ltmp10:
.Ltmp6:
.p2align 2
.long 246
.long .Ltmp12-.Ltmp11
.Ltmp11:
.long 0
.long 4112
.cv_filechecksumoffset 3
.long 391
.long 4115
.cv_filechecksumoffset 2
.long 129
.long 4118
.cv_filechecksumoffset 2
.long 192
.Ltmp12:
.p2align 2
.long 241
.long .Ltmp14-.Ltmp13
.Ltmp13:
.short .Ltmp16-.Ltmp15
.Ltmp15:
.short 4422
.long 0
.long 0
.long 0
.long .Lfunc_end4-"Unity.Jobs.IJobExtensions.JobStruct`1<BurstInspectorGUITests.MyJob>.Execute(ref BurstInspectorGUITests.MyJob data, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) -> void_930e313844f708dd8e72e0cb41431524 from UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
.long 0
.long 0
.long 4126
.secrel32 "Unity.Jobs.IJobExtensions.JobStruct`1<BurstInspectorGUITests.MyJob>.Execute(ref BurstInspectorGUITests.MyJob data, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) -> void_930e313844f708dd8e72e0cb41431524 from UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
.secidx "Unity.Jobs.IJobExtensions.JobStruct`1<BurstInspectorGUITests.MyJob>.Execute(ref BurstInspectorGUITests.MyJob data, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) -> void_930e313844f708dd8e72e0cb41431524 from UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
.byte 0
.asciz "Unity.Jobs.IJobExtensions.JobStruct`1<BurstInspectorGUITests.MyJob>.Execute(ref BurstInspectorGUITests.MyJob data, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) -> void_930e313844f708dd8e72e0cb41431524 from UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
.p2align 2
.Ltmp16:
.short .Ltmp18-.Ltmp17
.Ltmp17:
.short 4114
.long 8
.long 0
.long 0
.long 0
.long 0
.short 0
.long 1212416
.p2align 2
.Ltmp18:
.short .Ltmp20-.Ltmp19
.Ltmp19:
.short 4429
.long 0
.long 0
.long 4112
.cv_inline_linetable 1 3 391 .Lfunc_begin4 .Lfunc_end4
.p2align 2
.Ltmp20:
.short .Ltmp22-.Ltmp21
.Ltmp21:
.short 4429
.long 0
.long 0
.long 4115
.cv_inline_linetable 2 2 129 .Lfunc_begin4 .Lfunc_end4
.p2align 2
.Ltmp22:
.short 2
.short 4430
.short .Ltmp24-.Ltmp23
.Ltmp23:
.short 4429
.long 0
.long 0
.long 4118
.cv_inline_linetable 3 2 192 .Lfunc_begin4 .Lfunc_end4
.p2align 2
.Ltmp24:
.short 2
.short 4430
.short 2
.short 4430
.short 2
.short 4431
.Ltmp14:
.p2align 2
.cv_linetable 0, "Unity.Jobs.IJobExtensions.JobStruct`1<BurstInspectorGUITests.MyJob>.Execute(ref BurstInspectorGUITests.MyJob data, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) -> void_930e313844f708dd8e72e0cb41431524 from UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", .Lfunc_end4
.long 241
.long .Ltmp26-.Ltmp25
.Ltmp25:
.short .Ltmp28-.Ltmp27
.Ltmp27:
.short 4360
.long 4099
.asciz "BurstInspectorGUITests/MyJob"
.p2align 2
.Ltmp28:
.short .Ltmp30-.Ltmp29
.Ltmp29:
.short 4360
.long 4104
.asciz "Unity.Collections.NativeArray`1<System.Single>"
.p2align 2
.Ltmp30:
.short .Ltmp32-.Ltmp31
.Ltmp31:
.short 4360
.long 4107
.asciz "Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle"
.p2align 2
.Ltmp32:
.short .Ltmp34-.Ltmp33
.Ltmp33:
.short 4360
.long 4124
.asciz "Unity.Jobs.LowLevel.Unsafe.JobRanges"
.p2align 2
.Ltmp34:
.Ltmp26:
.p2align 2
.cv_filechecksums
.cv_stringtable
.long 241
.long .Ltmp36-.Ltmp35
.Ltmp35:
.short .Ltmp38-.Ltmp37
.Ltmp37:
.short 4428
.long 4130
.p2align 2
.Ltmp38:
.Ltmp36:
.p2align 2
.section .debug$T,"dr"
.p2align 2
.long 4
.short 0x32
.short 0x1505
.short 0x0
.short 0x80
.long 0x0
.long 0x0
.long 0x0
.short 0x0
.asciz "BurstInspectorGUITests/MyJob"
.byte 241
.short 0x46
.short 0x1505
.short 0x0
.short 0x80
.long 0x0
.long 0x0
.long 0x0
.short 0x0
.asciz "Unity.Collections.NativeArray`1<System.Single>"
.byte 243
.byte 242
.byte 241
.short 0x2a
.short 0x1203
.short 0x150d
.short 0x3
.long 0x1001
.short 0x0
.asciz "Inp\303\272t"
.byte 243
.byte 242
.byte 241
.short 0x150d
.short 0x3
.long 0x1001
.short 0x30
.asciz "Output"
.byte 243
.byte 242
.byte 241
.short 0x32
.short 0x1505
.short 0x2
.short 0x0
.long 0x1002
.long 0x0
.long 0x0
.short 0x60
.asciz "BurstInspectorGUITests/MyJob"
.byte 241
.short 0x42
.short 0x1605
.long 0x0
.asciz "C:\\UnitySrc\\burst\\src\\Unity.Burst.Tester\\unknown\\unknown"
.byte 243
.byte 242
.byte 241
.short 0xe
.short 0x1606
.long 0x1003
.long 0x1004
.long 0x0
.short 0x4a
.short 0x1505
.short 0x0
.short 0x80
.long 0x0
.long 0x0
.long 0x0
.short 0x0
.asciz "Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle"
.byte 241
.short 0x8a
.short 0x1203
.short 0x150d
.short 0x3
.long 0x620
.short 0x0
.asciz "m_Buffer"
.byte 241
.short 0x150d
.short 0x3
.long 0x74
.short 0x8
.asciz "m_Length"
.byte 241
.short 0x150d
.short 0x3
.long 0x74
.short 0xc
.asciz "m_MinIndex"
.byte 243
.byte 242
.byte 241
.short 0x150d
.short 0x3
.long 0x74
.short 0x10
.asciz "m_MaxIndex"
.byte 243
.byte 242
.byte 241
.short 0x150d
.short 0x3
.long 0x1006
.short 0x18
.asciz "m_Safety"
.byte 241
.short 0x150d
.short 0x3
.long 0x74
.short 0x28
.asciz "m_AllocatorLabel"
.byte 241
.short 0x46
.short 0x1505
.short 0x6
.short 0x0
.long 0x1007
.long 0x0
.long 0x0
.short 0x30
.asciz "Unity.Collections.NativeArray`1<System.Single>"
.byte 243
.byte 242
.byte 241
.short 0xe
.short 0x1606
.long 0x1008
.long 0x1004
.long 0x0
.short 0x4a
.short 0x1203
.short 0x150d
.short 0x3
.long 0x620
.short 0x0
.asciz "versionNode"
.byte 242
.byte 241
.short 0x150d
.short 0x3
.long 0x74
.short 0x8
.asciz "version"
.byte 242
.byte 241
.short 0x150d
.short 0x3
.long 0x74
.short 0xc
.asciz "staticSafetyId"
.byte 243
.byte 242
.byte 241
.short 0x4a
.short 0x1505
.short 0x3
.short 0x0
.long 0x100a
.long 0x0
.long 0x0
.short 0x10
.asciz "Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle"
.byte 241
.short 0xe
.short 0x1606
.long 0x100b
.long 0x1004
.long 0x0
.short 0xa
.short 0x1002
.long 0x1000
.long 0x1000c
.short 0x6
.short 0x1201
.long 0x0
.short 0x1a
.short 0x1009
.long 0x3
.long 0x1000
.long 0x100d
.byte 0x0
.byte 0x0
.short 0x0
.long 0x100e
.long 0x0
.short 0x32
.short 0x1602
.long 0x1000
.long 0x100f
.asciz "BurstInspectorGUITests.MyJob.Execute"
.byte 243
.byte 242
.byte 241
.short 0xa
.short 0x1002
.long 0x1001
.long 0x1000c
.short 0x1a
.short 0x1009
.long 0x74
.long 0x1001
.long 0x1011
.byte 0x0
.byte 0x0
.short 0x0
.long 0x100e
.long 0x0
.short 0x3e
.short 0x1602
.long 0x1001
.long 0x1012
.asciz "Unity.Collections.NativeArray`1<float>.get_Length"
.byte 242
.byte 241
.short 0xe
.short 0x1201
.long 0x2
.long 0x74
.long 0x40
.short 0x1a
.short 0x1009
.long 0x3
.long 0x1001
.long 0x1011
.byte 0x0
.byte 0x0
.short 0x2
.long 0x1014
.long 0x0
.short 0x3a
.short 0x1602
.long 0x1001
.long 0x1015
.asciz "Unity.Collections.NativeArray`1<float>.set_Item"
.short 0x3a
.short 0x1505
.short 0x0
.short 0x80
.long 0x0
.long 0x0
.long 0x0
.short 0x0
.asciz "Unity.Jobs.LowLevel.Unsafe.JobRanges"
.byte 241
.short 0xa
.short 0x1002
.long 0x1017
.long 0x1000c
.short 0x1a
.short 0x1201
.long 0x5
.long 0x100d
.long 0x620
.long 0x620
.long 0x1018
.long 0x74
.short 0xe
.short 0x1008
.long 0x3
.byte 0x0
.byte 0x0
.short 0x5
.long 0x1019
.short 0x62
.short 0x1203
.short 0x150d
.short 0x3
.long 0x74
.short 0x0
.asciz "BatchSize"
.short 0x150d
.short 0x3
.long 0x74
.short 0x4
.asciz "NumJobs"
.byte 242
.byte 241
.short 0x150d
.short 0x3
.long 0x74
.short 0x8
.asciz "TotalIterationCount"
.byte 242
.byte 241
.short 0x150d
.short 0x3
.long 0x620
.short 0x10
.asciz "StartEndIndex"
.short 0x3a
.short 0x1505
.short 0x4
.short 0x0
.long 0x101b
.long 0x0
.long 0x0
.short 0x18
.asciz "Unity.Jobs.LowLevel.Unsafe.JobRanges"
.byte 241
.short 0xe
.short 0x1606
.long 0x101c
.long 0x1004
.long 0x0
.short 0x17a
.short 0x1601
.long 0x0
.long 0x101a
.asciz "Unity.Jobs.IJobExtensions.JobStruct`1<BurstInspectorGUITests.MyJob>.Execute(ref BurstInspectorGUITests.MyJob data, System.IntPtr additionalPtr, System.IntPtr bufferRangePatchData, ref Unity.Jobs.LowLevel.Unsafe.JobRanges ranges, int jobIndex) -> void_930e313844f708dd8e72e0cb41431524 from UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
.byte 241
.short 0x3a
.short 0x1605
.long 0x0
.asciz "C:\\UnitySrc\\burst\\src\\Unity.Burst.Tester\\unknown"
.byte 243
.byte 242
.byte 241
.short 0xe
.short 0x1605
.long 0x0
.asciz "unknown"
.short 0xa
.short 0x1605
.long 0x0
.byte 0
.byte 243
.byte 242
.byte 241
.short 0x1a
.short 0x1603
.short 0x5
.long 0x101f
.long 0x0
.long 0x1020
.long 0x1021
.long 0x0
.byte 242
.byte 241
.globl _fltused

View file

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e98313e850883648a977ddbceaaca946
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: