BsLightGrid.cpp 11 KB

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