BsLightGrid.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsLightGrid.h"
  4. #include "BsGpuBuffer.h"
  5. #include "BsGpuParamsSet.h"
  6. #include "BsRendererUtility.h"
  7. #include "BsRendererCamera.h"
  8. #include "BsRenderTargets.h"
  9. #include "BsLightRendering.h"
  10. namespace bs { namespace ct
  11. {
  12. static const UINT32 CELL_XY_SIZE = 64;
  13. static const UINT32 NUM_Z_SUBDIVIDES = 32;
  14. static const UINT32 MAX_LIGHTS_PER_CELL = 32;
  15. static const UINT32 THREADGROUP_SIZE = 4;
  16. LightGridParamDef gLightGridParamDefDef;
  17. LightGridLLCreationMat::LightGridLLCreationMat()
  18. :mBufferNumCells(0)
  19. {
  20. SPtr<GpuParams> params = mParamsSet->getGpuParams();
  21. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLights", mLightBufferParam);
  22. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLinkedListCounter", mLinkedListCounterParam);
  23. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLinkedListHeads", mLinkedListHeadsParam);
  24. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLinkedList", mLinkedListParam);
  25. GPU_BUFFER_DESC desc;
  26. desc.elementCount = 1;
  27. desc.format = BF_32X1U;
  28. desc.randomGpuWrite = true;
  29. desc.type = GBT_STANDARD;
  30. desc.elementSize = 0;
  31. mLinkedListCounter = GpuBuffer::create(desc);
  32. mLinkedListCounterParam.set(mLinkedListCounter);
  33. }
  34. void LightGridLLCreationMat::_initDefines(ShaderDefines& defines)
  35. {
  36. defines.set("THREADGROUP_SIZE", THREADGROUP_SIZE);
  37. }
  38. void LightGridLLCreationMat::setParams(const Vector3I& gridSize, const SPtr<GpuParamBlockBuffer>& gridParams,
  39. const SPtr<GpuBuffer>& lightsBuffer)
  40. {
  41. mGridSize = gridSize;
  42. UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
  43. if(numCells > mBufferNumCells || mBufferNumCells == 0)
  44. {
  45. GPU_BUFFER_DESC desc;
  46. desc.elementCount = numCells;
  47. desc.format = BF_32X1U;
  48. desc.randomGpuWrite = true;
  49. desc.type = GBT_STANDARD;
  50. desc.elementSize = 0;
  51. mLinkedListHeads = GpuBuffer::create(desc);
  52. mLinkedListHeadsParam.set(mLinkedListHeads);
  53. desc.format = BF_32X4U;
  54. desc.elementCount = numCells * MAX_LIGHTS_PER_CELL;
  55. mLinkedList = GpuBuffer::create(desc);
  56. mLinkedListParam.set(mLinkedList);
  57. mBufferNumCells = numCells;
  58. }
  59. UINT32 zero = 0;
  60. mLinkedListCounter->writeData(0, sizeof(UINT32), &zero, BWT_DISCARD);
  61. // Note: Add a method to clear buffer data directly? e.g. GpuBuffer->clear(value);
  62. UINT32* headsClearData = (UINT32*)bs_stack_alloc(mLinkedListHeads->getSize());
  63. memset(headsClearData, 0xFFFFFFFF, mLinkedListHeads->getSize());
  64. mLinkedListHeads->writeData(0, mLinkedListHeads->getSize(), headsClearData, BWT_DISCARD);
  65. bs_stack_free(headsClearData);
  66. mParamsSet->setParamBlockBuffer("GridParams", gridParams, true);
  67. mLightBufferParam.set(lightsBuffer);
  68. }
  69. void LightGridLLCreationMat::execute(const RendererCamera& view)
  70. {
  71. mParamsSet->setParamBlockBuffer("PerCamera", view.getPerViewBuffer(), true);
  72. UINT32 width = view.getRenderTargets()->getWidth();
  73. UINT32 height = view.getRenderTargets()->getHeight();
  74. UINT32 numGroupsX = (mGridSize[0] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  75. UINT32 numGroupsY = (mGridSize[1] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  76. UINT32 numGroupsZ = (mGridSize[2] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  77. gRendererUtility().setComputePass(mMaterial, 0);
  78. gRendererUtility().setPassParams(mParamsSet);
  79. RenderAPI::instance().dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
  80. }
  81. void LightGridLLCreationMat::getOutputs(SPtr<GpuBuffer>& linkedListHeads, SPtr<GpuBuffer>& linkedList) const
  82. {
  83. linkedListHeads = mLinkedListHeads;
  84. linkedList = mLinkedList;
  85. }
  86. LightGridLLReductionMat::LightGridLLReductionMat()
  87. :mBufferNumCells(0)
  88. {
  89. SPtr<GpuParams> params = mParamsSet->getGpuParams();
  90. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLinkedListHeads", mLinkedListHeadsParam);
  91. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLinkedList", mLinkedListParam);
  92. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridDataCounter", mGridDataCounterParam);
  93. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridLightOffsetAndSize", mGridLightOffsetAndSizeParam);
  94. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridLightIndices", mGridLightIndicesParam);
  95. GPU_BUFFER_DESC desc;
  96. desc.elementCount = 1;
  97. desc.format = BF_32X1U;
  98. desc.randomGpuWrite = true;
  99. desc.type = GBT_STANDARD;
  100. desc.elementSize = 0;
  101. mGridDataCounter = GpuBuffer::create(desc);
  102. mGridDataCounterParam.set(mGridDataCounter);
  103. }
  104. void LightGridLLReductionMat::_initDefines(ShaderDefines& defines)
  105. {
  106. defines.set("THREADGROUP_SIZE", THREADGROUP_SIZE);
  107. }
  108. void LightGridLLReductionMat::setParams(const Vector3I& gridSize, const SPtr<GpuParamBlockBuffer>& gridParams,
  109. SPtr<GpuBuffer>& linkedListHeads, SPtr<GpuBuffer>& linkedList)
  110. {
  111. mGridSize = gridSize;
  112. UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
  113. if (numCells > mBufferNumCells || mBufferNumCells == 0)
  114. {
  115. GPU_BUFFER_DESC desc;
  116. desc.elementCount = numCells;
  117. desc.format = BF_32X4U;
  118. desc.randomGpuWrite = true;
  119. desc.type = GBT_STANDARD;
  120. desc.elementSize = 0;
  121. mGridLightOffsetAndSize = GpuBuffer::create(desc);
  122. mGridLightOffsetAndSizeParam.set(mGridLightOffsetAndSize);
  123. desc.format = BF_32X1U;
  124. desc.elementCount = numCells * MAX_LIGHTS_PER_CELL;
  125. mGridLightIndices = GpuBuffer::create(desc);
  126. mGridLightIndicesParam.set(mGridLightIndices);
  127. mBufferNumCells = numCells;
  128. }
  129. // Note: Add a method to clear buffer data directly? e.g. GpuBuffer->clear(value);
  130. UINT32 zero = 0;
  131. mGridDataCounter->writeData(0, sizeof(UINT32), &zero, BWT_DISCARD);
  132. mParamsSet->setParamBlockBuffer("GridParams", gridParams, true);
  133. mLinkedListHeadsParam.set(linkedListHeads);
  134. mLinkedListParam.set(linkedList);
  135. }
  136. void LightGridLLReductionMat::execute(const RendererCamera& view)
  137. {
  138. mParamsSet->setParamBlockBuffer("PerCamera", view.getPerViewBuffer(), true);
  139. UINT32 numGroupsX = (mGridSize[0] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  140. UINT32 numGroupsY = (mGridSize[1] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  141. UINT32 numGroupsZ = (mGridSize[2] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  142. gRendererUtility().setComputePass(mMaterial, 0);
  143. gRendererUtility().setPassParams(mParamsSet);
  144. RenderAPI::instance().dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
  145. }
  146. void LightGridLLReductionMat::getOutputs(SPtr<GpuBuffer>& gridOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices) const
  147. {
  148. gridOffsetsAndSize = mGridLightOffsetAndSize;
  149. gridLightIndices = mGridLightIndices;
  150. }
  151. LightGrid::LightGrid()
  152. {
  153. mGridParamBuffer = gLightGridParamDefDef.createBuffer();
  154. }
  155. void LightGrid::updateGrid(const RendererCamera& view, const GPULightData& lightData)
  156. {
  157. UINT32 width = view.getRenderTargets()->getWidth();
  158. UINT32 height = view.getRenderTargets()->getHeight();
  159. Vector3I gridSize;
  160. gridSize[0] = (width + CELL_XY_SIZE - 1) / CELL_XY_SIZE;
  161. gridSize[1] = (height + CELL_XY_SIZE - 1) / CELL_XY_SIZE;
  162. gridSize[2] = NUM_Z_SUBDIVIDES;
  163. Vector3I lightOffsets;
  164. lightOffsets[0] = lightData.getNumDirLights();
  165. lightOffsets[1] = lightOffsets[0] + lightData.getNumRadialLights();
  166. lightOffsets[2] = lightOffsets[1] + lightData.getNumSpotLights();
  167. UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
  168. gLightGridParamDefDef.gLightOffsets.set(mGridParamBuffer, lightOffsets);
  169. gLightGridParamDefDef.gNumCells.set(mGridParamBuffer, numCells);
  170. gLightGridParamDefDef.gGridSize.set(mGridParamBuffer, gridSize);
  171. gLightGridParamDefDef.gMaxNumLightsPerCell.set(mGridParamBuffer, MAX_LIGHTS_PER_CELL);
  172. gLightGridParamDefDef.gGridPixelSize.set(mGridParamBuffer, Vector2I(CELL_XY_SIZE, CELL_XY_SIZE));
  173. mLLCreationMat.setParams(gridSize, mGridParamBuffer, lightData.getLightBuffer());
  174. mLLCreationMat.execute(view);
  175. SPtr<GpuBuffer> linkedListHeads;
  176. SPtr<GpuBuffer> linkedList;
  177. mLLCreationMat.getOutputs(linkedListHeads, linkedList);
  178. mLLReductionMat.setParams(gridSize, mGridParamBuffer, linkedListHeads, linkedList);
  179. mLLReductionMat.execute(view);
  180. }
  181. void LightGrid::getOutputs(SPtr<GpuBuffer>& gridOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices,
  182. SPtr<GpuParamBlockBuffer>& gridParams) const
  183. {
  184. mLLReductionMat.getOutputs(gridOffsetsAndSize, gridLightIndices);
  185. gridParams = mGridParamBuffer;
  186. }
  187. }}