暫無描述
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.

HlbvhTopLevelBuilder.cs 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using Unity.Mathematics;
  4. namespace UnityEngine.Rendering.RadeonRays
  5. {
  6. internal struct TopLevelAccelStruct : IDisposable
  7. {
  8. public const GraphicsBuffer.Target topLevelBvhTarget = GraphicsBuffer.Target.Structured;
  9. public const GraphicsBuffer.Target instanceInfoTarget = GraphicsBuffer.Target.Structured;
  10. public GraphicsBuffer topLevelBvh;
  11. public GraphicsBuffer bottomLevelBvhs;
  12. public GraphicsBuffer instanceInfos;
  13. public uint instanceCount;
  14. public void Dispose()
  15. {
  16. topLevelBvh?.Dispose();
  17. instanceInfos?.Dispose();
  18. }
  19. }
  20. internal class HlbvhTopLevelBuilder
  21. {
  22. private ComputeShader shaderBuildHlbvh;
  23. private int kernelInit;
  24. private int kernelCalculateAabb;
  25. private int kernelCalculateMortonCodes;
  26. private int kernelBuildTreeBottomUp;
  27. private int kernelClearUpdateFlags;
  28. private RadixSort radixSort;
  29. const uint kTrianglesPerThread = 8u;
  30. const uint kGroupSize = 256u;
  31. const uint kTrianglesPerGroup = kTrianglesPerThread * kGroupSize;
  32. public HlbvhTopLevelBuilder(RadeonRaysShaders shaders)
  33. {
  34. shaderBuildHlbvh = shaders.buildHlbvh;
  35. kernelInit = shaderBuildHlbvh.FindKernel("Init");
  36. kernelCalculateAabb = shaderBuildHlbvh.FindKernel("CalculateAabb");
  37. kernelCalculateMortonCodes = shaderBuildHlbvh.FindKernel("CalculateMortonCodes");
  38. kernelBuildTreeBottomUp = shaderBuildHlbvh.FindKernel("BuildTreeBottomUp");
  39. kernelClearUpdateFlags = shaderBuildHlbvh.FindKernel("ClearUpdateFlags");
  40. radixSort = new RadixSort(shaders);
  41. }
  42. public ulong GetScratchDataSizeInDwords(uint instanceCount)
  43. {
  44. var scratchLayout = GetScratchBufferLayout(instanceCount);
  45. return scratchLayout.TotalSize;
  46. }
  47. public static uint GetBvhNodeCount(uint leafCount)
  48. {
  49. return 2 * leafCount - 1;
  50. }
  51. public void AllocateResultBuffers(uint instanceCount, ref TopLevelAccelStruct accelStruct)
  52. {
  53. var bvhNodeCount = GetBvhNodeCount(instanceCount);
  54. accelStruct.Dispose();
  55. accelStruct.instanceInfos = new GraphicsBuffer(TopLevelAccelStruct.instanceInfoTarget, (int)instanceCount, Marshal.SizeOf<InstanceInfo>());
  56. accelStruct.topLevelBvh = new GraphicsBuffer(TopLevelAccelStruct.topLevelBvhTarget, (int)bvhNodeCount + 1, Marshal.SizeOf<BvhNode>()); // plus one for header
  57. }
  58. public void CreateEmpty(ref TopLevelAccelStruct accelStruct)
  59. {
  60. accelStruct.Dispose();
  61. accelStruct.topLevelBvh = new GraphicsBuffer(TopLevelAccelStruct.topLevelBvhTarget, (int)2, Marshal.SizeOf<BvhNode>());
  62. accelStruct.instanceInfos = accelStruct.topLevelBvh;
  63. accelStruct.bottomLevelBvhs = accelStruct.topLevelBvh;
  64. accelStruct.instanceCount = 0;
  65. var top = new BvhNode[2];
  66. top[0].child0 = 0;
  67. top[0].child1 = 0;
  68. top[0].parent = 0;
  69. top[1].child0 = 0;
  70. top[1].child1 = 0;
  71. top[1].parent = 0xFFFFFFFF;
  72. top[1].update = 0;
  73. top[1].aabb0_min = math.asuint(new float3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity));
  74. top[1].aabb0_max = math.asuint(new float3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity));
  75. top[1].aabb1_min = math.asuint(new float3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity));
  76. top[1].aabb1_max = math.asuint(new float3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity));
  77. accelStruct.topLevelBvh.SetData(top);
  78. }
  79. struct ScratchBufferOffsets
  80. {
  81. public uint Aabb;
  82. public uint MortonCodes;
  83. public uint PrimitiveRefs;
  84. public uint SortedMortonCodes;
  85. public uint SortedPrimitiveRefs;
  86. public uint SortMemory;
  87. public uint InternalNodeRange;
  88. public uint TotalSize;
  89. }
  90. public void Execute(CommandBuffer cmd, GraphicsBuffer scratch, ref TopLevelAccelStruct accelStruct)
  91. {
  92. Common.EnableKeyword(cmd, shaderBuildHlbvh, "TOP_LEVEL", true);
  93. Common.EnableKeyword(cmd, shaderBuildHlbvh, "NO_REDUCTION", true);
  94. uint instanceCount = accelStruct.instanceCount;
  95. var scratchLayout = GetScratchBufferLayout(instanceCount);
  96. cmd.SetComputeIntParam(shaderBuildHlbvh, SID.g_constants_vertex_stride, (int)0);
  97. cmd.SetComputeIntParam(shaderBuildHlbvh, SID.g_constants_triangle_count, (int)instanceCount);
  98. cmd.SetComputeIntParam(shaderBuildHlbvh, SID.g_bvh_offset, 0);
  99. cmd.SetComputeIntParam(shaderBuildHlbvh, SID.g_internal_node_range_offset, (int)scratchLayout.InternalNodeRange);
  100. BindKernelArguments(cmd, kernelInit, scratch, scratchLayout, accelStruct, false);
  101. cmd.DispatchCompute(shaderBuildHlbvh, kernelInit, 1, 1, 1);
  102. BindKernelArguments(cmd, kernelCalculateAabb, scratch, scratchLayout, accelStruct, false);
  103. cmd.DispatchCompute(shaderBuildHlbvh, kernelCalculateAabb, (int)Common.CeilDivide(instanceCount, kTrianglesPerGroup), 1, 1);
  104. BindKernelArguments(cmd, kernelCalculateMortonCodes, scratch, scratchLayout, accelStruct, false);
  105. cmd.DispatchCompute(shaderBuildHlbvh, kernelCalculateMortonCodes, (int)Common.CeilDivide(instanceCount, kTrianglesPerGroup), 1, 1);
  106. radixSort.Execute(cmd, scratch,
  107. scratchLayout.MortonCodes, scratchLayout.SortedMortonCodes,
  108. scratchLayout.PrimitiveRefs, scratchLayout.SortedPrimitiveRefs,
  109. scratchLayout.SortMemory, instanceCount);
  110. BindKernelArguments(cmd, kernelClearUpdateFlags, scratch, scratchLayout, accelStruct, true);
  111. cmd.DispatchCompute(shaderBuildHlbvh, kernelClearUpdateFlags, (int)Common.CeilDivide(instanceCount, kTrianglesPerGroup), 1, 1);
  112. BindKernelArguments(cmd, kernelBuildTreeBottomUp, scratch, scratchLayout, accelStruct, true);
  113. cmd.DispatchCompute(shaderBuildHlbvh, kernelBuildTreeBottomUp, (int)Common.CeilDivide(instanceCount, kTrianglesPerGroup), 1, 1);
  114. }
  115. private ScratchBufferOffsets cachedScratchOffsets;
  116. private uint cachedInstanceCount = 0;
  117. ScratchBufferOffsets GetScratchBufferLayout(uint instanceCount)
  118. {
  119. if (cachedInstanceCount == instanceCount)
  120. {
  121. return cachedScratchOffsets;
  122. }
  123. var result = new ScratchBufferOffsets();
  124. uint offset = 0;
  125. result.Aabb = offset;
  126. offset += 6;
  127. result.MortonCodes = offset;
  128. offset += instanceCount;
  129. result.PrimitiveRefs = offset;
  130. offset += instanceCount;
  131. result.SortedMortonCodes = offset;
  132. offset += instanceCount;
  133. result.SortedPrimitiveRefs = offset;
  134. offset += instanceCount;
  135. result.SortMemory = offset;
  136. offset += (uint)radixSort.GetScratchDataSizeInDwords(instanceCount);
  137. result.TotalSize = offset;
  138. // overlaps with MortonCodes and PrimitiveRefs
  139. result.InternalNodeRange = result.MortonCodes;
  140. cachedScratchOffsets = result;
  141. cachedInstanceCount = instanceCount;
  142. return result;
  143. }
  144. private void BindKernelArguments(
  145. CommandBuffer cmd,
  146. int kernel,
  147. GraphicsBuffer scratch,
  148. ScratchBufferOffsets scratchLayout,
  149. TopLevelAccelStruct accelStruct,
  150. bool setSortedCodes)
  151. {
  152. cmd.SetComputeBufferParam(shaderBuildHlbvh, kernel, SID.g_scratch_buffer, scratch);
  153. cmd.SetComputeBufferParam(shaderBuildHlbvh, kernel, SID.g_bvh, accelStruct.topLevelBvh);
  154. cmd.SetComputeBufferParam(shaderBuildHlbvh, kernel, SID.g_bottom_bvhs, accelStruct.bottomLevelBvhs);
  155. cmd.SetComputeBufferParam(shaderBuildHlbvh, kernel, SID.g_instance_infos, accelStruct.instanceInfos);
  156. cmd.SetComputeIntParam(shaderBuildHlbvh, SID.g_aabb_offset, (int)scratchLayout.Aabb);
  157. if (setSortedCodes)
  158. {
  159. cmd.SetComputeIntParam(shaderBuildHlbvh, SID.g_morton_codes_offset, (int)scratchLayout.SortedMortonCodes);
  160. cmd.SetComputeIntParam(shaderBuildHlbvh, SID.g_primitive_refs_offset, (int)scratchLayout.SortedPrimitiveRefs);
  161. }
  162. else
  163. {
  164. cmd.SetComputeIntParam(shaderBuildHlbvh, SID.g_morton_codes_offset, (int)scratchLayout.MortonCodes);
  165. cmd.SetComputeIntParam(shaderBuildHlbvh, SID.g_primitive_refs_offset, (int)scratchLayout.PrimitiveRefs);
  166. }
  167. }
  168. }
  169. }