BsLightGrid.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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 numGroupsX = (mGridSize[0] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  73. UINT32 numGroupsY = (mGridSize[1] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  74. UINT32 numGroupsZ = (mGridSize[2] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  75. gRendererUtility().setComputePass(mMaterial, 0);
  76. gRendererUtility().setPassParams(mParamsSet);
  77. RenderAPI::instance().dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
  78. }
  79. void LightGridLLCreationMat::getOutputs(SPtr<GpuBuffer>& linkedListHeads, SPtr<GpuBuffer>& linkedList) const
  80. {
  81. linkedListHeads = mLinkedListHeads;
  82. linkedList = mLinkedList;
  83. }
  84. LightGridLLReductionMat::LightGridLLReductionMat()
  85. :mBufferNumCells(0)
  86. {
  87. SPtr<GpuParams> params = mParamsSet->getGpuParams();
  88. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLinkedListHeads", mLinkedListHeadsParam);
  89. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gLinkedList", mLinkedListParam);
  90. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridDataCounter", mGridDataCounterParam);
  91. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridLightOffsetAndSize", mGridLightOffsetAndSizeParam);
  92. params->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridLightIndices", mGridLightIndicesParam);
  93. GPU_BUFFER_DESC desc;
  94. desc.elementCount = 1;
  95. desc.format = BF_32X1U;
  96. desc.randomGpuWrite = true;
  97. desc.type = GBT_STANDARD;
  98. desc.elementSize = 0;
  99. mGridDataCounter = GpuBuffer::create(desc);
  100. mGridDataCounterParam.set(mGridDataCounter);
  101. }
  102. void LightGridLLReductionMat::_initDefines(ShaderDefines& defines)
  103. {
  104. defines.set("THREADGROUP_SIZE", THREADGROUP_SIZE);
  105. }
  106. void LightGridLLReductionMat::setParams(const Vector3I& gridSize, const SPtr<GpuParamBlockBuffer>& gridParams,
  107. const SPtr<GpuBuffer>& linkedListHeads, const SPtr<GpuBuffer>& linkedList)
  108. {
  109. mGridSize = gridSize;
  110. UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
  111. if (numCells > mBufferNumCells || mBufferNumCells == 0)
  112. {
  113. GPU_BUFFER_DESC desc;
  114. desc.elementCount = numCells;
  115. desc.format = BF_32X4U;
  116. desc.randomGpuWrite = true;
  117. desc.type = GBT_STANDARD;
  118. desc.elementSize = 0;
  119. mGridLightOffsetAndSize = GpuBuffer::create(desc);
  120. mGridLightOffsetAndSizeParam.set(mGridLightOffsetAndSize);
  121. desc.format = BF_32X1U;
  122. desc.elementCount = numCells * MAX_LIGHTS_PER_CELL;
  123. mGridLightIndices = GpuBuffer::create(desc);
  124. mGridLightIndicesParam.set(mGridLightIndices);
  125. mBufferNumCells = numCells;
  126. }
  127. // Note: Add a method to clear buffer data directly? e.g. GpuBuffer->clear(value);
  128. UINT32 zero = 0;
  129. mGridDataCounter->writeData(0, sizeof(UINT32), &zero, BWT_DISCARD);
  130. mParamsSet->setParamBlockBuffer("GridParams", gridParams, true);
  131. mLinkedListHeadsParam.set(linkedListHeads);
  132. mLinkedListParam.set(linkedList);
  133. }
  134. void LightGridLLReductionMat::execute(const RendererCamera& view)
  135. {
  136. mParamsSet->setParamBlockBuffer("PerCamera", view.getPerViewBuffer(), true);
  137. UINT32 numGroupsX = (mGridSize[0] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  138. UINT32 numGroupsY = (mGridSize[1] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  139. UINT32 numGroupsZ = (mGridSize[2] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE;
  140. gRendererUtility().setComputePass(mMaterial, 0);
  141. gRendererUtility().setPassParams(mParamsSet);
  142. RenderAPI::instance().dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
  143. }
  144. void LightGridLLReductionMat::getOutputs(SPtr<GpuBuffer>& gridOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices) const
  145. {
  146. gridOffsetsAndSize = mGridLightOffsetAndSize;
  147. gridLightIndices = mGridLightIndices;
  148. }
  149. LightGrid::LightGrid()
  150. {
  151. mGridParamBuffer = gLightGridParamDefDef.createBuffer();
  152. }
  153. void LightGrid::updateGrid(const RendererCamera& view, const GPULightData& lightData, bool noLighting)
  154. {
  155. UINT32 width = view.getRenderTargets()->getWidth();
  156. UINT32 height = view.getRenderTargets()->getHeight();
  157. Vector3I gridSize;
  158. gridSize[0] = (width + CELL_XY_SIZE - 1) / CELL_XY_SIZE;
  159. gridSize[1] = (height + CELL_XY_SIZE - 1) / CELL_XY_SIZE;
  160. gridSize[2] = NUM_Z_SUBDIVIDES;
  161. Vector3I lightOffsets;
  162. if (!noLighting)
  163. {
  164. lightOffsets[0] = lightData.getNumDirLights();
  165. lightOffsets[1] = lightOffsets[0] + lightData.getNumRadialLights();
  166. lightOffsets[2] = lightOffsets[1] + lightData.getNumSpotLights();
  167. }
  168. else
  169. {
  170. lightOffsets[0] = 0;
  171. lightOffsets[1] = 1;
  172. lightOffsets[2] = 2;
  173. }
  174. UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2];
  175. gLightGridParamDefDef.gLightOffsets.set(mGridParamBuffer, lightOffsets);
  176. gLightGridParamDefDef.gNumCells.set(mGridParamBuffer, numCells);
  177. gLightGridParamDefDef.gGridSize.set(mGridParamBuffer, gridSize);
  178. gLightGridParamDefDef.gMaxNumLightsPerCell.set(mGridParamBuffer, MAX_LIGHTS_PER_CELL);
  179. gLightGridParamDefDef.gGridPixelSize.set(mGridParamBuffer, Vector2I(CELL_XY_SIZE, CELL_XY_SIZE));
  180. mLLCreationMat.setParams(gridSize, mGridParamBuffer, lightData.getLightBuffer());
  181. mLLCreationMat.execute(view);
  182. SPtr<GpuBuffer> linkedListHeads;
  183. SPtr<GpuBuffer> linkedList;
  184. mLLCreationMat.getOutputs(linkedListHeads, linkedList);
  185. mLLReductionMat.setParams(gridSize, mGridParamBuffer, linkedListHeads, linkedList);
  186. mLLReductionMat.execute(view);
  187. }
  188. void LightGrid::getOutputs(SPtr<GpuBuffer>& gridOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices,
  189. SPtr<GpuParamBlockBuffer>& gridParams) const
  190. {
  191. mLLReductionMat.getOutputs(gridOffsetsAndSize, gridLightIndices);
  192. gridParams = mGridParamBuffer;
  193. }
  194. }}