LightGridLLReduction.bsl 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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. RWBuffer<uint> gGridDataCounter;
  17. RWBuffer<uint4> gGridLightOffsetAndSize;
  18. RWBuffer<uint> gGridLightIndices;
  19. RWBuffer<uint2> gGridProbeOffsetAndSize;
  20. RWBuffer<uint> gGridProbeIndices;
  21. [numthreads(THREADGROUP_SIZE, THREADGROUP_SIZE, THREADGROUP_SIZE)]
  22. void main(
  23. uint3 groupId : SV_GroupID,
  24. uint3 groupThreadId : SV_GroupThreadID,
  25. uint3 dispatchThreadId : SV_DispatchThreadID)
  26. {
  27. // Ignore pixels out of valid range
  28. if (any(dispatchThreadId.xy >= gGridSize.xy))
  29. return;
  30. uint maxNumLinks = gNumCells * gMaxNumLightsPerCell;
  31. uint cellIdx = (dispatchThreadId.z * gGridSize.y + dispatchThreadId.y) * gGridSize.x + dispatchThreadId.x;
  32. // Reduce lights
  33. //// First count total number of lights affecting the tile
  34. uint currentIdx = gLightsLLHeads[cellIdx];
  35. uint numRadialLights = 0;
  36. uint numSpotLights = 0;
  37. while(currentIdx != 0xFFFFFFFF)
  38. {
  39. uint4 entry = gLightsLL[currentIdx];
  40. if(entry.y == 1) // Radial
  41. numRadialLights++;
  42. else // Spot
  43. numSpotLights++;
  44. currentIdx = entry.z;
  45. }
  46. //// Allocate enough room and remember the offset to indices
  47. uint numLights = numRadialLights + numSpotLights;
  48. uint indicesStart;
  49. InterlockedAdd(gGridDataCounter[0], numLights, indicesStart);
  50. gGridLightOffsetAndSize[cellIdx] = uint4(indicesStart, numRadialLights, numSpotLights, 0);
  51. //// Actually write light indices (reverse order, so that radial lights come first, as is the convention)
  52. currentIdx = gLightsLLHeads[cellIdx];
  53. uint lightIdx = 0;
  54. while(currentIdx != 0xFFFFFFFF)
  55. {
  56. uint4 entry = gLightsLL[currentIdx];
  57. gGridLightIndices[indicesStart + numLights - 1 - lightIdx] = entry.x;
  58. currentIdx = entry.z;
  59. lightIdx++;
  60. }
  61. // Reduce probes
  62. //// First count total number of probes affecting the tile
  63. currentIdx = gProbesLLHeads[cellIdx];
  64. uint numProbes = 0;
  65. while(currentIdx != 0xFFFFFFFF)
  66. {
  67. uint2 entry = gProbesLL[currentIdx];
  68. numProbes++;
  69. currentIdx = entry.y;
  70. }
  71. //// Allocate enough room and remember the offset to indices
  72. InterlockedAdd(gGridDataCounter[1], numProbes, indicesStart);
  73. gGridProbeOffsetAndSize[cellIdx] = uint2(indicesStart, numProbes);
  74. //// Actually write probe indices (reverse order, in order to restore original order since LL was formed in reverse)
  75. currentIdx = gProbesLLHeads[cellIdx];
  76. uint probeIdx = 0;
  77. while(currentIdx != 0xFFFFFFFF)
  78. {
  79. uint2 entry = gProbesLL[currentIdx];
  80. gGridProbeIndices[indicesStart + numProbes - 1 - probeIdx] = entry.x;
  81. currentIdx = entry.y;
  82. probeIdx++;
  83. }
  84. }
  85. };
  86. };
  87. };
  88. Technique
  89. : inherits("PerCameraData")
  90. : inherits("LightGridCommon") =
  91. {
  92. Language = "GLSL";
  93. Pass =
  94. {
  95. Compute =
  96. {
  97. layout (local_size_x = THREADGROUP_SIZE, local_size_y = THREADGROUP_SIZE, local_size_z = THREADGROUP_SIZE) in;
  98. layout(binding = 1) uniform usamplerBuffer gLinkedListHeads;
  99. layout(binding = 2) uniform usamplerBuffer gLinkedList;
  100. layout(binding = 3, r32ui) uniform uimageBuffer gGridDataCounter;
  101. layout(binding = 5, rgba32ui) uniform uimageBuffer gGridLightOffsetAndSize;
  102. layout(binding = 6, r32ui) uniform uimageBuffer gGridLightIndices;
  103. void main()
  104. {
  105. // Ignore pixels out of valid range
  106. if (any(greaterThanEqual(gl_GlobalInvocationID.xy, gGridSize.xy)))
  107. return;
  108. uint maxNumLinks = gNumCells * gMaxNumLightsPerCell;
  109. int cellIdx = int((gl_GlobalInvocationID.z * gGridSize.y + gl_GlobalInvocationID.y) * gGridSize.x + gl_GlobalInvocationID.x);
  110. // First count total number of lights affecting the tile
  111. int currentIdx = int(texelFetch(gLinkedListHeads, cellIdx).x);
  112. uint numRadialLights = 0;
  113. uint numSpotLights = 0;
  114. while(currentIdx != 0xFFFFFFFF)
  115. {
  116. uvec3 entry = texelFetch(gLinkedList, currentIdx).xyz;
  117. if(entry.y == 1) // Radial
  118. numRadialLights++;
  119. else // Spot
  120. numSpotLights++;
  121. currentIdx = int(entry.z);
  122. }
  123. // Allocate enough room and remember the offset to indices
  124. uint numLights = numRadialLights + numSpotLights;
  125. uint indicesStart = imageAtomicAdd(gGridDataCounter, 0, numLights);
  126. imageStore(gGridLightOffsetAndSize, cellIdx, uvec4(indicesStart, numRadialLights, numSpotLights, 0));
  127. // Actually write light indices (reverse order, so that radial lights come first, as is the convention)
  128. currentIdx = int(texelFetch(gLinkedListHeads, cellIdx).x);
  129. uint lightIdx = 0;
  130. while(currentIdx != 0xFFFFFFFF)
  131. {
  132. uvec3 entry = texelFetch(gLinkedList, currentIdx).xyz;
  133. imageStore(gGridLightIndices, int(indicesStart + numLights - 1 - lightIdx), uvec4(entry.x, 0, 0, 0));
  134. currentIdx = int(entry.z);
  135. lightIdx++;
  136. }
  137. }
  138. };
  139. };
  140. };