BsLightGrid.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsLightGrid.h"
  4. #include "RenderAPI/BsGpuBuffer.h"
  5. #include "Material/BsGpuParamsSet.h"
  6. #include "Renderer/BsRendererUtility.h"
  7. #include "BsRendererView.h"
  8. #include "BsLightRendering.h"
  9. #include "BsImageBasedLighting.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. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gLights", mLightBufferParam);
  21. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gLightsCounter", mLightsCounterParam);
  22. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gLightsLLHeads", mLightsLLHeadsParam);
  23. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gLightsLL", mLightsLLParam);
  24. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gReflectionProbes", mProbesBufferParam);
  25. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gProbesCounter", mProbesCounterParam);
  26. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gProbesLLHeads", mProbesLLHeadsParam);
  27. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gProbesLL", mProbesLLParam);
  28. GPU_BUFFER_DESC desc;
  29. desc.elementCount = 1;
  30. desc.format = BF_32X1U;
  31. desc.randomGpuWrite = true;
  32. desc.type = GBT_STANDARD;
  33. desc.elementSize = 0;
  34. mLightsCounter = GpuBuffer::create(desc);
  35. mLightsCounterParam.set(mLightsCounter);
  36. mProbesCounter = GpuBuffer::create(desc);
  37. mProbesCounterParam.set(mProbesCounter);
  38. }
  39. void LightGridLLCreationMat::_initDefines(ShaderDefines& defines)
  40. {
  41. defines.set("THREADGROUP_SIZE", THREADGROUP_SIZE);
  42. }
  43. void LightGridLLCreationMat::setParams(const Vector3I& gridSize, const SPtr<GpuParamBlockBuffer>& gridParams,
  44. const SPtr<GpuBuffer>& lightsBuffer, const SPtr<GpuBuffer>& probesBuffer)
  45. {
  46. mGridSize = gridSize;
  47. UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
  48. if(numCells > mBufferNumCells || mBufferNumCells == 0)
  49. {
  50. GPU_BUFFER_DESC desc;
  51. desc.elementCount = numCells;
  52. desc.format = BF_32X1U;
  53. desc.randomGpuWrite = true;
  54. desc.type = GBT_STANDARD;
  55. desc.elementSize = 0;
  56. mLightsLLHeads = GpuBuffer::create(desc);
  57. mLightsLLHeadsParam.set(mLightsLLHeads);
  58. mProbesLLHeads = GpuBuffer::create(desc);
  59. mProbesLLHeadsParam.set(mProbesLLHeads);
  60. desc.format = BF_32X4U;
  61. desc.elementCount = numCells * MAX_LIGHTS_PER_CELL;
  62. mLightsLL = GpuBuffer::create(desc);
  63. mLightsLLParam.set(mLightsLL);
  64. desc.format = BF_32X2U;
  65. mProbesLL = GpuBuffer::create(desc);
  66. mProbesLLParam.set(mProbesLL);
  67. mBufferNumCells = numCells;
  68. }
  69. UINT32 zero = 0;
  70. mLightsCounter->writeData(0, sizeof(UINT32), &zero, BWT_DISCARD);
  71. mProbesCounter->writeData(0, sizeof(UINT32), &zero, BWT_DISCARD);
  72. // Note: Add a method to clear buffer data directly? e.g. GpuBuffer->clear(value);
  73. UINT32* headsClearData = (UINT32*)bs_stack_alloc(mLightsLLHeads->getSize());
  74. memset(headsClearData, 0xFFFFFFFF, mLightsLLHeads->getSize());
  75. mLightsLLHeads->writeData(0, mLightsLLHeads->getSize(), headsClearData, BWT_DISCARD);
  76. bs_stack_free(headsClearData);
  77. headsClearData = (UINT32*)bs_stack_alloc(mProbesLLHeads->getSize());
  78. memset(headsClearData, 0xFFFFFFFF, mProbesLLHeads->getSize());
  79. mProbesLLHeads->writeData(0, mProbesLLHeads->getSize(), headsClearData, BWT_DISCARD);
  80. bs_stack_free(headsClearData);
  81. mParams->setParamBlockBuffer("GridParams", gridParams);
  82. mLightBufferParam.set(lightsBuffer);
  83. mProbesBufferParam.set(probesBuffer);
  84. }
  85. void LightGridLLCreationMat::execute(const RendererView& view)
  86. {
  87. mParams->setParamBlockBuffer("PerCamera", view.getPerViewBuffer());
  88. UINT32 numGroupsX = (mGridSize[0] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  89. UINT32 numGroupsY = (mGridSize[1] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  90. UINT32 numGroupsZ = (mGridSize[2] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  91. bind();
  92. RenderAPI::instance().dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
  93. }
  94. void LightGridLLCreationMat::getOutputs(SPtr<GpuBuffer>& lightsLLHeads, SPtr<GpuBuffer>& lightsLL,
  95. SPtr<GpuBuffer>& probesLLHeads, SPtr<GpuBuffer>& probesLL) const
  96. {
  97. lightsLLHeads = mLightsLLHeads;
  98. lightsLL = mLightsLL;
  99. probesLLHeads = mProbesLLHeads;
  100. probesLL = mProbesLL;
  101. }
  102. LightGridLLReductionMat::LightGridLLReductionMat()
  103. :mBufferNumCells(0)
  104. {
  105. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gLightsLLHeads", mLightsLLHeadsParam);
  106. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gLightsLL", mLightsLLParam);
  107. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gProbesLLHeads", mProbesLLHeadsParam);
  108. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gProbesLL", mProbesLLParam);
  109. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridDataCounter", mGridDataCounterParam);
  110. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridLightOffsetAndSize", mGridLightOffsetAndSizeParam);
  111. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridLightIndices", mGridLightIndicesParam);
  112. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridProbeOffsetAndSize", mGridProbeOffsetAndSizeParam);
  113. mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridProbeIndices", mGridProbeIndicesParam);
  114. GPU_BUFFER_DESC desc;
  115. desc.elementCount = 2;
  116. desc.format = BF_32X1U;
  117. desc.randomGpuWrite = true;
  118. desc.type = GBT_STANDARD;
  119. desc.elementSize = 0;
  120. mGridDataCounter = GpuBuffer::create(desc);
  121. mGridDataCounterParam.set(mGridDataCounter);
  122. }
  123. void LightGridLLReductionMat::_initDefines(ShaderDefines& defines)
  124. {
  125. defines.set("THREADGROUP_SIZE", THREADGROUP_SIZE);
  126. }
  127. void LightGridLLReductionMat::setParams(const Vector3I& gridSize, const SPtr<GpuParamBlockBuffer>& gridParams,
  128. const SPtr<GpuBuffer>& lightsLLHeads, const SPtr<GpuBuffer>& lightsLL,
  129. const SPtr<GpuBuffer>& probeLLHeads, const SPtr<GpuBuffer>& probeLL)
  130. {
  131. mGridSize = gridSize;
  132. UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
  133. if (numCells > mBufferNumCells || mBufferNumCells == 0)
  134. {
  135. GPU_BUFFER_DESC desc;
  136. desc.elementCount = numCells;
  137. desc.format = BF_32X4U;
  138. desc.randomGpuWrite = true;
  139. desc.type = GBT_STANDARD;
  140. desc.elementSize = 0;
  141. mGridLightOffsetAndSize = GpuBuffer::create(desc);
  142. mGridLightOffsetAndSizeParam.set(mGridLightOffsetAndSize);
  143. desc.format = BF_32X2U;
  144. mGridProbeOffsetAndSize = GpuBuffer::create(desc);
  145. mGridProbeOffsetAndSizeParam.set(mGridProbeOffsetAndSize);
  146. desc.format = BF_32X1U;
  147. desc.elementCount = numCells * MAX_LIGHTS_PER_CELL;
  148. mGridLightIndices = GpuBuffer::create(desc);
  149. mGridLightIndicesParam.set(mGridLightIndices);
  150. mGridProbeIndices = GpuBuffer::create(desc);
  151. mGridProbeIndicesParam.set(mGridProbeIndices);
  152. mBufferNumCells = numCells;
  153. }
  154. // Note: Add a method to clear buffer data directly? e.g. GpuBuffer->clear(value);
  155. UINT32 zeros[] = { 0, 0 };
  156. mGridDataCounter->writeData(0, sizeof(UINT32) * 2, zeros, BWT_DISCARD);
  157. mParams->setParamBlockBuffer("GridParams", gridParams);
  158. mLightsLLHeadsParam.set(lightsLLHeads);
  159. mLightsLLParam.set(lightsLL);
  160. mProbesLLHeadsParam.set(probeLLHeads);
  161. mProbesLLParam.set(probeLL);
  162. }
  163. void LightGridLLReductionMat::execute(const RendererView& view)
  164. {
  165. mParams->setParamBlockBuffer("PerCamera", view.getPerViewBuffer());
  166. UINT32 numGroupsX = (mGridSize[0] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  167. UINT32 numGroupsY = (mGridSize[1] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  168. UINT32 numGroupsZ = (mGridSize[2] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  169. bind();
  170. RenderAPI::instance().dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
  171. }
  172. void LightGridLLReductionMat::getOutputs(SPtr<GpuBuffer>& gridLightOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices,
  173. SPtr<GpuBuffer>& gridProbeOffsetsAndSize, SPtr<GpuBuffer>& gridProbeIndices) const
  174. {
  175. gridLightOffsetsAndSize = mGridLightOffsetAndSize;
  176. gridLightIndices = mGridLightIndices;
  177. gridProbeOffsetsAndSize = mGridProbeOffsetAndSize;
  178. gridProbeIndices = mGridProbeIndices;
  179. }
  180. LightGrid::LightGrid()
  181. {
  182. mGridParamBuffer = gLightGridParamDefDef.createBuffer();
  183. }
  184. void LightGrid::updateGrid(const RendererView& view, const VisibleLightData& lightData, const VisibleReflProbeData& probeData,
  185. bool noLighting)
  186. {
  187. const RendererViewProperties& viewProps = view.getProperties();
  188. UINT32 width = viewProps.viewRect.width;
  189. UINT32 height = viewProps.viewRect.height;
  190. Vector3I gridSize;
  191. gridSize[0] = (width + CELL_XY_SIZE - 1) / CELL_XY_SIZE;
  192. gridSize[1] = (height + CELL_XY_SIZE - 1) / CELL_XY_SIZE;
  193. gridSize[2] = NUM_Z_SUBDIVIDES;
  194. Vector4I lightCount;
  195. Vector2I lightStrides;
  196. if (!noLighting)
  197. {
  198. lightCount[0] = lightData.getNumLights(LightType::Directional);
  199. lightCount[1] = lightData.getNumLights(LightType::Radial);
  200. lightCount[2] = lightData.getNumLights(LightType::Spot);
  201. lightCount[3] = lightCount[0] + lightCount[1] + lightCount[2];
  202. lightStrides[0] = lightCount[0];
  203. lightStrides[1] = lightStrides[0] + lightCount[1];
  204. }
  205. else
  206. {
  207. lightCount[0] = 0;
  208. lightCount[1] = 0;
  209. lightCount[2] = 0;
  210. lightCount[3] = 0;
  211. lightStrides[0] = 0;
  212. lightStrides[1] = 0;
  213. }
  214. UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
  215. gLightGridParamDefDef.gLightCounts.set(mGridParamBuffer, lightCount);
  216. gLightGridParamDefDef.gLightStrides.set(mGridParamBuffer, lightStrides);
  217. gLightGridParamDefDef.gNumReflProbes.set(mGridParamBuffer, probeData.getNumProbes());
  218. gLightGridParamDefDef.gNumCells.set(mGridParamBuffer, numCells);
  219. gLightGridParamDefDef.gGridSize.set(mGridParamBuffer, gridSize);
  220. gLightGridParamDefDef.gMaxNumLightsPerCell.set(mGridParamBuffer, MAX_LIGHTS_PER_CELL);
  221. gLightGridParamDefDef.gGridPixelSize.set(mGridParamBuffer, Vector2I(CELL_XY_SIZE, CELL_XY_SIZE));
  222. LightGridLLCreationMat* creationMat = LightGridLLCreationMat::get();
  223. creationMat->setParams(gridSize, mGridParamBuffer, lightData.getLightBuffer(), probeData.getProbeBuffer());
  224. creationMat->execute(view);
  225. SPtr<GpuBuffer> lightLLHeads;
  226. SPtr<GpuBuffer> lightLL;
  227. SPtr<GpuBuffer> probeLLHeads;
  228. SPtr<GpuBuffer> probeLL;
  229. creationMat->getOutputs(lightLLHeads, lightLL, probeLLHeads, probeLL);
  230. LightGridLLReductionMat* reductionMat = LightGridLLReductionMat::get();
  231. reductionMat->setParams(gridSize, mGridParamBuffer, lightLLHeads, lightLL, probeLLHeads, probeLL);
  232. reductionMat->execute(view);
  233. }
  234. void LightGrid::getOutputs(SPtr<GpuBuffer>& gridLightOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices,
  235. SPtr<GpuBuffer>& gridProbeOffsetsAndSize, SPtr<GpuBuffer>& gridProbeIndices,
  236. SPtr<GpuParamBlockBuffer>& gridParams) const
  237. {
  238. LightGridLLReductionMat* reductionMat = LightGridLLReductionMat::get();
  239. reductionMat->getOutputs(gridLightOffsetsAndSize, gridLightIndices, gridProbeOffsetsAndSize, gridProbeIndices);
  240. gridParams = mGridParamBuffer;
  241. }
  242. }}