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.

AccelStructInstances.cs 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. using System;
  2. using System.Collections.Generic;
  3. using Unity.Mathematics;
  4. using UnityEngine.Assertions;
  5. namespace UnityEngine.Rendering.UnifiedRayTracing
  6. {
  7. internal class AccelStructInstances : IDisposable
  8. {
  9. internal AccelStructInstances(GeometryPool geometryPool)
  10. {
  11. m_GeometryPool = geometryPool;
  12. }
  13. public void Dispose()
  14. {
  15. foreach (InstanceEntry instanceEntry in m_Instances.Values)
  16. {
  17. GeometryPoolHandle geomHandle = instanceEntry.geometryPoolHandle;
  18. m_GeometryPool.Unregister(geomHandle);
  19. }
  20. m_GeometryPool.SendGpuCommands();
  21. m_InstanceBuffer?.Dispose();
  22. m_GeometryPool.Dispose();
  23. }
  24. public PersistentGpuArray<RTInstance> instanceBuffer { get => m_InstanceBuffer; }
  25. public IReadOnlyCollection<InstanceEntry> instances { get => m_Instances.Values; }
  26. public GeometryPool geometryPool { get => m_GeometryPool; }
  27. public int AddInstance(MeshInstanceDesc meshInstance, uint materialID)
  28. {
  29. if (meshInstance.mesh == null)
  30. throw new System.ArgumentException("targetRenderer.mesh is null");
  31. GeometryPoolHandle geometryHandle;
  32. if (!m_GeometryPool.Register(meshInstance.mesh, out geometryHandle))
  33. throw new System.InvalidOperationException("Failed to allocate geometry data for instance");
  34. m_GeometryPool.SendGpuCommands();
  35. var slotAllocation = m_InstanceBuffer.Add(
  36. new RTInstance
  37. {
  38. localToWorld = meshInstance.localToWorldMatrix,
  39. localToWorldNormals = NormalMatrix(meshInstance.localToWorldMatrix),
  40. previousLocalToWorld = meshInstance.localToWorldMatrix,
  41. userMaterialID = materialID,
  42. instanceMask = meshInstance.mask,
  43. userInstanceID = meshInstance.instanceID,
  44. geometryIndex = (uint)(m_GeometryPool.GetEntryGeomAllocation(geometryHandle).meshChunkTableAlloc.block.offset + meshInstance.subMeshIndex)
  45. });
  46. var allocInfo = m_GeometryPool.GetEntryGeomAllocation(geometryHandle).meshChunks[meshInstance.subMeshIndex];
  47. var instanceEntry = new InstanceEntry
  48. {
  49. geometryPoolHandle = geometryHandle,
  50. indexInInstanceBuffer = slotAllocation,
  51. instanceMask = meshInstance.mask,
  52. vertexOffset = (uint)(allocInfo.vertexAlloc.block.offset) * ((uint)GeometryPool.GetVertexByteSize() / 4),
  53. indexOffset = (uint)allocInfo.indexAlloc.block.offset,
  54. };
  55. m_Instances.Add(slotAllocation.block.offset, instanceEntry);
  56. return slotAllocation.block.offset;
  57. }
  58. public GeometryPool.MeshChunk GetEntryGeomAllocation(GeometryPoolHandle handle, int submeshIndex)
  59. {
  60. return m_GeometryPool.GetEntryGeomAllocation(handle).meshChunks[submeshIndex];
  61. }
  62. public GraphicsBuffer indexBuffer { get { return m_GeometryPool.globalIndexBuffer; } }
  63. public GraphicsBuffer vertexBuffer { get { return m_GeometryPool.globalVertexBuffer; } }
  64. public void RemoveInstance(int instanceHandle)
  65. {
  66. bool success = m_Instances.TryGetValue(instanceHandle, out InstanceEntry removedEntry);
  67. Assert.IsTrue(success);
  68. m_Instances.Remove(instanceHandle);
  69. m_InstanceBuffer.Remove(removedEntry.indexInInstanceBuffer);
  70. var geomHandle = removedEntry.geometryPoolHandle;
  71. m_GeometryPool.Unregister(geomHandle);
  72. m_GeometryPool.SendGpuCommands();
  73. }
  74. public void ClearInstances()
  75. {
  76. foreach (InstanceEntry instanceEntry in m_Instances.Values)
  77. {
  78. GeometryPoolHandle geomHandle = instanceEntry.geometryPoolHandle;
  79. m_GeometryPool.Unregister(geomHandle);
  80. }
  81. m_GeometryPool.SendGpuCommands();
  82. m_Instances.Clear();
  83. m_InstanceBuffer.Clear();
  84. }
  85. public void UpdateInstanceTransform(int instanceHandle, Matrix4x4 localToWorldMatrix)
  86. {
  87. bool success = m_Instances.TryGetValue(instanceHandle, out InstanceEntry instanceEntry);
  88. Assert.IsTrue(success);
  89. var instanceInfo = m_InstanceBuffer.Get(instanceEntry.indexInInstanceBuffer);
  90. instanceInfo.localToWorld = localToWorldMatrix;
  91. instanceInfo.localToWorldNormals = NormalMatrix(localToWorldMatrix);
  92. m_InstanceBuffer.Set(instanceEntry.indexInInstanceBuffer, instanceInfo);
  93. m_TransformTouchedLastTimestamp = m_FrameTimestamp;
  94. }
  95. public void UpdateInstanceMaterialID(int instanceHandle, uint materialID)
  96. {
  97. InstanceEntry instanceEntry;
  98. bool success = m_Instances.TryGetValue(instanceHandle, out instanceEntry);
  99. Assert.IsTrue(success);
  100. var instanceInfo = m_InstanceBuffer.Get(instanceEntry.indexInInstanceBuffer);
  101. instanceInfo.userMaterialID = materialID;
  102. m_InstanceBuffer.Set(instanceEntry.indexInInstanceBuffer, instanceInfo);
  103. }
  104. public void UpdateInstanceID(int instanceHandle, uint instanceID)
  105. {
  106. InstanceEntry instanceEntry;
  107. bool success = m_Instances.TryGetValue(instanceHandle, out instanceEntry);
  108. Assert.IsTrue(success);
  109. var instanceInfo = m_InstanceBuffer.Get(instanceEntry.indexInInstanceBuffer);
  110. instanceInfo.userInstanceID = instanceID;
  111. m_InstanceBuffer.Set(instanceEntry.indexInInstanceBuffer, instanceInfo);
  112. }
  113. public void UpdateInstanceMask(int instanceHandle, uint mask)
  114. {
  115. bool success = m_Instances.TryGetValue(instanceHandle, out InstanceEntry instanceEntry);
  116. Assert.IsTrue(success);
  117. instanceEntry.instanceMask = mask;
  118. var instanceInfo = m_InstanceBuffer.Get(instanceEntry.indexInInstanceBuffer);
  119. instanceInfo.instanceMask = mask;
  120. m_InstanceBuffer.Set(instanceEntry.indexInInstanceBuffer, instanceInfo);
  121. }
  122. public void NextFrame()
  123. {
  124. if ((m_FrameTimestamp - m_TransformTouchedLastTimestamp) <= 1)
  125. {
  126. m_InstanceBuffer.ModifyForEach(
  127. instance =>
  128. {
  129. instance.previousLocalToWorld = instance.localToWorld;
  130. return instance;
  131. });
  132. }
  133. m_FrameTimestamp++;
  134. }
  135. public bool instanceListValid => m_InstanceBuffer != null;
  136. public void Bind(CommandBuffer cmd, IRayTracingShader shader)
  137. {
  138. var gpuBuffer = m_InstanceBuffer.GetGpuBuffer(cmd);
  139. shader.SetBufferParam(cmd, Shader.PropertyToID("g_AccelStructInstanceList"), gpuBuffer);
  140. shader.SetBufferParam(cmd, Shader.PropertyToID("g_globalIndexBuffer"), m_GeometryPool.globalIndexBuffer);
  141. shader.SetBufferParam(cmd, Shader.PropertyToID("g_globalVertexBuffer"), m_GeometryPool.globalVertexBuffer);
  142. shader.SetIntParam(cmd, Shader.PropertyToID("g_globalVertexBufferStride"), m_GeometryPool.globalVertexBufferStrideBytes/4);
  143. shader.SetBufferParam(cmd, Shader.PropertyToID("g_MeshList"), m_GeometryPool.globalMeshChunkTableEntryBuffer);
  144. }
  145. public int GetInstanceCount()
  146. {
  147. return m_Instances.Count;
  148. }
  149. static private float4x4 NormalMatrix(float4x4 m)
  150. {
  151. float3x3 t = new float3x3(m);
  152. return new float4x4(math.inverse(math.transpose(t)), new float3(0.0));
  153. }
  154. GeometryPool m_GeometryPool;
  155. PersistentGpuArray<RTInstance> m_InstanceBuffer = new PersistentGpuArray<RTInstance>(100);
  156. public struct RTInstance
  157. {
  158. public float4x4 localToWorld;
  159. public float4x4 previousLocalToWorld;
  160. public float4x4 localToWorldNormals;
  161. public uint userInstanceID;
  162. public uint instanceMask;
  163. public uint userMaterialID;
  164. public uint geometryIndex;
  165. };
  166. public class InstanceEntry
  167. {
  168. public GeometryPoolHandle geometryPoolHandle;
  169. public BlockAllocator.Allocation indexInInstanceBuffer;
  170. public uint instanceMask;
  171. public uint vertexOffset;
  172. public uint indexOffset;
  173. }
  174. Dictionary<int, InstanceEntry> m_Instances = new Dictionary<int, InstanceEntry>();
  175. uint m_FrameTimestamp = 0;
  176. uint m_TransformTouchedLastTimestamp = 0;
  177. }
  178. }