BsLightGrid.cpp 11 KB

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