1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
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 "BsRendererLight.h" |
9 | #include "BsRendererReflectionProbe.h" |
10 | #include "BsTiledDeferred.h" |
11 | |
12 | namespace bs { namespace ct |
13 | { |
14 | static const UINT32 CELL_XY_SIZE = 64; |
15 | static const UINT32 NUM_Z_SUBDIVIDES = 32; |
16 | static const UINT32 MAX_LIGHTS_PER_CELL = 32; |
17 | static const UINT32 THREADGROUP_SIZE = 4; |
18 | |
19 | LightGridParamDef gLightGridParamDefDef; |
20 | |
21 | LightGridLLCreationMat::LightGridLLCreationMat() |
22 | { |
23 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gLights" , mLightBufferParam); |
24 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gLightsCounter" , mLightsCounterParam); |
25 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gLightsLLHeads" , mLightsLLHeadsParam); |
26 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gLightsLL" , mLightsLLParam); |
27 | |
28 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gReflectionProbes" , mProbesBufferParam); |
29 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gProbesCounter" , mProbesCounterParam); |
30 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gProbesLLHeads" , mProbesLLHeadsParam); |
31 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gProbesLL" , mProbesLLParam); |
32 | |
33 | GPU_BUFFER_DESC desc; |
34 | desc.elementCount = 1; |
35 | desc.format = BF_UNKNOWN; |
36 | desc.usage = GBU_LOADSTORE; |
37 | desc.type = GBT_STRUCTURED; |
38 | desc.elementSize = 4; |
39 | |
40 | mLightsCounter = GpuBuffer::create(desc); |
41 | mLightsCounterParam.set(mLightsCounter); |
42 | |
43 | mProbesCounter = GpuBuffer::create(desc); |
44 | mProbesCounterParam.set(mProbesCounter); |
45 | } |
46 | |
47 | void LightGridLLCreationMat::_initDefines(ShaderDefines& defines) |
48 | { |
49 | defines.set("THREADGROUP_SIZE" , THREADGROUP_SIZE); |
50 | } |
51 | |
52 | void LightGridLLCreationMat::setParams(const Vector3I& gridSize, const SPtr<GpuParamBlockBuffer>& gridParams, |
53 | const SPtr<GpuBuffer>& lightsBuffer, const SPtr<GpuBuffer>& probesBuffer) |
54 | { |
55 | mGridSize = gridSize; |
56 | UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2]; |
57 | |
58 | if(numCells > mBufferNumCells || mBufferNumCells == 0) |
59 | { |
60 | GPU_BUFFER_DESC desc; |
61 | desc.elementCount = numCells; |
62 | desc.format = BF_UNKNOWN; |
63 | desc.usage = GBU_LOADSTORE; |
64 | desc.type = GBT_STRUCTURED; |
65 | desc.elementSize = 4; |
66 | |
67 | mLightsLLHeads = GpuBuffer::create(desc); |
68 | mLightsLLHeadsParam.set(mLightsLLHeads); |
69 | |
70 | mProbesLLHeads = GpuBuffer::create(desc); |
71 | mProbesLLHeadsParam.set(mProbesLLHeads); |
72 | |
73 | desc.type = GBT_STANDARD; |
74 | desc.format = BF_32X4U; |
75 | desc.elementCount = numCells * MAX_LIGHTS_PER_CELL; |
76 | desc.elementSize = 0; |
77 | |
78 | mLightsLL = GpuBuffer::create(desc); |
79 | mLightsLLParam.set(mLightsLL); |
80 | |
81 | desc.format = BF_32X2U; |
82 | mProbesLL = GpuBuffer::create(desc); |
83 | mProbesLLParam.set(mProbesLL); |
84 | |
85 | mBufferNumCells = numCells; |
86 | } |
87 | |
88 | ClearLoadStoreMat* clearMat = ClearLoadStoreMat::getVariation( |
89 | ClearLoadStoreType::StructuredBuffer, ClearLoadStoreDataType::Int, 1 |
90 | ); |
91 | |
92 | clearMat->execute(mLightsCounter); |
93 | clearMat->execute(mProbesCounter); |
94 | |
95 | UINT32 clearValue = 0xFFFFFFFF; |
96 | Color clearColor; |
97 | clearColor.r = *(float*) &clearValue; |
98 | clearColor.g = *(float*) &clearValue; |
99 | clearColor.b = *(float*) &clearValue; |
100 | clearColor.a = *(float*) &clearValue; |
101 | |
102 | clearMat->execute(mLightsLLHeads, clearColor); |
103 | clearMat->execute(mProbesLLHeads, clearColor); |
104 | |
105 | mParams->setParamBlockBuffer("GridParams" , gridParams); |
106 | mLightBufferParam.set(lightsBuffer); |
107 | mProbesBufferParam.set(probesBuffer); |
108 | } |
109 | |
110 | void LightGridLLCreationMat::execute(const RendererView& view) |
111 | { |
112 | BS_RENMAT_PROFILE_BLOCK |
113 | |
114 | mParams->setParamBlockBuffer("PerCamera" , view.getPerViewBuffer()); |
115 | |
116 | UINT32 numGroupsX = (mGridSize[0] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE; |
117 | UINT32 numGroupsY = (mGridSize[1] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE; |
118 | UINT32 numGroupsZ = (mGridSize[2] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE; |
119 | |
120 | bind(); |
121 | RenderAPI::instance().dispatchCompute(numGroupsX, numGroupsY, numGroupsZ); |
122 | } |
123 | |
124 | void LightGridLLCreationMat::getOutputs(SPtr<GpuBuffer>& lightsLLHeads, SPtr<GpuBuffer>& lightsLL, |
125 | SPtr<GpuBuffer>& probesLLHeads, SPtr<GpuBuffer>& probesLL) const |
126 | { |
127 | lightsLLHeads = mLightsLLHeads; |
128 | lightsLL = mLightsLL; |
129 | probesLLHeads = mProbesLLHeads; |
130 | probesLL = mProbesLL; |
131 | } |
132 | |
133 | LightGridLLReductionMat::LightGridLLReductionMat() |
134 | :mBufferNumCells(0) |
135 | { |
136 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gLightsLLHeads" , mLightsLLHeadsParam); |
137 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gLightsLL" , mLightsLLParam); |
138 | |
139 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gProbesLLHeads" , mProbesLLHeadsParam); |
140 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gProbesLL" , mProbesLLParam); |
141 | |
142 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridDataCounter" , mGridDataCounterParam); |
143 | |
144 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridLightOffsetAndSize" , mGridLightOffsetAndSizeParam); |
145 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridLightIndices" , mGridLightIndicesParam); |
146 | |
147 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridProbeOffsetAndSize" , mGridProbeOffsetAndSizeParam); |
148 | mParams->getBufferParam(GPT_COMPUTE_PROGRAM, "gGridProbeIndices" , mGridProbeIndicesParam); |
149 | |
150 | GPU_BUFFER_DESC desc; |
151 | desc.elementCount = 2; |
152 | desc.format = BF_UNKNOWN; |
153 | desc.usage = GBU_LOADSTORE; |
154 | desc.type = GBT_STRUCTURED; |
155 | desc.elementSize = 4; |
156 | |
157 | mGridDataCounter = GpuBuffer::create(desc); |
158 | mGridDataCounterParam.set(mGridDataCounter); |
159 | } |
160 | |
161 | void LightGridLLReductionMat::_initDefines(ShaderDefines& defines) |
162 | { |
163 | defines.set("THREADGROUP_SIZE" , THREADGROUP_SIZE); |
164 | } |
165 | |
166 | void LightGridLLReductionMat::setParams(const Vector3I& gridSize, const SPtr<GpuParamBlockBuffer>& gridParams, |
167 | const SPtr<GpuBuffer>& lightsLLHeads, const SPtr<GpuBuffer>& lightsLL, |
168 | const SPtr<GpuBuffer>& probeLLHeads, const SPtr<GpuBuffer>& probeLL) |
169 | { |
170 | mGridSize = gridSize; |
171 | UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2]; |
172 | |
173 | if (numCells > mBufferNumCells || mBufferNumCells == 0) |
174 | { |
175 | GPU_BUFFER_DESC desc; |
176 | desc.elementCount = numCells; |
177 | desc.format = BF_32X4U; |
178 | desc.usage = GBU_LOADSTORE; |
179 | desc.type = GBT_STANDARD; |
180 | desc.elementSize = 0; |
181 | |
182 | mGridLightOffsetAndSize = GpuBuffer::create(desc); |
183 | mGridLightOffsetAndSizeParam.set(mGridLightOffsetAndSize); |
184 | |
185 | desc.format = BF_32X2U; |
186 | |
187 | mGridProbeOffsetAndSize = GpuBuffer::create(desc); |
188 | mGridProbeOffsetAndSizeParam.set(mGridProbeOffsetAndSize); |
189 | |
190 | desc.format = BF_32X1U; |
191 | desc.elementCount = numCells * MAX_LIGHTS_PER_CELL; |
192 | mGridLightIndices = GpuBuffer::create(desc); |
193 | mGridLightIndicesParam.set(mGridLightIndices); |
194 | |
195 | mGridProbeIndices = GpuBuffer::create(desc); |
196 | mGridProbeIndicesParam.set(mGridProbeIndices); |
197 | |
198 | mBufferNumCells = numCells; |
199 | } |
200 | |
201 | ClearLoadStoreMat* clearMat = ClearLoadStoreMat::getVariation( |
202 | ClearLoadStoreType::StructuredBuffer, ClearLoadStoreDataType::Int, 1 |
203 | ); |
204 | clearMat->execute(mGridDataCounter); |
205 | |
206 | mParams->setParamBlockBuffer("GridParams" , gridParams); |
207 | |
208 | mLightsLLHeadsParam.set(lightsLLHeads); |
209 | mLightsLLParam.set(lightsLL); |
210 | |
211 | mProbesLLHeadsParam.set(probeLLHeads); |
212 | mProbesLLParam.set(probeLL); |
213 | } |
214 | |
215 | void LightGridLLReductionMat::execute(const RendererView& view) |
216 | { |
217 | BS_RENMAT_PROFILE_BLOCK |
218 | |
219 | mParams->setParamBlockBuffer("PerCamera" , view.getPerViewBuffer()); |
220 | |
221 | UINT32 numGroupsX = (mGridSize[0] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE; |
222 | UINT32 numGroupsY = (mGridSize[1] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE; |
223 | UINT32 numGroupsZ = (mGridSize[2] + THREADGROUP_SIZE - 1) / THREADGROUP_SIZE; |
224 | |
225 | bind(); |
226 | RenderAPI::instance().dispatchCompute(numGroupsX, numGroupsY, numGroupsZ); |
227 | } |
228 | |
229 | void LightGridLLReductionMat::getOutputs(SPtr<GpuBuffer>& gridLightOffsetsAndSize, SPtr<GpuBuffer>& gridLightIndices, |
230 | SPtr<GpuBuffer>& gridProbeOffsetsAndSize, SPtr<GpuBuffer>& gridProbeIndices) const |
231 | { |
232 | gridLightOffsetsAndSize = mGridLightOffsetAndSize; |
233 | gridLightIndices = mGridLightIndices; |
234 | gridProbeOffsetsAndSize = mGridProbeOffsetAndSize; |
235 | gridProbeIndices = mGridProbeIndices; |
236 | } |
237 | |
238 | LightGrid::LightGrid() |
239 | { |
240 | mGridParamBuffer = gLightGridParamDefDef.createBuffer(); |
241 | } |
242 | |
243 | void LightGrid::updateGrid(const RendererView& view, const VisibleLightData& lightData, const VisibleReflProbeData& probeData, |
244 | bool noLighting) |
245 | { |
246 | const RendererViewProperties& viewProps = view.getProperties(); |
247 | |
248 | UINT32 width = viewProps.target.viewRect.width; |
249 | UINT32 height = viewProps.target.viewRect.height; |
250 | |
251 | Vector3I gridSize; |
252 | gridSize[0] = (width + CELL_XY_SIZE - 1) / CELL_XY_SIZE; |
253 | gridSize[1] = (height + CELL_XY_SIZE - 1) / CELL_XY_SIZE; |
254 | gridSize[2] = NUM_Z_SUBDIVIDES; |
255 | |
256 | Vector4I lightCount; |
257 | Vector2I lightStrides; |
258 | if (!noLighting) |
259 | { |
260 | lightCount[0] = lightData.getNumLights(LightType::Directional); |
261 | lightCount[1] = lightData.getNumLights(LightType::Radial); |
262 | lightCount[2] = lightData.getNumLights(LightType::Spot); |
263 | lightCount[3] = lightCount[0] + lightCount[1] + lightCount[2]; |
264 | |
265 | lightStrides[0] = lightCount[0]; |
266 | lightStrides[1] = lightStrides[0] + lightCount[1]; |
267 | } |
268 | else |
269 | { |
270 | lightCount[0] = 0; |
271 | lightCount[1] = 0; |
272 | lightCount[2] = 0; |
273 | lightCount[3] = 0; |
274 | |
275 | lightStrides[0] = 0; |
276 | lightStrides[1] = 0; |
277 | } |
278 | |
279 | UINT32 numCells = gridSize[0] * gridSize[1] * gridSize[2]; |
280 | |
281 | gLightGridParamDefDef.gLightCounts.set(mGridParamBuffer, lightCount); |
282 | gLightGridParamDefDef.gLightStrides.set(mGridParamBuffer, lightStrides); |
283 | gLightGridParamDefDef.gNumReflProbes.set(mGridParamBuffer, probeData.getNumProbes()); |
284 | gLightGridParamDefDef.gNumCells.set(mGridParamBuffer, numCells); |
285 | gLightGridParamDefDef.gGridSize.set(mGridParamBuffer, gridSize); |
286 | gLightGridParamDefDef.gMaxNumLightsPerCell.set(mGridParamBuffer, MAX_LIGHTS_PER_CELL); |
287 | gLightGridParamDefDef.gGridPixelSize.set(mGridParamBuffer, Vector2I(CELL_XY_SIZE, CELL_XY_SIZE)); |
288 | |
289 | LightGridLLCreationMat* creationMat = LightGridLLCreationMat::get(); |
290 | creationMat->setParams(gridSize, mGridParamBuffer, lightData.getLightBuffer(), probeData.getProbeBuffer()); |
291 | creationMat->execute(view); |
292 | |
293 | SPtr<GpuBuffer> lightLLHeads; |
294 | SPtr<GpuBuffer> lightLL; |
295 | SPtr<GpuBuffer> probeLLHeads; |
296 | SPtr<GpuBuffer> probeLL; |
297 | creationMat->getOutputs(lightLLHeads, lightLL, probeLLHeads, probeLL); |
298 | |
299 | LightGridLLReductionMat* reductionMat = LightGridLLReductionMat::get(); |
300 | reductionMat->setParams(gridSize, mGridParamBuffer, lightLLHeads, lightLL, probeLLHeads, probeLL); |
301 | reductionMat->execute(view); |
302 | } |
303 | |
304 | LightGridOutputs LightGrid::getOutputs() const |
305 | { |
306 | LightGridOutputs outputs; |
307 | |
308 | LightGridLLReductionMat* reductionMat = LightGridLLReductionMat::get(); |
309 | reductionMat->getOutputs( |
310 | outputs.gridLightOffsetsAndSize, |
311 | outputs.gridLightIndices, |
312 | outputs.gridProbeOffsetsAndSize, |
313 | outputs.gridProbeIndices |
314 | ); |
315 | |
316 | outputs.gridParams = mGridParamBuffer; |
317 | |
318 | return outputs; |
319 | } |
320 | }} |
321 | |