LightGridLLReduction.bsl 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #include "$ENGINE$\PerCameraData.bslinc"
  2. #include "$ENGINE$\LightGridCommon.bslinc"
  3. Technique
  4. : inherits("PerCameraData")
  5. : inherits("LightGridCommon") =
  6. {
  7. Language = "HLSL11";
  8. Pass =
  9. {
  10. Compute =
  11. {
  12. Buffer<uint> gLightsLLHeads;
  13. Buffer<uint4> gLightsLL;
  14. Buffer<uint> gProbesLLHeads;
  15. Buffer<uint2> gProbesLL;
  16. [layout(r32ui)]
  17. RWBuffer<uint> gGridDataCounter;
  18. RWBuffer<uint4> gGridLightOffsetAndSize;
  19. RWBuffer<uint> gGridLightIndices;
  20. RWBuffer<uint2> gGridProbeOffsetAndSize;
  21. RWBuffer<uint> gGridProbeIndices;
  22. [numthreads(THREADGROUP_SIZE, THREADGROUP_SIZE, THREADGROUP_SIZE)]
  23. void main(
  24. uint3 groupId : SV_GroupID,
  25. uint3 groupThreadId : SV_GroupThreadID,
  26. uint3 dispatchThreadId : SV_DispatchThreadID)
  27. {
  28. // Ignore pixels out of valid range
  29. if (any(dispatchThreadId.xy >= gGridSize.xy))
  30. return;
  31. uint maxNumLinks = gNumCells * gMaxNumLightsPerCell;
  32. uint cellIdx = (dispatchThreadId.z * gGridSize.y + dispatchThreadId.y) * gGridSize.x + dispatchThreadId.x;
  33. // Reduce lights
  34. //// First count total number of lights affecting the tile
  35. uint currentIdx = gLightsLLHeads[cellIdx];
  36. uint numRadialLights = 0;
  37. uint numSpotLights = 0;
  38. while(currentIdx != 0xFFFFFFFF)
  39. {
  40. uint4 entry = gLightsLL[currentIdx];
  41. if(entry.y == 1) // Radial
  42. numRadialLights++;
  43. else // Spot
  44. numSpotLights++;
  45. currentIdx = entry.z;
  46. }
  47. //// Allocate enough room and remember the offset to indices
  48. uint numLights = numRadialLights + numSpotLights;
  49. uint indicesStart;
  50. InterlockedAdd(gGridDataCounter[0], numLights, indicesStart);
  51. gGridLightOffsetAndSize[cellIdx] = uint4(indicesStart, numRadialLights, numSpotLights, 0);
  52. //// Actually write light indices (reverse order, so that radial lights come first, as is the convention)
  53. currentIdx = gLightsLLHeads[cellIdx];
  54. uint lightIdx = 0;
  55. while(currentIdx != 0xFFFFFFFF)
  56. {
  57. uint4 entry = gLightsLL[currentIdx];
  58. gGridLightIndices[indicesStart + numLights - 1 - lightIdx] = entry.x;
  59. currentIdx = entry.z;
  60. lightIdx++;
  61. }
  62. // Reduce probes
  63. //// First count total number of probes affecting the tile
  64. currentIdx = gProbesLLHeads[cellIdx];
  65. uint numProbes = 0;
  66. while(currentIdx != 0xFFFFFFFF)
  67. {
  68. uint2 entry = gProbesLL[currentIdx];
  69. numProbes++;
  70. currentIdx = entry.y;
  71. }
  72. //// Allocate enough room and remember the offset to indices
  73. InterlockedAdd(gGridDataCounter[1], numProbes, indicesStart);
  74. gGridProbeOffsetAndSize[cellIdx] = uint2(indicesStart, numProbes);
  75. //// Actually write probe indices (reverse order, in order to restore original order since LL was formed in reverse)
  76. currentIdx = gProbesLLHeads[cellIdx];
  77. uint probeIdx = 0;
  78. while(currentIdx != 0xFFFFFFFF)
  79. {
  80. uint2 entry = gProbesLL[currentIdx];
  81. gGridProbeIndices[indicesStart + numProbes - 1 - probeIdx] = entry.x;
  82. currentIdx = entry.y;
  83. probeIdx++;
  84. }
  85. }
  86. };
  87. };
  88. };