LightGridLLReduction.bsl 2.9 KB

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