LightGridLLReduction.bsl 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #include "$ENGINE$\PerCameraData.bslinc"
  2. Technique : inherits("PerCameraData") =
  3. {
  4. Language = "HLSL11";
  5. Pass =
  6. {
  7. Compute =
  8. {
  9. cbuffer Params : register(b0)
  10. {
  11. // Offsets at which specific light types begin in gLights buffer
  12. // Assumed directional lights start at 0
  13. // x - offset to point lights, y - offset to spot lights, z - total number of lights
  14. uint3 gLightOffsets;
  15. uint gNumCells;
  16. uint3 gGridSize;
  17. uint gMaxNumLightsPerCell;
  18. }
  19. Buffer<uint> gLinkedListHeads : register(t0);
  20. Buffer<uint2> gLinkedList : register(t1);
  21. RWBuffer<uint> gGridDataCounter : register(u0);
  22. RWBuffer<uint2> gGridLightOffsetAndSize : register(u1);
  23. RWBuffer<uint> gGridLightIndices : register(u2);
  24. [numthreads(THREADGROUP_SIZE, THREADGROUP_SIZE, THREADGROUP_SIZE)]
  25. void main(
  26. uint3 groupId : SV_GroupID,
  27. uint3 groupThreadId : SV_GroupThreadID,
  28. uint3 dispatchThreadId : SV_DispatchThreadID)
  29. {
  30. uint2 viewportMax = gViewportRectangle.xy + gViewportRectangle.zw;
  31. // Ignore pixels out of valid range
  32. if (all(dispatchThreadId.xy >= viewportMax))
  33. return;
  34. uint maxNumLinks = gNumCells * gMaxNumLightsPerCell;
  35. uint cellIdx = (dispatchThreadId.z * gGridSize.y + dispatchThreadId.y) * gGridSize.x + dispatchThreadId.x;
  36. // First count total number of lights affecting the tile
  37. uint currentIdx = gLinkedListHeads[cellIdx];
  38. uint numLights = 0;
  39. while(currentIdx != 0xFFFFFFFF)
  40. {
  41. numLights++;
  42. currentIdx = gLinkedList[currentIdx].y;
  43. }
  44. // Allocate enough room and remember the offset to indices
  45. uint indicesStart;
  46. InterlockedAdd(gGridDataCounter[0], numLights, indicesStart);
  47. gGridLightOffsetAndSize[cellIdx] = uint2(indicesStart, numLights);
  48. // Actually write light indices
  49. // Note: Values are written in the reverse order than they were found in
  50. currentIdx = gLinkedListHeads[cellIdx];
  51. uint lightIdx = 0;
  52. while(currentIdx != 0xFFFFFFFF)
  53. {
  54. uint2 entry = gLinkedList[currentIdx];
  55. gGridLightIndices[indicesStart + lightIdx] = entry.x;
  56. currentIdx = entry.y;
  57. lightIdx++;
  58. }
  59. }
  60. };
  61. };
  62. };
  63. Technique : inherits("PerCameraData") =
  64. {
  65. Language = "GLSL";
  66. Pass =
  67. {
  68. Compute =
  69. {
  70. layout (local_size_x = THREADGROUP_SIZE, local_size_y = THREADGROUP_SIZE, local_size_z = THREADGROUP_SIZE) in;
  71. layout(binding = 0, std140) uniform Params
  72. {
  73. // Offsets at which specific light types begin in gLights buffer
  74. // Assumed directional lights start at 0
  75. // x - offset to point lights, y - offset to spot lights, z - total number of lights
  76. uvec3 gLightOffsets;
  77. uint gNumCells;
  78. uvec3 gGridSize;
  79. uint gMaxNumLightsPerCell;
  80. };
  81. layout(binding = 1) uniform usamplerBuffer gLinkedListHeads;
  82. layout(binding = 2) uniform usamplerBuffer gLinkedList;
  83. layout(binding = 3, r32ui) uniform uimageBuffer gGridDataCounter;
  84. layout(binding = 4, rg32ui) uniform uimageBuffer gGridLightOffsetAndSize;
  85. layout(binding = 5, r32ui) uniform uimageBuffer gGridLightIndices;
  86. void main()
  87. {
  88. uvec2 viewportMax = gViewportRectangle.xy + gViewportRectangle.zw;
  89. // Ignore pixels out of valid range
  90. if (all(greaterThanEqual(gl_GlobalInvocationID.xy, viewportMax)))
  91. return;
  92. uint maxNumLinks = gNumCells * gMaxNumLightsPerCell;
  93. int cellIdx = int((gl_GlobalInvocationID.z * gGridSize.y + gl_GlobalInvocationID.y) * gGridSize.x + gl_GlobalInvocationID.x);
  94. // First count total number of lights affecting the tile
  95. int currentIdx = int(texelFetch(gLinkedListHeads, cellIdx).x);
  96. uint numLights = 0;
  97. while(currentIdx != 0xFFFFFFFF)
  98. {
  99. numLights++;
  100. currentIdx = int(texelFetch(gLinkedList, currentIdx).y);
  101. }
  102. // Allocate enough room and remember the offset to indices
  103. uint indicesStart = imageAtomicAdd(gGridDataCounter, 0, numLights);
  104. imageStore(gGridLightOffsetAndSize, cellIdx, uvec4(indicesStart, numLights, 0, 0));
  105. // Actually write light indices
  106. // Note: Values are written in the reverse order than they were found in
  107. currentIdx = int(texelFetch(gLinkedListHeads, cellIdx).x);
  108. uint lightIdx = 0;
  109. while(currentIdx != 0xFFFFFFFF)
  110. {
  111. uvec2 entry = texelFetch(gLinkedList, currentIdx).xy;
  112. imageStore(gGridLightIndices, int(indicesStart + lightIdx), uvec4(entry.x, 0, 0, 0));
  113. currentIdx = int(entry.y);
  114. lightIdx++;
  115. }
  116. }
  117. };
  118. };
  119. };