LightGridLLReduction.bsl 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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. uint2 viewportMax = gViewportRectangle.xy + gViewportRectangle.zw;
  24. // Ignore pixels out of valid range
  25. if (all(dispatchThreadId.xy >= viewportMax))
  26. return;
  27. uint maxNumLinks = gNumCells * gMaxNumLightsPerCell;
  28. uint cellIdx = (dispatchThreadId.z * gGridSize.y + dispatchThreadId.y) * gGridSize.x + dispatchThreadId.x;
  29. // First count total number of lights affecting the tile
  30. uint currentIdx = gLinkedListHeads[cellIdx];
  31. uint numRadialLights = 0;
  32. uint numSpotLights = 0;
  33. while(currentIdx != 0xFFFFFFFF)
  34. {
  35. uint4 entry = gLinkedList[currentIdx];
  36. if(entry.y == 1) // Radial
  37. numRadialLights++;
  38. else // Spot
  39. numSpotLights++;
  40. currentIdx = entry.z;
  41. }
  42. // Allocate enough room and remember the offset to indices
  43. uint numLights = numRadialLights + numSpotLights;
  44. uint indicesStart;
  45. InterlockedAdd(gGridDataCounter[0], numLights, indicesStart);
  46. gGridLightOffsetAndSize[cellIdx] = uint4(indicesStart, numRadialLights, numSpotLights, 0);
  47. // Actually write light indices (reverse order, so that radial lights come first, as is the convention)
  48. currentIdx = gLinkedListHeads[cellIdx];
  49. uint lightIdx = 0;
  50. while(currentIdx != 0xFFFFFFFF)
  51. {
  52. uint4 entry = gLinkedList[currentIdx];
  53. gGridLightIndices[indicesStart + numLights - 1 - lightIdx] = entry.x;
  54. currentIdx = entry.z;
  55. lightIdx++;
  56. }
  57. }
  58. };
  59. };
  60. };
  61. Technique
  62. : inherits("PerCameraData")
  63. : inherits("LightGridCommon") =
  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 = 1) uniform usamplerBuffer gLinkedListHeads;
  72. layout(binding = 2) uniform usamplerBuffer gLinkedList;
  73. layout(binding = 3, r32ui) uniform uimageBuffer gGridDataCounter;
  74. layout(binding = 5, rgba32ui) uniform uimageBuffer gGridLightOffsetAndSize;
  75. layout(binding = 6, r32ui) uniform uimageBuffer gGridLightIndices;
  76. void main()
  77. {
  78. uvec2 viewportMax = gViewportRectangle.xy + gViewportRectangle.zw;
  79. // Ignore pixels out of valid range
  80. if (all(greaterThanEqual(gl_GlobalInvocationID.xy, viewportMax)))
  81. return;
  82. uint maxNumLinks = gNumCells * gMaxNumLightsPerCell;
  83. int cellIdx = int((gl_GlobalInvocationID.z * gGridSize.y + gl_GlobalInvocationID.y) * gGridSize.x + gl_GlobalInvocationID.x);
  84. // First count total number of lights affecting the tile
  85. int currentIdx = int(texelFetch(gLinkedListHeads, cellIdx).x);
  86. uint numRadialLights = 0;
  87. uint numSpotLights = 0;
  88. while(currentIdx != 0xFFFFFFFF)
  89. {
  90. uvec3 entry = texelFetch(gLinkedList, currentIdx).xyz;
  91. if(entry.y == 1) // Radial
  92. numRadialLights++;
  93. else // Spot
  94. numSpotLights++;
  95. currentIdx = int(entry.z);
  96. }
  97. // Allocate enough room and remember the offset to indices
  98. uint numLights = numRadialLights + numSpotLights;
  99. uint indicesStart = imageAtomicAdd(gGridDataCounter, 0, numLights);
  100. imageStore(gGridLightOffsetAndSize, cellIdx, uvec4(indicesStart, numRadialLights, numSpotLights, 0));
  101. // Actually write light indices (reverse order, so that radial lights come first, as is the convention)
  102. currentIdx = int(texelFetch(gLinkedListHeads, cellIdx).x);
  103. uint lightIdx = 0;
  104. while(currentIdx != 0xFFFFFFFF)
  105. {
  106. uvec3 entry = texelFetch(gLinkedList, currentIdx).xyz;
  107. imageStore(gGridLightIndices, int(indicesStart + numLights - 1 - lightIdx), uvec4(entry.x, 0, 0, 0));
  108. currentIdx = int(entry.z);
  109. lightIdx++;
  110. }
  111. }
  112. };
  113. };
  114. };