説明なし
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

SphereCulling.cs 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using System.Runtime.InteropServices;
  4. using Unity.Collections;
  5. using Unity.Collections.LowLevel.Unsafe;
  6. using Unity.Jobs;
  7. using Unity.Mathematics;
  8. [assembly: InternalsVisibleTo("Burst.Benchmarks")]
  9. namespace UnityBenchShared
  10. {
  11. internal struct Sphere
  12. {
  13. private float x, y, z, r;
  14. public Sphere(float x, float y, float z, float r)
  15. {
  16. this.x = x;
  17. this.y = y;
  18. this.z = z;
  19. this.r = r;
  20. }
  21. public bool Intersects(Sphere other)
  22. {
  23. float dx = x - other.x;
  24. float dy = y - other.y;
  25. float dz = z - other.z;
  26. float rs = r + other.r;
  27. return dx * dx + dy * dy + dz * dz < (rs * rs);
  28. }
  29. }
  30. internal static class SphereCulling
  31. {
  32. public static int BenchCount = 128 * 1024 + 3;
  33. }
  34. internal interface IJob<T> : IJob
  35. {
  36. T Result { get; set; }
  37. }
  38. /// <summary>
  39. /// Simple AOS with a Sphere struct using plain floats
  40. /// </summary>
  41. internal struct SphereCullingAOSJob : IJob<bool>, IDisposable
  42. {
  43. public Sphere Against;
  44. [ReadOnly] public NativeArray<Sphere> Spheres;
  45. [MarshalAs(UnmanagedType.U1)]
  46. private bool result;
  47. public bool Result
  48. {
  49. get => result;
  50. set => result = value;
  51. }
  52. public void Execute()
  53. {
  54. bool result = false;
  55. for (int i = 0; i < Spheres.Length; ++i)
  56. {
  57. result |= Spheres[i].Intersects(Against);
  58. }
  59. Result = result;
  60. }
  61. public struct Provider : IArgumentProvider
  62. {
  63. public object Value
  64. {
  65. get
  66. {
  67. int length = SphereCulling.BenchCount * 2;
  68. var job = new SphereCullingAOSJob()
  69. {
  70. Spheres = new NativeArray<Sphere>(length, Allocator.Persistent),
  71. Against = new Sphere(0, 0, 0, 1)
  72. };
  73. var random = new System.Random(0);
  74. for (int i = 0; i < job.Spheres.Length; i++)
  75. {
  76. // Most don't intersects
  77. var x = random.Next(100) + 3.0f;
  78. if (i == job.Spheres.Length / 2)
  79. {
  80. // only this one
  81. x = 0.5f;
  82. }
  83. job.Spheres[i] = new Sphere(x, x, x, 1.0f);
  84. }
  85. return job;
  86. }
  87. }
  88. }
  89. public void Dispose()
  90. {
  91. Spheres.Dispose();
  92. }
  93. }
  94. /// <summary>
  95. /// Simple AOS with a float4 for the struct and using
  96. /// </summary>
  97. internal struct SphereCullingFloat4AOSJob : IJob<bool>, IDisposable
  98. {
  99. public float4 Against;
  100. [ReadOnly]
  101. public NativeArray<float4> Spheres;
  102. [MarshalAs(UnmanagedType.U1)]
  103. private bool result;
  104. public bool Result
  105. {
  106. get => result;
  107. set => result = value;
  108. }
  109. public static bool Intersects(float4 value, float4 other)
  110. {
  111. float rs = value.w + other.w;
  112. return math.dot(value.xyz, other.xyz) < (rs * rs);
  113. }
  114. public void Execute()
  115. {
  116. bool result = false;
  117. for (int i = 0; i < Spheres.Length; ++i)
  118. {
  119. result |= Intersects(Spheres[i], Against);
  120. }
  121. Result = result;
  122. }
  123. public struct Provider : IArgumentProvider
  124. {
  125. public object Value
  126. {
  127. get
  128. {
  129. int length = SphereCulling.BenchCount;
  130. var job = new SphereCullingFloat4AOSJob()
  131. {
  132. Spheres = new NativeArray<float4>(length, Allocator.Persistent),
  133. Against = new float4(0, 0, 0, 1)
  134. };
  135. var random = new System.Random(0);
  136. for (int i = 0; i < job.Spheres.Length; i++)
  137. {
  138. // Most don't intersects
  139. var x = random.Next(100) + 3.0f;
  140. if (i == job.Spheres.Length / 2)
  141. {
  142. // only this one
  143. x = 0.5f;
  144. }
  145. job.Spheres[i] = new float4(x, x, x, 1.0f);
  146. }
  147. return job;
  148. }
  149. }
  150. }
  151. public void Dispose()
  152. {
  153. Spheres.Dispose();
  154. }
  155. }
  156. /// <summary>
  157. /// Simple SOA with 4 NativeArray for X,Y,Z,R
  158. /// </summary>
  159. internal struct SphereCullingSOAJob : IJob<bool>, IDisposable
  160. {
  161. [ReadOnly] public NativeArray<float> X;
  162. [ReadOnly] public NativeArray<float> Y;
  163. [ReadOnly] public NativeArray<float> Z;
  164. [ReadOnly] public NativeArray<float> R;
  165. public float4 Against;
  166. [MarshalAs(UnmanagedType.U1)]
  167. private bool result;
  168. public bool Result
  169. {
  170. get => result;
  171. set => result = value;
  172. }
  173. public void Execute()
  174. {
  175. bool result = false;
  176. for (int i = 0; i < X.Length; ++i)
  177. {
  178. float dx = X[i] - Against.x;
  179. float dy = Y[i] - Against.y;
  180. float dz = Z[i] - Against.z;
  181. float rs = R[i] + Against.w;
  182. result |= dx * dx + dy * dy + dz * dz < (rs * rs);
  183. }
  184. Result = result;
  185. }
  186. public struct Provider : IArgumentProvider
  187. {
  188. public object Value
  189. {
  190. get
  191. {
  192. int length = SphereCulling.BenchCount * 2;
  193. var job = new SphereCullingSOAJob()
  194. {
  195. X = new NativeArray<float>(length, Allocator.Persistent),
  196. Y = new NativeArray<float>(length, Allocator.Persistent),
  197. Z = new NativeArray<float>(length, Allocator.Persistent),
  198. R = new NativeArray<float>(length, Allocator.Persistent),
  199. Against = new float4(0, 0, 0, 1)
  200. };
  201. var random = new System.Random(0);
  202. for (int i = 0; i < job.X.Length; i++)
  203. {
  204. // Most don't intersects
  205. var x = random.Next(100) + 3.0f;
  206. if (i == job.X.Length / 2)
  207. {
  208. // only this one
  209. x = 0.5f;
  210. }
  211. job.X[i] = x;
  212. job.Y[i] = x;
  213. job.Z[i] = x;
  214. job.R[i] = 1;
  215. }
  216. return job;
  217. }
  218. }
  219. }
  220. public void Dispose()
  221. {
  222. X.Dispose();
  223. Y.Dispose();
  224. Z.Dispose();
  225. R.Dispose();
  226. }
  227. }
  228. /// <summary>
  229. /// SOA with chunks of x,y,z,r using `float4`
  230. /// </summary>
  231. internal struct SphereCullingChunkSOAJob : IJob<bool>, IDisposable
  232. {
  233. public struct Chunk
  234. {
  235. public float4 X;
  236. public float4 Y;
  237. public float4 Z;
  238. public float4 R;
  239. }
  240. [ReadOnly] public NativeArray<Chunk> Chunks;
  241. public float4 Against;
  242. [MarshalAs(UnmanagedType.U1)]
  243. private bool result;
  244. public bool Result
  245. {
  246. get => result;
  247. set => result = value;
  248. }
  249. public void Execute()
  250. {
  251. bool result = false;
  252. for (int i = 0; i < Chunks.Length; ++i)
  253. {
  254. var chunk = Chunks[i];
  255. for (int j = 0; j < 4; j++)
  256. {
  257. float dx = chunk.X[j] - Against.x;
  258. float dy = chunk.Y[j] - Against.y;
  259. float dz = chunk.Z[j] - Against.z;
  260. float rs = chunk.R[j] + Against.w;
  261. result |= dx * dx + dy * dy + dz * dz < (rs * rs);
  262. }
  263. }
  264. Result = result;
  265. }
  266. public struct Provider : IArgumentProvider
  267. {
  268. public object Value
  269. {
  270. get
  271. {
  272. // Approximate a similar batch
  273. int length = ((SphereCulling.BenchCount * 2) + 4) / 4;
  274. var job = new SphereCullingChunkSOAJob
  275. {
  276. Chunks = new NativeArray<SphereCullingChunkSOAJob.Chunk>(length, Allocator.Persistent),
  277. Against = new float4(0, 0, 0, 1)
  278. };
  279. var random = new System.Random(0);
  280. for (int i = 0; i < job.Chunks.Length; i++)
  281. {
  282. var chunk = job.Chunks[i];
  283. for (int j = 0; j < 4; j++)
  284. {
  285. // Most don't intersects
  286. var x = random.Next(100) + 3.0f;
  287. if (i == job.Chunks.Length / 2)
  288. {
  289. // only this one
  290. x = 0.5f;
  291. }
  292. chunk.X[j] = x;
  293. chunk.Y[j] = x;
  294. chunk.Z[j] = x;
  295. chunk.R[j] = 1;
  296. }
  297. job.Chunks[i] = chunk;
  298. }
  299. return job;
  300. }
  301. }
  302. }
  303. public void Dispose()
  304. {
  305. Chunks.Dispose();
  306. }
  307. }
  308. /// <summary>
  309. /// SOA with chunks of x,y,z,r using `fixed float x[4]`
  310. /// </summary>
  311. internal struct SphereCullingChunkFixedSOAJob : IJob<bool>, IDisposable
  312. {
  313. public unsafe struct Chunk
  314. {
  315. public fixed float X[4];
  316. public fixed float Y[4];
  317. public fixed float Z[4];
  318. public fixed float R[4];
  319. }
  320. [ReadOnly] public NativeArray<Chunk> Chunks;
  321. public float4 Against;
  322. [MarshalAs(UnmanagedType.U1)]
  323. private bool result;
  324. public bool Result
  325. {
  326. get => result;
  327. set => result = value;
  328. }
  329. public unsafe void Execute()
  330. {
  331. bool result = false;
  332. for (int i = 0; i < Chunks.Length; ++i)
  333. {
  334. var chunk = Chunks[i];
  335. for (int j = 0; j < 4; j++)
  336. {
  337. float dx = chunk.X[j] - Against.x;
  338. float dy = chunk.Y[j] - Against.y;
  339. float dz = chunk.Z[j] - Against.z;
  340. float rs = chunk.R[j] + Against.w;
  341. result |= dx * dx + dy * dy + dz * dz < (rs * rs);
  342. }
  343. }
  344. Result = result;
  345. }
  346. public struct Provider : IArgumentProvider
  347. {
  348. public unsafe object Value
  349. {
  350. get
  351. {
  352. // Approximate a similar batch
  353. int length = ((SphereCulling.BenchCount) + 4) / 2;
  354. var job = new SphereCullingChunkFixedSOAJob
  355. {
  356. Chunks = new NativeArray<Chunk>(length, Allocator.Persistent),
  357. Against = new float4(0, 0, 0, 1)
  358. };
  359. var random = new System.Random(0);
  360. for (int i = 0; i < job.Chunks.Length; i++)
  361. {
  362. var chunk = job.Chunks[i];
  363. for (int j = 0; j < 4; j++)
  364. {
  365. // Most don't intersects
  366. var x = random.Next(100) + 3.0f;
  367. if (i == job.Chunks.Length / 2)
  368. {
  369. // only this one
  370. x = 0.5f;
  371. }
  372. chunk.X[j] = x;
  373. chunk.Y[j] = x;
  374. chunk.Z[j] = x;
  375. chunk.R[j] = 1;
  376. }
  377. job.Chunks[i] = chunk;
  378. }
  379. return job;
  380. }
  381. }
  382. }
  383. public void Dispose()
  384. {
  385. Chunks.Dispose();
  386. }
  387. }
  388. /// <summary>
  389. /// </summary>
  390. internal struct SphereCullingChunkSOAManualJob : IJob<bool>, IDisposable
  391. {
  392. public struct Chunk
  393. {
  394. public float4 X;
  395. public float4 Y;
  396. public float4 Z;
  397. public float4 R;
  398. }
  399. [ReadOnly] public NativeArray<Chunk> Chunks;
  400. public float4 Against;
  401. [MarshalAs(UnmanagedType.U1)]
  402. private bool result;
  403. public bool Result
  404. {
  405. get => result;
  406. set => result = value;
  407. }
  408. public void Execute()
  409. {
  410. bool4 result = false;
  411. for (int i = 0; i < Chunks.Length; ++i)
  412. {
  413. var chunk = Chunks[i];
  414. float4 dx = chunk.X - Against.x;
  415. float4 dy = chunk.Y - Against.y;
  416. float4 dz = chunk.Z - Against.z;
  417. float4 rs = chunk.R + Against.w;
  418. result |= dx * dx + dy * dy + dz * dz < (rs * rs);
  419. }
  420. Result = math.any(result);
  421. }
  422. public struct Provider : IArgumentProvider
  423. {
  424. public object Value
  425. {
  426. get
  427. {
  428. // Approximate a similar batch
  429. int length = (SphereCulling.BenchCount + 4) / 4;
  430. var job = new SphereCullingChunkSOAManualJob
  431. {
  432. Chunks = new NativeArray<SphereCullingChunkSOAManualJob.Chunk>(length, Allocator.Persistent),
  433. Against = new float4(0, 0, 0, 1)
  434. };
  435. var random = new System.Random(0);
  436. for (int i = 0; i < job.Chunks.Length; i++)
  437. {
  438. var chunk = job.Chunks[i];
  439. for (int j = 0; j < 4; j++)
  440. {
  441. // Most don't intersects
  442. var x = random.Next(100) + 3.0f;
  443. if (i == job.Chunks.Length / 2)
  444. {
  445. // only this one
  446. x = 0.5f;
  447. }
  448. chunk.X[j] = x;
  449. chunk.Y[j] = x;
  450. chunk.Z[j] = x;
  451. chunk.R[j] = 1;
  452. }
  453. job.Chunks[i] = chunk;
  454. }
  455. return job;
  456. }
  457. }
  458. }
  459. public void Dispose()
  460. {
  461. Chunks.Dispose();
  462. }
  463. }
  464. }