LightGridLLReduction.bsl 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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> gLinkedListHeads : register(t0);
  13. Buffer<uint4> gLinkedList : register(t1);
  14. RWBuffer<uint> gGridDataCounter : register(u0);
  15. RWBuffer<uint4> gGridLightOffsetAndSize : register(u1);
  16. RWBuffer<uint> gGridLightIndices : register(u2);
  17. [numthreads(THREADGROUP_SIZE, THREADGROUP_SIZE, THREADGROUP_SIZE)]
  18. void main(
  19. uint3 groupId : SV_GroupID,
  20. uint3 groupThreadId : SV_GroupThreadID,
  21. uint3 dispatchThreadId : SV_DispatchThreadID)
  22. {
  23. // Ignore pixels out of valid range
  24. if (any(dispatchThreadId.xy >= gGridSize.xy))
  25. return;
  26. uint maxNumLinks = gNumCells * gMaxNumLightsPerCell;
  27. uint cellIdx = (dispatchThreadId.z * gGridSize.y + dispatchThreadId.y) * gGridSize.x + dispatchThreadId.x;
  28. // First count total number of lights affecting the tile
  29. uint currentIdx = gLinkedListHeads[cellIdx];
  30. uint numRadialLights = 0;
  31. uint numSpotLights = 0;
  32. while(currentIdx != 0xFFFFFFFF)
  33. {
  34. uint4 entry = gLinkedList[currentIdx];
  35. if(entry.y == 1) // Radial
  36. numRadialLights++;
  37. else // Spot
  38. numSpotLights++;
  39. currentIdx = entry.z;
  40. }
  41. // Allocate enough room and remember the offset to indices
  42. uint numLights = numRadialLights + numSpotLights;
  43. uint indicesStart;
  44. InterlockedAdd(gGridDataCounter[0], numLights, indicesStart);
  45. gGridLightOffsetAndSize[cellIdx] = uint4(indicesStart, numRadialLights, numSpotLights, 0);
  46. // Actually write light indices (reverse order, so that radial lights come first, as is the convention)
  47. currentIdx = gLinkedListHeads[cellIdx];
  48. uint lightIdx = 0;
  49. while(currentIdx != 0xFFFFFFFF)
  50. {
  51. uint4 entry = gLinkedList[currentIdx];
  52. gGridLightIndices[indicesStart + numLights - 1 - lightIdx] = entry.x;
  53. currentIdx = entry.z;
  54. lightIdx++;
  55. }
  56. }
  57. };
  58. };
  59. };
  60. Technique
  61. : inherits("PerCameraData")
  62. : inherits("LightGridCommon") =
  63. {
  64. Language = "GLSL";
  65. Pass =
  66. {
  67. Compute =
  68. {
  69. layout (local_size_x = THREADGROUP_SIZE, local_size_y = THREADGROUP_SIZE, local_size_z = THREADGROUP_SIZE) in;
  70. layout(binding = 1) uniform usamplerBuffer gLinkedListHeads;
  71. layout(binding = 2) uniform usamplerBuffer gLinkedList;
  72. layout(binding = 3, r32ui) uniform uimageBuffer gGridDataCounter;
  73. layout(binding = 5, rgba32ui) uniform uimageBuffer gGridLightOffsetAndSize;
  74. layout(binding = 6, r32ui) uniform uimageBuffer gGridLightIndices;
  75. void main()
  76. {
  77. // Ignore pixels out of valid range
  78. if (any(greaterThanEqual(gl_GlobalInvocationID.xy, gGridSize.xy)))
  79. return;
  80. uint maxNumLinks = gNumCells * gMaxNumLightsPerCell;
  81. int cellIdx = int((gl_GlobalInvocationID.z * gGridSize.y + gl_GlobalInvocationID.y) * gGridSize.x + gl_GlobalInvocationID.x);
  82. // First count total number of lights affecting the tile
  83. int currentIdx = int(texelFetch(gLinkedListHeads, cellIdx).x);
  84. uint numRadialLights = 0;
  85. uint numSpotLights = 0;
  86. while(currentIdx != 0xFFFFFFFF)
  87. {
  88. uvec3 entry = texelFetch(gLinkedList, currentIdx).xyz;
  89. if(entry.y == 1) // Radial
  90. numRadialLights++;
  91. else // Spot
  92. numSpotLights++;
  93. currentIdx = int(entry.z);
  94. }
  95. // Allocate enough room and remember the offset to indices
  96. uint numLights = numRadialLights + numSpotLights;
  97. uint indicesStart = imageAtomicAdd(gGridDataCounter, 0, numLights);
  98. imageStore(gGridLightOffsetAndSize, cellIdx, uvec4(indicesStart, numRadialLights, numSpotLights, 0));
  99. // Actually write light indices (reverse order, so that radial lights come first, as is the convention)
  100. currentIdx = int(texelFetch(gLinkedListHeads, cellIdx).x);
  101. uint lightIdx = 0;
  102. while(currentIdx != 0xFFFFFFFF)
  103. {
  104. uvec3 entry = texelFetch(gLinkedList, currentIdx).xyz;
  105. imageStore(gGridLightIndices, int(indicesStart + numLights - 1 - lightIdx), uvec4(entry.x, 0, 0, 0));
  106. currentIdx = int(entry.z);
  107. lightIdx++;
  108. }
  109. }
  110. };
  111. };
  112. };