Açıklama Yok
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PlaymodeTest.cs 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. using System.Collections;
  2. using NUnit.Framework;
  3. using Unity.Burst;
  4. using UnityEngine;
  5. using Unity.Jobs.LowLevel.Unsafe;
  6. using UnityEngine.TestTools;
  7. using System;
  8. using Unity.Jobs;
  9. [TestFixture]
  10. public class PlaymodeTest
  11. {
  12. // [UnityTest]
  13. public IEnumerator CheckBurstJobEnabledDisabled()
  14. {
  15. BurstCompiler.Options.EnableBurstCompileSynchronously = true;
  16. foreach(var item in CheckBurstJobDisabled()) yield return item;
  17. foreach(var item in CheckBurstJobEnabled()) yield return item;
  18. }
  19. private IEnumerable CheckBurstJobEnabled()
  20. {
  21. BurstCompiler.Options.EnableBurstCompilation = true;
  22. yield return null;
  23. using (var jobTester = new BurstJobTester2())
  24. {
  25. var result = jobTester.Calculate();
  26. Assert.AreNotEqual(0.0f, result);
  27. }
  28. }
  29. private IEnumerable CheckBurstJobDisabled()
  30. {
  31. BurstCompiler.Options.EnableBurstCompilation = false;
  32. yield return null;
  33. using (var jobTester = new BurstJobTester2())
  34. {
  35. var result = jobTester.Calculate();
  36. Assert.AreEqual(0.0f, result);
  37. }
  38. }
  39. [BurstCompile(CompileSynchronously = true)]
  40. private struct ThrowingJob : IJob
  41. {
  42. public int I;
  43. public void Execute()
  44. {
  45. if (I < 0)
  46. {
  47. throw new System.Exception("Some Exception!");
  48. }
  49. }
  50. }
  51. [Test]
  52. public void NoSafetyCheckExceptionWarningInEditor()
  53. {
  54. var job = new ThrowingJob { I = 42 };
  55. job.Schedule().Complete();
  56. // UNITY_BURST_DEBUG enables additional logging which messes with our check.
  57. if (null == System.Environment.GetEnvironmentVariable("UNITY_BURST_DEBUG"))
  58. {
  59. LogAssert.NoUnexpectedReceived();
  60. }
  61. }
  62. private struct MyKey { public struct MySubKey0 { } public struct MySubKey1 { } }
  63. private struct SomeGenericStruct<T> {}
  64. private static readonly SharedStatic<int> SharedStaticOneType = SharedStatic<int>.GetOrCreate<MyKey>();
  65. private static readonly SharedStatic<double> SharedStaticTwoTypes0 = SharedStatic<double>.GetOrCreate<MyKey, MyKey.MySubKey0>();
  66. private static readonly SharedStatic<double> SharedStaticTwoTypes1 = SharedStatic<double>.GetOrCreate<MyKey, MyKey.MySubKey1>();
  67. private struct MyGenericContainingStruct<T>
  68. {
  69. public static readonly SharedStatic<int> Data0 = SharedStatic<int>.GetOrCreate<T>();
  70. public static readonly SharedStatic<int> Data1 = SharedStatic<int>.GetOrCreate<SomeGenericStruct<MyKey>, T>();
  71. public static readonly SharedStatic<int> Data2 = SharedStatic<int>.GetOrCreate<SomeGenericStruct<T>, MyKey>();
  72. }
  73. private static readonly SharedStatic<int> SharedStaticWithSystemTypes0 = SharedStatic<int>.GetOrCreate<IntPtr>();
  74. private static readonly SharedStatic<int> SharedStaticWithSystemTypes1 = SharedStatic<int>.GetOrCreate<IntPtr, MyKey>();
  75. private static readonly SharedStatic<int> SharedStaticWithSystemTypes2 = SharedStatic<int>.GetOrCreate<MyKey, IntPtr>();
  76. private static readonly SharedStatic<int> SharedStaticWithSystemTypes3 = SharedStatic<int>.GetOrCreate<IntPtr, IntPtr>();
  77. [Test]
  78. public unsafe void SharedStaticPostProcessedTests()
  79. {
  80. var oneType = SharedStatic<int>.GetOrCreate(typeof(MyKey));
  81. Assert.AreEqual((IntPtr)oneType.UnsafeDataPointer, (IntPtr)SharedStaticOneType.UnsafeDataPointer);
  82. Assert.AreNotEqual((IntPtr)oneType.UnsafeDataPointer, (IntPtr)SharedStaticTwoTypes0.UnsafeDataPointer);
  83. Assert.AreNotEqual((IntPtr)oneType.UnsafeDataPointer, (IntPtr)SharedStaticTwoTypes1.UnsafeDataPointer);
  84. var twoTypes0 = SharedStatic<double>.GetOrCreate(typeof(MyKey), typeof(MyKey.MySubKey0));
  85. Assert.AreEqual((IntPtr)twoTypes0.UnsafeDataPointer, (IntPtr)SharedStaticTwoTypes0.UnsafeDataPointer);
  86. Assert.AreNotEqual((IntPtr)twoTypes0.UnsafeDataPointer, (IntPtr)SharedStaticOneType.UnsafeDataPointer);
  87. Assert.AreNotEqual((IntPtr)twoTypes0.UnsafeDataPointer, (IntPtr)SharedStaticTwoTypes1.UnsafeDataPointer);
  88. var twoTypes1 = SharedStatic<double>.GetOrCreate(typeof(MyKey), typeof(MyKey.MySubKey1));
  89. Assert.AreEqual((IntPtr)twoTypes1.UnsafeDataPointer, (IntPtr)SharedStaticTwoTypes1.UnsafeDataPointer);
  90. Assert.AreNotEqual((IntPtr)twoTypes1.UnsafeDataPointer, (IntPtr)SharedStaticOneType.UnsafeDataPointer);
  91. Assert.AreNotEqual((IntPtr)twoTypes1.UnsafeDataPointer, (IntPtr)SharedStaticTwoTypes0.UnsafeDataPointer);
  92. // A shared static in a generic struct, that uses the same type for `GetOrCreate`, will resolve to the same shared static.
  93. Assert.AreEqual((IntPtr)oneType.UnsafeDataPointer, (IntPtr)MyGenericContainingStruct<MyKey>.Data0.UnsafeDataPointer);
  94. // These two test partial evaluations of shared statics (where we can evaluate one of the template arguments at ILPP time
  95. // but not both).
  96. Assert.AreEqual(
  97. (IntPtr)MyGenericContainingStruct<MyKey>.Data1.UnsafeDataPointer,
  98. (IntPtr)MyGenericContainingStruct<MyKey>.Data2.UnsafeDataPointer);
  99. // Check that system type evaluations all match up.
  100. Assert.AreEqual(
  101. (IntPtr)SharedStatic<int>.GetOrCreate(typeof(IntPtr)).UnsafeDataPointer,
  102. (IntPtr)SharedStaticWithSystemTypes0.UnsafeDataPointer);
  103. Assert.AreEqual(
  104. (IntPtr)SharedStatic<int>.GetOrCreate(typeof(IntPtr), typeof(MyKey)).UnsafeDataPointer,
  105. (IntPtr)SharedStaticWithSystemTypes1.UnsafeDataPointer);
  106. Assert.AreEqual(
  107. (IntPtr)SharedStatic<int>.GetOrCreate(typeof(MyKey), typeof(IntPtr)).UnsafeDataPointer,
  108. (IntPtr)SharedStaticWithSystemTypes2.UnsafeDataPointer);
  109. Assert.AreEqual(
  110. (IntPtr)SharedStatic<int>.GetOrCreate(typeof(IntPtr), typeof(IntPtr)).UnsafeDataPointer,
  111. (IntPtr)SharedStaticWithSystemTypes3.UnsafeDataPointer);
  112. }
  113. [BurstCompile]
  114. public struct SomeFunctionPointers
  115. {
  116. [BurstDiscard]
  117. private static void MessWith(ref int a) => a += 13;
  118. [BurstCompile]
  119. public static int A(int a, int b)
  120. {
  121. MessWith(ref a);
  122. return a + b;
  123. }
  124. [BurstCompile(DisableDirectCall = true)]
  125. public static int B(int a, int b)
  126. {
  127. MessWith(ref a);
  128. return a - b;
  129. }
  130. [BurstCompile(CompileSynchronously = true)]
  131. public static int C(int a, int b)
  132. {
  133. MessWith(ref a);
  134. return a * b;
  135. }
  136. [BurstCompile(CompileSynchronously = true, DisableDirectCall = true)]
  137. public static int D(int a, int b)
  138. {
  139. MessWith(ref a);
  140. return a / b;
  141. }
  142. public delegate int Delegate(int a, int b);
  143. }
  144. [Test]
  145. public void TestDirectCalls()
  146. {
  147. Assert.IsTrue(BurstCompiler.IsEnabled);
  148. // a can either be (42 + 13) + 53 or 42 + 53 (depending on whether it was burst compiled).
  149. var a = SomeFunctionPointers.A(42, 53);
  150. Assert.IsTrue((a == ((42 + 13) + 53)) || (a == (42 + 53)));
  151. // b can only be (42 + 13) - 53, because direct call is disabled and so we always call the managed method.
  152. var b = SomeFunctionPointers.B(42, 53);
  153. Assert.AreEqual((42 + 13) - 53, b);
  154. // c can only be 42 * 53, because synchronous compilation is enabled.
  155. var c = SomeFunctionPointers.C(42, 53);
  156. Assert.AreEqual(42 * 53, c);
  157. // d can only be (42 + 13) / 53, because even though synchronous compilation is enabled, direct call is disabled.
  158. var d = SomeFunctionPointers.D(42, 53);
  159. Assert.AreEqual((42 + 13) / 53, d);
  160. }
  161. [Test]
  162. public void TestDirectCallInNamespacedClass()
  163. {
  164. void onCompileILPPMethod2()
  165. {
  166. Assert.Fail("BurstCompiler.CompileILPPMethod2 should not have been called at this time");
  167. }
  168. // We expect BurstCompiler.CompileILPPMethod2 to have been called at startup, via
  169. // [InitializeOnLoad] or [RuntimeInitializeOnLoadMethod]. If it's called when we invoke
  170. // N.C.A(), then something has gone wrong.
  171. try
  172. {
  173. BurstCompiler.OnCompileILPPMethod2 += onCompileILPPMethod2;
  174. var result = N.C.A();
  175. Assert.AreEqual(42, result);
  176. }
  177. finally
  178. {
  179. BurstCompiler.OnCompileILPPMethod2 -= onCompileILPPMethod2;
  180. }
  181. }
  182. [Test]
  183. public void TestFunctionPointers()
  184. {
  185. Assert.IsTrue(BurstCompiler.IsEnabled);
  186. var A = BurstCompiler.CompileFunctionPointer<SomeFunctionPointers.Delegate>(SomeFunctionPointers.A);
  187. var B = BurstCompiler.CompileFunctionPointer<SomeFunctionPointers.Delegate>(SomeFunctionPointers.B);
  188. var C = BurstCompiler.CompileFunctionPointer<SomeFunctionPointers.Delegate>(SomeFunctionPointers.C);
  189. var D = BurstCompiler.CompileFunctionPointer<SomeFunctionPointers.Delegate>(SomeFunctionPointers.D);
  190. // a can either be (42 + 13) + 53 or 42 + 53 (depending on whether it was burst compiled).
  191. var a = A.Invoke(42, 53);
  192. Assert.IsTrue((a == ((42 + 13) + 53)) || (a == (42 + 53)));
  193. // b can either be (42 + 13) - 53 or 42 - 53 (depending on whether it was burst compiled).
  194. var b = B.Invoke(42, 53);
  195. Assert.IsTrue((b == ((42 + 13) - 53)) || (b == (42 - 53)));
  196. // c can only be 42 * 53, because synchronous compilation is enabled.
  197. var c = C.Invoke(42, 53);
  198. Assert.AreEqual(42 * 53, c);
  199. // d can only be 42 / 53, because synchronous compilation is enabled.
  200. var d = D.Invoke(42, 53);
  201. Assert.AreEqual(42 / 53, d);
  202. }
  203. [BurstCompile]
  204. public static class GenericClass<T>
  205. {
  206. [BurstCompile]
  207. public static int ConcreteMethod() => 3;
  208. }
  209. public delegate int NoArgsIntReturnDelegate();
  210. [Test]
  211. public void TestGenericClassConcreteMethodFunctionPointer()
  212. {
  213. Assert.IsTrue(BurstCompiler.IsEnabled);
  214. var F = BurstCompiler.CompileFunctionPointer<NoArgsIntReturnDelegate>(GenericClass<int>.ConcreteMethod);
  215. Assert.AreEqual(3, F.Invoke());
  216. }
  217. }
  218. // This test class is intentionally in a namespace to ensure that our
  219. // direct-call [RuntimeInitializeOnLoadMethod] works correctly in that
  220. // scenario.
  221. namespace N
  222. {
  223. [BurstCompile]
  224. internal static class C
  225. {
  226. public static int A() => B();
  227. [BurstCompile(CompileSynchronously = true)]
  228. private static int B()
  229. {
  230. var x = 42;
  231. DiscardedMethod(ref x);
  232. return x;
  233. }
  234. [BurstDiscard]
  235. private static void DiscardedMethod(ref int x)
  236. {
  237. x += 1;
  238. }
  239. }
  240. }