Ei kuvausta
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.

RestructureBvh.cs 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. using System;
  2. using System.IO;
  3. using System.Runtime.InteropServices;
  4. using Unity.Mathematics;
  5. namespace UnityEngine.Rendering.RadeonRays
  6. {
  7. internal class RestructureBvh : IDisposable
  8. {
  9. private ComputeShader shader;
  10. private int kernelInitPrimitiveCounts;
  11. private int kernelFindTreeletRoots;
  12. private int kernelRestructure;
  13. private int kernelPrepareTreeletsDispatchSize;
  14. private int numIterations = 3;
  15. public GraphicsBuffer treeletDispatchIndirectBuffer;
  16. const uint kGroupSize = 256u;
  17. const uint kTrianglesPerThread = 8u;
  18. const uint kTrianglesPerGroup = kTrianglesPerThread * kGroupSize;
  19. const uint kMinPrimitivesPerTreelet = 64u;
  20. private const int kMaxThreadGroupsPerDispatch = 65535;
  21. public RestructureBvh(RadeonRaysShaders shaders)
  22. {
  23. shader = shaders.restructureBvh;
  24. kernelInitPrimitiveCounts = shader.FindKernel("InitPrimitiveCounts");
  25. kernelFindTreeletRoots = shader.FindKernel("FindTreeletRoots");
  26. kernelRestructure = shader.FindKernel("Restructure");
  27. kernelPrepareTreeletsDispatchSize = shader.FindKernel("PrepareTreeletsDispatchSize");
  28. treeletDispatchIndirectBuffer = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments, 6, sizeof(uint));
  29. }
  30. public void Dispose()
  31. {
  32. treeletDispatchIndirectBuffer.Dispose();
  33. }
  34. public ulong GetScratchDataSizeInDwords(uint triangleCount)
  35. {
  36. var scratchLayout = GetScratchBufferLayout(triangleCount);
  37. return scratchLayout.TotalSize;
  38. }
  39. public static uint GetBvhNodeCount(uint leafCount)
  40. {
  41. return 2 * leafCount - 1;
  42. }
  43. public void Execute(
  44. CommandBuffer cmd,
  45. GraphicsBuffer vertices, int verticesOffset, uint vertexStride,
  46. GraphicsBuffer indices, int indicesOffset, uint triangleCount,
  47. GraphicsBuffer scratch, GraphicsBuffer result, uint resultOffset, string objName = null)
  48. {
  49. var scratchLayout = GetScratchBufferLayout(triangleCount);
  50. Common.EnableKeyword(cmd, shader, "TOP_LEVEL", false);
  51. cmd.SetComputeIntParam(shader, SID.g_indices_offset, indicesOffset);
  52. cmd.SetComputeIntParam(shader, SID.g_vertices_offset, verticesOffset);
  53. cmd.SetComputeIntParam(shader, SID.g_constants_vertex_stride, (int)vertexStride);
  54. cmd.SetComputeIntParam(shader, SID.g_constants_triangle_count, (int)triangleCount);
  55. cmd.SetComputeIntParam(shader, SID.g_treelet_count_offset, (int)scratchLayout.TreeletCount);
  56. cmd.SetComputeIntParam(shader, SID.g_treelet_roots_offset, (int)scratchLayout.TreeletRoots);
  57. cmd.SetComputeIntParam(shader, SID.g_primitive_counts_offset, (int)scratchLayout.PrimitiveCounts);
  58. cmd.SetComputeIntParam(shader, SID.g_bvh_offset, (int)resultOffset);
  59. uint minPrimitivePerTreelet = kMinPrimitivesPerTreelet;
  60. for (int i = 0; i < numIterations; ++i)
  61. {
  62. cmd.SetComputeIntParam(shader, SID.g_constants_min_prims_per_treelet, (int)minPrimitivePerTreelet);
  63. BindKernelArguments(cmd, kernelInitPrimitiveCounts, vertices, indices, scratch, result);
  64. cmd.DispatchCompute(shader, kernelInitPrimitiveCounts, (int)Common.CeilDivide(kTrianglesPerGroup, kGroupSize), 1, 1);
  65. BindKernelArguments(cmd, kernelFindTreeletRoots, vertices, indices, scratch, result);
  66. cmd.DispatchCompute(shader, kernelFindTreeletRoots, (int)Common.CeilDivide(kTrianglesPerGroup, kGroupSize), 1, 1);
  67. BindKernelArguments(cmd, kernelPrepareTreeletsDispatchSize, vertices, indices, scratch, result);
  68. cmd.DispatchCompute(shader, kernelPrepareTreeletsDispatchSize, 1, 1, 1);
  69. BindKernelArguments(cmd, kernelRestructure, vertices, indices, scratch, result);
  70. cmd.SetComputeIntParam(shader, SID.g_remainder_treelets, 0);
  71. cmd.DispatchCompute(shader, kernelRestructure, treeletDispatchIndirectBuffer, 0);
  72. if (Common.CeilDivide(triangleCount, minPrimitivePerTreelet) > kMaxThreadGroupsPerDispatch)
  73. {
  74. cmd.SetComputeIntParam(shader, SID.g_remainder_treelets, 1);
  75. cmd.DispatchCompute(shader, kernelRestructure, treeletDispatchIndirectBuffer, 3 * sizeof(uint));
  76. }
  77. minPrimitivePerTreelet *= 2;
  78. }
  79. }
  80. private void BindKernelArguments(
  81. CommandBuffer cmd, int kernel,
  82. GraphicsBuffer vertices, GraphicsBuffer indices,
  83. GraphicsBuffer scratch, GraphicsBuffer result)
  84. {
  85. cmd.SetComputeBufferParam(shader, kernel, SID.g_vertices, vertices);
  86. cmd.SetComputeBufferParam(shader, kernel, SID.g_indices, indices);
  87. cmd.SetComputeBufferParam(shader, kernel, SID.g_scratch_buffer, scratch);
  88. cmd.SetComputeBufferParam(shader, kernel, SID.g_bvh, result);
  89. cmd.SetComputeBufferParam(shader, kernel, SID.g_treelet_dispatch_buffer, treeletDispatchIndirectBuffer);
  90. }
  91. struct ScratchBufferOffsets
  92. {
  93. public uint TreeletCount;
  94. public uint TreeletRoots;
  95. public uint PrimitiveCounts;
  96. public uint TotalSize;
  97. }
  98. ScratchBufferOffsets GetScratchBufferLayout(uint triangleCount)
  99. {
  100. var result = new ScratchBufferOffsets();
  101. uint offset = 0;
  102. result.TreeletCount = offset;
  103. offset += 1;
  104. result.TreeletRoots = offset;
  105. offset += triangleCount;
  106. result.PrimitiveCounts = offset;
  107. offset += GetBvhNodeCount(triangleCount);
  108. result.TotalSize = offset;
  109. return result;
  110. }
  111. }
  112. }