No Description
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.

ComputeRayTracingAccelStruct.cs 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. using System;
  2. using System.Collections.Generic;
  3. using Unity.Mathematics;
  4. using UnityEngine.Assertions;
  5. using UnityEngine.Rendering.RadeonRays;
  6. #if UNITY_EDITOR
  7. using UnityEditor.Embree;
  8. #endif
  9. namespace UnityEngine.Rendering.UnifiedRayTracing
  10. {
  11. internal class ComputeRayTracingAccelStruct : IRayTracingAccelStruct
  12. {
  13. internal ComputeRayTracingAccelStruct(
  14. AccelerationStructureOptions options, RayTracingResources resources,
  15. ReferenceCounter counter, int blasBufferInitialSizeBytes = 64 * 1024 * 1024)
  16. {
  17. m_CopyShader = resources.copyBuffer;
  18. RadeonRaysShaders shaders = new RadeonRaysShaders();
  19. shaders.bitHistogram = resources.bitHistogram;
  20. shaders.blockReducePart = resources.blockReducePart;
  21. shaders.blockScan = resources.blockScan;
  22. shaders.buildHlbvh = resources.buildHlbvh;
  23. shaders.reorderTriangleIndices = resources.reorderTriangleIndices;
  24. shaders.restructureBvh = resources.restructureBvh;
  25. shaders.scatter = resources.scatter;
  26. shaders.topLevelIntersector = resources.topLevelIntersector;
  27. shaders.intersector = resources.intersector;
  28. m_RadeonRaysAPI = new RadeonRaysAPI(shaders);
  29. m_AccelStructBuildFlags = ConvertFlagsToGpuBuild(options.buildFlags);
  30. #if UNITY_EDITOR
  31. m_UseCpuBuild = options.useCPUBuild;
  32. m_CpuBuildOptions = ConvertFlagsToCpuBuild(options.buildFlags);
  33. #endif
  34. m_Blases = new Dictionary<(int mesh, int subMeshIndex), MeshBlas>();
  35. var blasNodeCount = blasBufferInitialSizeBytes / RadeonRaysAPI.BvhNodeSizeInBytes();
  36. m_BlasBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, blasNodeCount, RadeonRaysAPI.BvhNodeSizeInBytes());
  37. m_BlasPositions = new BLASPositionsPool(resources.copyPositions, resources.copyBuffer);
  38. m_BlasAllocator = new BlockAllocator();
  39. m_BlasAllocator.Initialize(blasNodeCount);
  40. m_Counter = counter;
  41. m_Counter.Inc();
  42. }
  43. internal GraphicsBuffer topLevelBvhBuffer { get { return m_TopLevelAccelStruct?.topLevelBvh; } }
  44. internal GraphicsBuffer bottomLevelBvhBuffer { get { return m_TopLevelAccelStruct?.bottomLevelBvhs; } }
  45. internal GraphicsBuffer instanceInfoBuffer { get { return m_TopLevelAccelStruct?.instanceInfos; } }
  46. public void Dispose()
  47. {
  48. m_Counter.Dec();
  49. m_RadeonRaysAPI.Dispose();
  50. m_BlasBuffer.Dispose();
  51. m_BlasPositions.Dispose();
  52. m_BlasAllocator.Dispose();
  53. m_TopLevelAccelStruct?.Dispose();
  54. }
  55. public int AddInstance(MeshInstanceDesc meshInstance)
  56. {
  57. var blas = GetOrAllocateMeshBlas(meshInstance.mesh, meshInstance.subMeshIndex);
  58. blas.IncRef();
  59. FreeTopLevelAccelStruct();
  60. int handle = NewHandle();
  61. (new RadeonRaysInstance()).GetHashCode();
  62. m_RadeonInstances.Add(handle, new RadeonRaysInstance
  63. {
  64. geomKey = (meshInstance.mesh.GetHashCode(), meshInstance.subMeshIndex),
  65. blas = blas,
  66. instanceMask = meshInstance.mask,
  67. triangleCullingEnabled = meshInstance.enableTriangleCulling,
  68. invertTriangleCulling = meshInstance.frontTriangleCounterClockwise,
  69. userInstanceID = meshInstance.instanceID == 0xFFFFFFFF ? (uint)handle : meshInstance.instanceID,
  70. localToWorldTransform = ConvertTranform(meshInstance.localToWorldMatrix)
  71. });
  72. return handle;
  73. }
  74. public void RemoveInstance(int instanceHandle)
  75. {
  76. ReleaseHandle(instanceHandle);
  77. m_RadeonInstances.Remove(instanceHandle, out RadeonRaysInstance entry);
  78. var meshBlas = entry.blas;
  79. meshBlas.DecRef();
  80. if (meshBlas.IsUnreferenced())
  81. DeleteMeshBlas(entry.geomKey, meshBlas);
  82. FreeTopLevelAccelStruct();
  83. }
  84. public void ClearInstances()
  85. {
  86. m_FreeHandles.Clear();
  87. m_RadeonInstances.Clear();
  88. m_Blases.Clear();
  89. m_BlasPositions.Clear();
  90. var currentCapacity = m_BlasAllocator.capacity;
  91. m_BlasAllocator.Dispose();
  92. m_BlasAllocator = new BlockAllocator();
  93. m_BlasAllocator.Initialize(currentCapacity);
  94. FreeTopLevelAccelStruct();
  95. }
  96. public void UpdateInstanceTransform(int instanceHandle, Matrix4x4 localToWorldMatrix)
  97. {
  98. m_RadeonInstances[instanceHandle].localToWorldTransform = ConvertTranform(localToWorldMatrix);
  99. FreeTopLevelAccelStruct();
  100. }
  101. public void UpdateInstanceID(int instanceHandle, uint instanceID)
  102. {
  103. m_RadeonInstances[instanceHandle].userInstanceID = instanceID;
  104. FreeTopLevelAccelStruct();
  105. }
  106. public void UpdateInstanceMask(int instanceHandle, uint mask)
  107. {
  108. m_RadeonInstances[instanceHandle].instanceMask = mask;
  109. FreeTopLevelAccelStruct();
  110. }
  111. public void Build(CommandBuffer cmd, GraphicsBuffer scratchBuffer)
  112. {
  113. var requiredScratchSize = GetBuildScratchBufferRequiredSizeInBytes();
  114. if (requiredScratchSize > 0 && (scratchBuffer == null || ((ulong)(scratchBuffer.count * scratchBuffer.stride) < requiredScratchSize)))
  115. {
  116. throw new System.ArgumentException("scratchBuffer size is too small");
  117. }
  118. if (requiredScratchSize > 0 && scratchBuffer.stride != 4)
  119. {
  120. throw new System.ArgumentException("scratchBuffer stride must be 4");
  121. }
  122. if (m_TopLevelAccelStruct != null)
  123. return;
  124. CreateBvh(cmd, scratchBuffer);
  125. }
  126. public ulong GetBuildScratchBufferRequiredSizeInBytes()
  127. {
  128. return GetBvhBuildScratchBufferSizeInDwords() * 4;
  129. }
  130. private void FreeTopLevelAccelStruct()
  131. {
  132. m_TopLevelAccelStruct?.Dispose();
  133. m_TopLevelAccelStruct = null;
  134. }
  135. private MeshBlas GetOrAllocateMeshBlas(Mesh mesh, int subMeshIndex)
  136. {
  137. MeshBlas blas;
  138. if (m_Blases.TryGetValue((mesh.GetHashCode(), subMeshIndex), out blas))
  139. return blas;
  140. blas = new MeshBlas();
  141. AllocateBlas(mesh, subMeshIndex, blas);
  142. m_Blases[(mesh.GetHashCode(), subMeshIndex)] = blas;
  143. return blas;
  144. }
  145. void AllocateBlas(Mesh mesh, int submeshIndex, MeshBlas blas)
  146. {
  147. var bvhNodeSizeInDwords = RadeonRaysAPI.BvhNodeSizeInDwords();
  148. mesh.indexBufferTarget |= GraphicsBuffer.Target.Raw;
  149. mesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw;
  150. SubMeshDescriptor submeshDescriptor = mesh.GetSubMesh(submeshIndex);
  151. using var vertexBuffer = LoadPositionBuffer(mesh, out int stride, out int offset);
  152. using var indexBuffer = LoadIndexBuffer(mesh);
  153. var inputInfo = new MeshBuildInfo();
  154. inputInfo.vertices = vertexBuffer;
  155. inputInfo.verticesStartOffset = offset;
  156. inputInfo.baseVertex = submeshDescriptor.baseVertex + submeshDescriptor.firstVertex;
  157. inputInfo.triangleIndices = indexBuffer;
  158. inputInfo.indexFormat = mesh.indexFormat == IndexFormat.UInt32 ? RadeonRays.IndexFormat.Int32 : RadeonRays.IndexFormat.Int16;
  159. inputInfo.vertexCount = (uint)submeshDescriptor.vertexCount;
  160. inputInfo.triangleCount = (uint)submeshDescriptor.indexCount / 3;
  161. inputInfo.indicesStartOffset = submeshDescriptor.indexStart;
  162. inputInfo.baseIndex = -submeshDescriptor.firstVertex;
  163. inputInfo.vertexStride = (uint)stride;
  164. m_BlasPositions.Add(inputInfo, out blas.blasIndices, out blas.blasVertices);
  165. var meshBuildInfo = new MeshBuildInfo();
  166. meshBuildInfo.vertices = m_BlasPositions.VertexBuffer;
  167. meshBuildInfo.verticesStartOffset = blas.blasVertices.block.offset;
  168. meshBuildInfo.baseVertex = 0;
  169. meshBuildInfo.triangleIndices = m_BlasPositions.IndexBuffer;
  170. meshBuildInfo.vertexCount = (uint)blas.blasVertices.block.count/3;
  171. meshBuildInfo.triangleCount = (uint)blas.blasIndices.block.count/3;
  172. meshBuildInfo.indicesStartOffset = blas.blasIndices.block.offset;
  173. meshBuildInfo.baseIndex = 0;
  174. meshBuildInfo.vertexStride = 3;
  175. blas.buildInfo = meshBuildInfo;
  176. #if UNITY_EDITOR
  177. if (m_UseCpuBuild)
  178. {
  179. blas.indicesForCpuBuild = new List<int>();
  180. mesh.GetTriangles(blas.indicesForCpuBuild, submeshIndex, false);
  181. blas.verticesForCpuBuild = new List<Vector3>();
  182. mesh.GetVertices(blas.verticesForCpuBuild);
  183. blas.blasAllocation = BlockAllocator.Allocation.Invalid;
  184. }
  185. else
  186. #endif
  187. {
  188. var requirements = m_RadeonRaysAPI.GetMeshBuildMemoryRequirements(meshBuildInfo, m_AccelStructBuildFlags);
  189. var allocationNodeCount = (int)(requirements.resultSizeInDwords / (ulong)bvhNodeSizeInDwords);
  190. blas.blasAllocation = AllocateBlas(allocationNodeCount);
  191. }
  192. }
  193. private GraphicsBuffer LoadIndexBuffer(Mesh mesh)
  194. {
  195. if ((mesh.indexBufferTarget & GraphicsBuffer.Target.Raw) == 0 && (mesh.GetIndices(0) == null || mesh.GetIndices(0).Length == 0))
  196. {
  197. throw new Exception("Cant use a mesh buffer that is not raw and has no CPU index information.");
  198. }
  199. return mesh.GetIndexBuffer();
  200. }
  201. GraphicsBuffer LoadPositionBuffer(Mesh mesh, out int stride, out int offset)
  202. {
  203. VertexAttribute attribute = VertexAttribute.Position;
  204. if (!mesh.HasVertexAttribute(attribute))
  205. {
  206. throw new Exception("Cant use a mesh buffer that has no positions.");
  207. }
  208. int stream = mesh.GetVertexAttributeStream(attribute);
  209. stride = mesh.GetVertexBufferStride(stream) / 4;
  210. offset = mesh.GetVertexAttributeOffset(attribute) / 4;
  211. return mesh.GetVertexBuffer(stream);
  212. }
  213. private void DeleteMeshBlas((int mesh, int subMeshIndex) geomKey, MeshBlas blas)
  214. {
  215. m_BlasAllocator.FreeAllocation(blas.blasAllocation);
  216. m_BlasPositions.Remove(ref blas.blasIndices, ref blas.blasVertices);
  217. blas.blasAllocation = BlockAllocator.Allocation.Invalid;
  218. m_Blases.Remove(geomKey);
  219. }
  220. private ulong GetBvhBuildScratchBufferSizeInDwords()
  221. {
  222. #if UNITY_EDITOR
  223. if (m_UseCpuBuild)
  224. return 0;
  225. #endif
  226. var bvhNodeSizeInDwords = RadeonRaysAPI.BvhNodeSizeInDwords();
  227. ulong scratchBufferSize = 0;
  228. foreach (var meshBlas in m_Blases)
  229. {
  230. if (meshBlas.Value.bvhBuilt)
  231. continue;
  232. var requirements = m_RadeonRaysAPI.GetMeshBuildMemoryRequirements(meshBlas.Value.buildInfo, m_AccelStructBuildFlags);
  233. Assert.AreEqual(requirements.resultSizeInDwords / (ulong)bvhNodeSizeInDwords, (ulong)meshBlas.Value.blasAllocation.block.count);
  234. scratchBufferSize = math.max(scratchBufferSize, requirements.buildScratchSizeInDwords);
  235. }
  236. var topLevelScratchSize = m_RadeonRaysAPI.GetSceneBuildMemoryRequirements((uint)m_RadeonInstances.Count).buildScratchSizeInDwords;
  237. scratchBufferSize = math.max(scratchBufferSize, topLevelScratchSize);
  238. scratchBufferSize = math.max(4, scratchBufferSize);
  239. return scratchBufferSize;
  240. }
  241. private void CreateBvh(CommandBuffer cmd, GraphicsBuffer scratchBuffer)
  242. {
  243. BuildMissingBottomLevelAccelStructs(cmd, scratchBuffer);
  244. BuildTopLevelAccelStruct(cmd, scratchBuffer);
  245. }
  246. private void BuildMissingBottomLevelAccelStructs(CommandBuffer cmd, GraphicsBuffer scratchBuffer)
  247. {
  248. foreach (var meshBlas in m_Blases.Values)
  249. {
  250. if (meshBlas.bvhBuilt)
  251. continue;
  252. meshBlas.buildInfo.vertices = m_BlasPositions.VertexBuffer;
  253. meshBlas.buildInfo.triangleIndices = m_BlasPositions.IndexBuffer;
  254. #if UNITY_EDITOR
  255. if (m_UseCpuBuild)
  256. {
  257. CpuBuildForBottomLevelAccelStruct(cmd, meshBlas);
  258. }
  259. else
  260. #endif
  261. {
  262. m_RadeonRaysAPI.BuildMeshAccelStruct(
  263. cmd,
  264. meshBlas.buildInfo, m_AccelStructBuildFlags,
  265. scratchBuffer, m_BlasBuffer, (uint)meshBlas.blasAllocation.block.offset, (uint)meshBlas.blasAllocation.block.count);
  266. }
  267. meshBlas.bvhBuilt = true;
  268. }
  269. }
  270. private void BuildTopLevelAccelStruct(CommandBuffer cmd, GraphicsBuffer scratchBuffer)
  271. {
  272. var radeonRaysInstances = new RadeonRays.Instance[m_RadeonInstances.Count];
  273. int i = 0;
  274. foreach (var instance in m_RadeonInstances.Values)
  275. {
  276. radeonRaysInstances[i].meshAccelStructOffset = (uint)instance.blas.blasAllocation.block.offset;
  277. radeonRaysInstances[i].localToWorldTransform = instance.localToWorldTransform;
  278. radeonRaysInstances[i].instanceMask = instance.instanceMask;
  279. radeonRaysInstances[i].vertexOffset = (uint)instance.blas.blasVertices.block.offset;
  280. radeonRaysInstances[i].indexOffset = (uint)instance.blas.blasIndices.block.offset;
  281. radeonRaysInstances[i].triangleCullingEnabled = instance.triangleCullingEnabled;
  282. radeonRaysInstances[i].invertTriangleCulling = instance.invertTriangleCulling;
  283. radeonRaysInstances[i].userInstanceID = instance.userInstanceID;
  284. i++;
  285. }
  286. m_TopLevelAccelStruct?.Dispose();
  287. #if UNITY_EDITOR
  288. if (m_UseCpuBuild)
  289. m_TopLevelAccelStruct = CpuBuildForTopLevelAccelStruct(cmd, radeonRaysInstances);
  290. else
  291. #endif
  292. m_TopLevelAccelStruct = m_RadeonRaysAPI.BuildSceneAccelStruct(cmd, m_BlasBuffer, radeonRaysInstances, m_AccelStructBuildFlags, scratchBuffer);
  293. }
  294. #if UNITY_EDITOR
  295. void CpuBuildForBottomLevelAccelStruct(CommandBuffer cmd, MeshBlas blas)
  296. {
  297. var vertices = blas.verticesForCpuBuild;
  298. var indices = blas.indicesForCpuBuild;
  299. var prims = new GpuBvhPrimitiveDescriptor[blas.buildInfo.triangleCount];
  300. for (int i = 0; i < blas.buildInfo.triangleCount; ++i)
  301. {
  302. var triangleIndices = GetFaceIndices(indices, i);
  303. var triangle = GetTriangle(vertices, triangleIndices);
  304. AABB aabb = new AABB();
  305. aabb.Encapsulate(triangle.v0);
  306. aabb.Encapsulate(triangle.v1);
  307. aabb.Encapsulate(triangle.v2);
  308. prims[i].primID = (uint)i;
  309. prims[i].lowerBound = aabb.Min;
  310. prims[i].upperBound = aabb.Max;
  311. }
  312. blas.indicesForCpuBuild = null;
  313. blas.verticesForCpuBuild = null;
  314. var bvhBlob = GpuBvh.Build(m_CpuBuildOptions, prims);
  315. var bvhSizeInDwords = bvhBlob.Length;
  316. var bvhSizeInNodes = bvhBlob.Length / RadeonRaysAPI.BvhNodeSizeInDwords();
  317. blas.blasAllocation = AllocateBlas(bvhSizeInNodes);
  318. var bvhStartInDwords = blas.blasAllocation.block.offset * RadeonRaysAPI.BvhNodeSizeInDwords();
  319. cmd.SetBufferData(m_BlasBuffer, bvhBlob, 0, bvhStartInDwords, bvhSizeInDwords);
  320. // read mesh aabb from bvh header.
  321. blas.aabbForCpuBuild = new AABB();
  322. blas.aabbForCpuBuild.Min.x = math.asfloat(bvhBlob[4]);
  323. blas.aabbForCpuBuild.Min.y = math.asfloat(bvhBlob[5]);
  324. blas.aabbForCpuBuild.Min.z = math.asfloat(bvhBlob[6]);
  325. blas.aabbForCpuBuild.Max.x = math.asfloat(bvhBlob[7]);
  326. blas.aabbForCpuBuild.Max.y = math.asfloat(bvhBlob[8]);
  327. blas.aabbForCpuBuild.Max.z = math.asfloat(bvhBlob[9]);
  328. }
  329. TopLevelAccelStruct CpuBuildForTopLevelAccelStruct(CommandBuffer cmd, RadeonRays.Instance[] radeonRaysInstances)
  330. {
  331. var prims = new GpuBvhPrimitiveDescriptor[m_RadeonInstances.Count];
  332. int i = 0;
  333. foreach (var instance in m_RadeonInstances.Values)
  334. {
  335. var blas = instance.blas;
  336. AABB aabb = blas.aabbForCpuBuild;
  337. var m = ConvertTranform(instance.localToWorldTransform);
  338. var bounds = GeometryUtility.CalculateBounds(new Vector3[]
  339. { new Vector3(aabb.Min.x, aabb.Min.y, aabb.Max.z),
  340. new Vector3(aabb.Min.x, aabb.Max.y, aabb.Min.z),
  341. new Vector3(aabb.Min.x, aabb.Max.y, aabb.Max.z),
  342. new Vector3(aabb.Max.x, aabb.Min.y, aabb.Max.z),
  343. new Vector3(aabb.Max.x, aabb.Max.y, aabb.Min.z),
  344. new Vector3(aabb.Max.x, aabb.Max.y, aabb.Max.z)
  345. }, m);
  346. prims[i].primID = (uint)i;
  347. prims[i].lowerBound = bounds.min;
  348. prims[i].upperBound = bounds.max;
  349. i++;
  350. }
  351. if (m_RadeonInstances.Count != 0)
  352. {
  353. var bvhBlob = GpuBvh.Build(m_CpuBuildOptions, prims);
  354. var bvhSizeInDwords = bvhBlob.Length;
  355. var result = m_RadeonRaysAPI.CreateSceneAccelStructBuffers(m_BlasBuffer, (uint)bvhSizeInDwords, radeonRaysInstances);
  356. cmd.SetBufferData(result.topLevelBvh, (bvhBlob));
  357. return result;
  358. }
  359. else
  360. {
  361. return m_RadeonRaysAPI.CreateSceneAccelStructBuffers(m_BlasBuffer, 0, radeonRaysInstances);
  362. }
  363. }
  364. GpuBvhBuildOptions ConvertFlagsToCpuBuild(BuildFlags flags)
  365. {
  366. GpuBvhBuildQuality quality = GpuBvhBuildQuality.Medium;
  367. if ((flags & BuildFlags.PreferFastBuild) != 0 && (flags & BuildFlags.PreferFastTrace) == 0)
  368. quality = GpuBvhBuildQuality.Low;
  369. else if ((flags & BuildFlags.PreferFastTrace) != 0 && (flags & BuildFlags.PreferFastBuild) == 0)
  370. quality = GpuBvhBuildQuality.High;
  371. return new GpuBvhBuildOptions
  372. {
  373. quality = quality,
  374. minLeafSize = 1,
  375. maxLeafSize = 1,
  376. allowPrimitiveSplits = (quality == GpuBvhBuildQuality.High)
  377. };
  378. }
  379. #endif
  380. RadeonRays.BuildFlags ConvertFlagsToGpuBuild(BuildFlags flags)
  381. {
  382. if ((BuildFlags.PreferFastBuild) != 0 && (flags & BuildFlags.PreferFastTrace) == 0)
  383. return RadeonRays.BuildFlags.PreferFastBuild;
  384. else
  385. return RadeonRays.BuildFlags.None;
  386. }
  387. public void Bind(CommandBuffer cmd, string name, IRayTracingShader shader)
  388. {
  389. shader.SetBufferParam(cmd, Shader.PropertyToID(name + "bvh"), topLevelBvhBuffer);
  390. shader.SetBufferParam(cmd, Shader.PropertyToID(name + "bottomBvhs"), bottomLevelBvhBuffer);
  391. shader.SetBufferParam(cmd, Shader.PropertyToID(name + "instanceInfos"), instanceInfoBuffer);
  392. shader.SetBufferParam(cmd, Shader.PropertyToID(name + "indexBuffer"), m_BlasPositions.IndexBuffer);
  393. shader.SetBufferParam(cmd, Shader.PropertyToID(name + "vertexBuffer"), m_BlasPositions.VertexBuffer);
  394. shader.SetIntParam(cmd, Shader.PropertyToID(name + "vertexStride"), 3);
  395. }
  396. static private RadeonRays.Transform ConvertTranform(Matrix4x4 input)
  397. {
  398. return new RadeonRays.Transform()
  399. {
  400. row0 = input.GetRow(0),
  401. row1 = input.GetRow(1),
  402. row2 = input.GetRow(2)
  403. };
  404. }
  405. static private Matrix4x4 ConvertTranform(RadeonRays.Transform input)
  406. {
  407. var m = new Matrix4x4();
  408. m.SetRow(0, input.row0);
  409. m.SetRow(1, input.row1);
  410. m.SetRow(2, input.row2);
  411. m.SetRow(3, new Vector4(0.0f, 0.0f, 0.0f, 1.0f));
  412. return m;
  413. }
  414. static int3 GetFaceIndices(List<int> indices, int triangleIdx)
  415. {
  416. return new int3(
  417. indices[3 * triangleIdx],
  418. indices[3 * triangleIdx + 1],
  419. indices[3 * triangleIdx + 2]);
  420. }
  421. struct Triangle
  422. {
  423. public float3 v0;
  424. public float3 v1;
  425. public float3 v2;
  426. };
  427. static Triangle GetTriangle(List<Vector3> vertices, int3 idx)
  428. {
  429. Triangle tri;
  430. tri.v0 = vertices[idx.x];
  431. tri.v1 = vertices[idx.y];
  432. tri.v2 = vertices[idx.z];
  433. return tri;
  434. }
  435. private BlockAllocator.Allocation AllocateBlas(int allocationNodeCount)
  436. {
  437. var allocation = m_BlasAllocator.Allocate(allocationNodeCount);
  438. if (!allocation.valid)
  439. {
  440. var oldBvhNodeCount = m_BlasAllocator.capacity;
  441. var newBvhNodeCount = m_BlasAllocator.Grow(m_BlasAllocator.capacity + allocationNodeCount);
  442. if ((ulong)newBvhNodeCount > ((ulong)2 * 1024 * 1024 * 1024) / (ulong)RadeonRaysAPI.BvhNodeSizeInBytes())
  443. throw new System.OutOfMemoryException("Out of memory in BLAS buffer");
  444. var newBlasBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, newBvhNodeCount, RadeonRaysAPI.BvhNodeSizeInBytes());
  445. GraphicsHelpers.CopyBuffer(m_CopyShader, m_BlasBuffer, 0, newBlasBuffer, 0, oldBvhNodeCount * RadeonRaysAPI.BvhNodeSizeInDwords());
  446. m_BlasBuffer.Dispose();
  447. m_BlasBuffer = newBlasBuffer;
  448. allocation = m_BlasAllocator.Allocate(allocationNodeCount);
  449. Assertions.Assert.IsTrue(allocation.valid);
  450. }
  451. return allocation;
  452. }
  453. uint m_HandleObfuscation = (uint)Random.Range(int.MinValue, int.MaxValue);
  454. int NewHandle()
  455. {
  456. if (m_FreeHandles.Count != 0)
  457. return (int)(m_FreeHandles.Dequeue() ^ m_HandleObfuscation);
  458. else
  459. return (int)((uint)m_RadeonInstances.Count ^ m_HandleObfuscation);
  460. }
  461. void ReleaseHandle(int handle)
  462. {
  463. m_FreeHandles.Enqueue((uint)handle ^ m_HandleObfuscation);
  464. }
  465. RadeonRaysAPI m_RadeonRaysAPI;
  466. RadeonRays.BuildFlags m_AccelStructBuildFlags = 0;
  467. #if UNITY_EDITOR
  468. bool m_UseCpuBuild = false;
  469. UnityEditor.Embree.GpuBvhBuildOptions m_CpuBuildOptions;
  470. #endif
  471. ReferenceCounter m_Counter;
  472. Dictionary<(int mesh, int subMeshIndex), MeshBlas> m_Blases;
  473. BlockAllocator m_BlasAllocator;
  474. GraphicsBuffer m_BlasBuffer;
  475. BLASPositionsPool m_BlasPositions;
  476. TopLevelAccelStruct? m_TopLevelAccelStruct = null;
  477. ComputeShader m_CopyShader;
  478. Dictionary<int, RadeonRaysInstance> m_RadeonInstances = new ();
  479. Queue<uint> m_FreeHandles = new();
  480. class RadeonRaysInstance
  481. {
  482. public (int mesh, int subMeshIndex) geomKey;
  483. public MeshBlas blas;
  484. public uint instanceMask;
  485. public bool triangleCullingEnabled;
  486. public bool invertTriangleCulling;
  487. public uint userInstanceID;
  488. public RadeonRays.Transform localToWorldTransform;
  489. }
  490. private class MeshBlas
  491. {
  492. public MeshBuildInfo buildInfo;
  493. public BlockAllocator.Allocation blasAllocation;
  494. public BlockAllocator.Allocation blasIndices;
  495. public BlockAllocator.Allocation blasVertices;
  496. #if UNITY_EDITOR
  497. public AABB aabbForCpuBuild;
  498. public List<int> indicesForCpuBuild;
  499. public List<Vector3> verticesForCpuBuild;
  500. #endif
  501. public bool bvhBuilt = false;
  502. private uint refCount = 0;
  503. public void IncRef() { refCount++; }
  504. public void DecRef() { refCount--; }
  505. public bool IsUnreferenced() { return refCount == 0; }
  506. }
  507. }
  508. }