ClusterBinning.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Renderer/ClusterBinning.h>
  6. #include <AnKi/Renderer/Renderer.h>
  7. #include <AnKi/Renderer/RenderQueue.h>
  8. #include <AnKi/Renderer/VolumetricLightingAccumulation.h>
  9. #include <AnKi/Core/ConfigSet.h>
  10. #include <AnKi/Util/Tracer.h>
  11. #include <AnKi/Util/ThreadHive.h>
  12. #include <AnKi/Util/HighRezTimer.h>
  13. #include <AnKi/Collision/Plane.h>
  14. #include <AnKi/Collision/Functions.h>
  15. namespace anki {
  16. ClusterBinning::ClusterBinning(Renderer* r)
  17. : RendererObject(r)
  18. {
  19. }
  20. ClusterBinning::~ClusterBinning()
  21. {
  22. }
  23. Error ClusterBinning::init(const ConfigSet& config)
  24. {
  25. ANKI_R_LOGI("Initializing clusterer binning");
  26. ANKI_CHECK(getResourceManager().loadResource("Shaders/ClusterBinning.ankiprog", m_prog));
  27. ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
  28. variantInitInfo.addConstant("TILE_SIZE", m_r->getTileSize());
  29. variantInitInfo.addConstant("TILE_COUNT_X", m_r->getTileCounts().x());
  30. variantInitInfo.addConstant("TILE_COUNT_Y", m_r->getTileCounts().y());
  31. variantInitInfo.addConstant("Z_SPLIT_COUNT", m_r->getZSplitCount());
  32. variantInitInfo.addConstant("RENDERING_SIZE",
  33. UVec2(m_r->getInternalResolution().x(), m_r->getInternalResolution().y()));
  34. const ShaderProgramResourceVariant* variant;
  35. m_prog->getOrCreateVariant(variantInitInfo, variant);
  36. m_grProg = variant->getProgram();
  37. m_tileCount = m_r->getTileCounts().x() * m_r->getTileCounts().y();
  38. m_clusterCount = m_tileCount + m_r->getZSplitCount();
  39. return Error::NONE;
  40. }
  41. void ClusterBinning::populateRenderGraph(RenderingContext& ctx)
  42. {
  43. m_runCtx.m_ctx = &ctx;
  44. writeClustererBuffers(ctx);
  45. ctx.m_clusteredShading.m_clustersBufferHandle = ctx.m_renderGraphDescr.importBuffer(
  46. ctx.m_clusteredShading.m_clustersToken.m_buffer, BufferUsageBit::NONE,
  47. ctx.m_clusteredShading.m_clustersToken.m_offset, ctx.m_clusteredShading.m_clustersToken.m_range);
  48. const RenderQueue& rqueue = *ctx.m_renderQueue;
  49. if(ANKI_LIKELY(rqueue.m_pointLights.getSize() || rqueue.m_spotLights.getSize() || rqueue.m_decals.getSize()
  50. || rqueue.m_reflectionProbes.getSize() || rqueue.m_fogDensityVolumes.getSize()
  51. || rqueue.m_giProbes.getSize()))
  52. {
  53. RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
  54. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("Cluster Binning");
  55. pass.newDependency(
  56. RenderPassDependency(ctx.m_clusteredShading.m_clustersBufferHandle, BufferUsageBit::STORAGE_COMPUTE_WRITE));
  57. pass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
  58. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  59. const ClusteredShadingContext& tokens = ctx.m_clusteredShading;
  60. cmdb->bindShaderProgram(m_grProg);
  61. bindUniforms(cmdb, 0, 0, tokens.m_clusteredShadingUniformsToken);
  62. bindStorage(cmdb, 0, 1, tokens.m_clustersToken);
  63. bindUniforms(cmdb, 0, 2, tokens.m_pointLightsToken);
  64. bindUniforms(cmdb, 0, 3, tokens.m_spotLightsToken);
  65. bindUniforms(cmdb, 0, 4, tokens.m_reflectionProbesToken);
  66. bindUniforms(cmdb, 0, 5, tokens.m_globalIlluminationProbesToken);
  67. bindUniforms(cmdb, 0, 6, tokens.m_fogDensityVolumesToken);
  68. bindUniforms(cmdb, 0, 7, tokens.m_decalsToken);
  69. const U32 sampleCount = 4;
  70. const U32 sizex = m_tileCount * sampleCount;
  71. const RenderQueue& rqueue = *ctx.m_renderQueue;
  72. U32 clusterObjectCounts = rqueue.m_pointLights.getSize();
  73. clusterObjectCounts += rqueue.m_spotLights.getSize();
  74. clusterObjectCounts += rqueue.m_reflectionProbes.getSize();
  75. clusterObjectCounts += rqueue.m_giProbes.getSize();
  76. clusterObjectCounts += rqueue.m_fogDensityVolumes.getSize();
  77. clusterObjectCounts += rqueue.m_decals.getSize();
  78. cmdb->dispatchCompute((sizex + 64 - 1) / 64, clusterObjectCounts, 1);
  79. });
  80. }
  81. }
  82. void ClusterBinning::writeClustererBuffers(RenderingContext& ctx)
  83. {
  84. ANKI_TRACE_SCOPED_EVENT(R_WRITE_CLUSTER_SHADING_OBJECTS);
  85. // Check limits
  86. RenderQueue& rqueue = *ctx.m_renderQueue;
  87. if(ANKI_UNLIKELY(rqueue.m_pointLights.getSize() > MAX_VISIBLE_POINT_LIGHTS))
  88. {
  89. ANKI_R_LOGW("Visible point lights exceed the max value by %u",
  90. rqueue.m_pointLights.getSize() - MAX_VISIBLE_POINT_LIGHTS);
  91. rqueue.m_pointLights.setArray(rqueue.m_pointLights.getBegin(), MAX_VISIBLE_POINT_LIGHTS);
  92. }
  93. if(ANKI_UNLIKELY(rqueue.m_spotLights.getSize() > MAX_VISIBLE_SPOT_LIGHTS))
  94. {
  95. ANKI_R_LOGW("Visible spot lights exceed the max value by %u",
  96. rqueue.m_spotLights.getSize() - MAX_VISIBLE_SPOT_LIGHTS);
  97. rqueue.m_spotLights.setArray(rqueue.m_spotLights.getBegin(), MAX_VISIBLE_SPOT_LIGHTS);
  98. }
  99. if(ANKI_UNLIKELY(rqueue.m_decals.getSize() > MAX_VISIBLE_DECALS))
  100. {
  101. ANKI_R_LOGW("Visible decals exceed the max value by %u", rqueue.m_decals.getSize() - MAX_VISIBLE_DECALS);
  102. rqueue.m_decals.setArray(rqueue.m_decals.getBegin(), MAX_VISIBLE_DECALS);
  103. }
  104. if(ANKI_UNLIKELY(rqueue.m_fogDensityVolumes.getSize() > MAX_VISIBLE_FOG_DENSITY_VOLUMES))
  105. {
  106. ANKI_R_LOGW("Visible fog volumes exceed the max value by %u",
  107. rqueue.m_fogDensityVolumes.getSize() - MAX_VISIBLE_FOG_DENSITY_VOLUMES);
  108. rqueue.m_fogDensityVolumes.setArray(rqueue.m_fogDensityVolumes.getBegin(), MAX_VISIBLE_FOG_DENSITY_VOLUMES);
  109. }
  110. if(ANKI_UNLIKELY(rqueue.m_reflectionProbes.getSize() > MAX_VISIBLE_REFLECTION_PROBES))
  111. {
  112. ANKI_R_LOGW("Visible reflection probes exceed the max value by %u",
  113. rqueue.m_reflectionProbes.getSize() - MAX_VISIBLE_REFLECTION_PROBES);
  114. rqueue.m_reflectionProbes.setArray(rqueue.m_reflectionProbes.getBegin(), MAX_VISIBLE_REFLECTION_PROBES);
  115. }
  116. if(ANKI_UNLIKELY(rqueue.m_giProbes.getSize() > MAX_VISIBLE_GLOBAL_ILLUMINATION_PROBES))
  117. {
  118. ANKI_R_LOGW("Visible GI probes exceed the max value by %u",
  119. rqueue.m_giProbes.getSize() - MAX_VISIBLE_GLOBAL_ILLUMINATION_PROBES);
  120. rqueue.m_giProbes.setArray(rqueue.m_giProbes.getBegin(), MAX_VISIBLE_GLOBAL_ILLUMINATION_PROBES);
  121. }
  122. // Allocate buffers
  123. ClusteredShadingContext& cs = ctx.m_clusteredShading;
  124. StagingGpuMemoryManager& stagingMem = m_r->getStagingGpuMemoryManager();
  125. cs.m_clusteredShadingUniformsAddress = stagingMem.allocateFrame(
  126. sizeof(ClusteredShadingUniforms), StagingGpuMemoryType::UNIFORM, cs.m_clusteredShadingUniformsToken);
  127. if(rqueue.m_pointLights.getSize())
  128. {
  129. cs.m_pointLightsAddress = stagingMem.allocateFrame(rqueue.m_pointLights.getSize() * sizeof(PointLight),
  130. StagingGpuMemoryType::UNIFORM, cs.m_pointLightsToken);
  131. }
  132. else
  133. {
  134. cs.m_pointLightsToken.markUnused();
  135. }
  136. if(rqueue.m_spotLights.getSize())
  137. {
  138. cs.m_spotLightsAddress = stagingMem.allocateFrame(rqueue.m_spotLights.getSize() * sizeof(SpotLight),
  139. StagingGpuMemoryType::UNIFORM, cs.m_spotLightsToken);
  140. }
  141. else
  142. {
  143. cs.m_spotLightsToken.markUnused();
  144. }
  145. if(rqueue.m_reflectionProbes.getSize())
  146. {
  147. cs.m_reflectionProbesAddress =
  148. stagingMem.allocateFrame(rqueue.m_reflectionProbes.getSize() * sizeof(ReflectionProbe),
  149. StagingGpuMemoryType::UNIFORM, cs.m_reflectionProbesToken);
  150. }
  151. else
  152. {
  153. cs.m_reflectionProbesToken.markUnused();
  154. }
  155. if(rqueue.m_decals.getSize())
  156. {
  157. cs.m_decalsAddress = stagingMem.allocateFrame(rqueue.m_decals.getSize() * sizeof(Decal),
  158. StagingGpuMemoryType::UNIFORM, cs.m_decalsToken);
  159. }
  160. else
  161. {
  162. cs.m_decalsToken.markUnused();
  163. }
  164. if(rqueue.m_fogDensityVolumes.getSize())
  165. {
  166. cs.m_fogDensityVolumesAddress =
  167. stagingMem.allocateFrame(rqueue.m_fogDensityVolumes.getSize() * sizeof(FogDensityVolume),
  168. StagingGpuMemoryType::UNIFORM, cs.m_fogDensityVolumesToken);
  169. }
  170. else
  171. {
  172. cs.m_fogDensityVolumesToken.markUnused();
  173. }
  174. if(rqueue.m_giProbes.getSize())
  175. {
  176. cs.m_globalIlluminationProbesAddress =
  177. stagingMem.allocateFrame(rqueue.m_giProbes.getSize() * sizeof(GlobalIlluminationProbe),
  178. StagingGpuMemoryType::UNIFORM, cs.m_globalIlluminationProbesToken);
  179. }
  180. else
  181. {
  182. cs.m_globalIlluminationProbesToken.markUnused();
  183. }
  184. cs.m_clustersAddress =
  185. stagingMem.allocateFrame(sizeof(Cluster) * m_clusterCount, StagingGpuMemoryType::STORAGE, cs.m_clustersToken);
  186. }
  187. void ClusterBinning::writeClusterBuffersAsync()
  188. {
  189. m_r->getThreadHive().submitTask(
  190. [](void* userData, U32 threadId, ThreadHive& hive, ThreadHiveSemaphore* signalSemaphore) {
  191. static_cast<ClusterBinning*>(userData)->writeClustererBuffersTask();
  192. },
  193. this);
  194. }
  195. void ClusterBinning::writeClustererBuffersTask()
  196. {
  197. ANKI_TRACE_SCOPED_EVENT(R_WRITE_CLUSTER_SHADING_OBJECTS);
  198. RenderingContext& ctx = *m_runCtx.m_ctx;
  199. ClusteredShadingContext& cs = ctx.m_clusteredShading;
  200. const RenderQueue& rqueue = *ctx.m_renderQueue;
  201. // Point lights
  202. if(rqueue.m_pointLights.getSize())
  203. {
  204. PointLight* lights = static_cast<PointLight*>(cs.m_pointLightsAddress);
  205. for(U32 i = 0; i < rqueue.m_pointLights.getSize(); ++i)
  206. {
  207. PointLight& out = lights[i];
  208. const PointLightQueueElement& in = rqueue.m_pointLights[i];
  209. out.m_position = in.m_worldPosition;
  210. out.m_diffuseColor = in.m_diffuseColor;
  211. out.m_radius = in.m_radius;
  212. out.m_squareRadiusOverOne = 1.0f / (in.m_radius * in.m_radius);
  213. if(in.m_shadowRenderQueues[0] == nullptr)
  214. {
  215. out.m_shadowAtlasTileScale = -1.0f;
  216. out.m_shadowLayer = MAX_U32;
  217. }
  218. else
  219. {
  220. out.m_shadowLayer = in.m_shadowLayer;
  221. out.m_shadowAtlasTileScale = in.m_shadowAtlasTileSize;
  222. static_assert(sizeof(out.m_shadowAtlasTileOffsets) == sizeof(in.m_shadowAtlasTileOffsets), "See file");
  223. memcpy(&out.m_shadowAtlasTileOffsets[0], &in.m_shadowAtlasTileOffsets[0],
  224. sizeof(in.m_shadowAtlasTileOffsets));
  225. }
  226. }
  227. }
  228. // Spot lights
  229. if(rqueue.m_spotLights.getSize())
  230. {
  231. SpotLight* lights = static_cast<SpotLight*>(cs.m_spotLightsAddress);
  232. for(U32 i = 0; i < rqueue.m_spotLights.getSize(); ++i)
  233. {
  234. const SpotLightQueueElement& in = rqueue.m_spotLights[i];
  235. SpotLight& out = lights[i];
  236. out.m_position = in.m_worldTransform.getTranslationPart().xyz();
  237. memcpy(&out.m_edgePoints[0][0], &in.m_edgePoints[0][0], sizeof(out.m_edgePoints));
  238. out.m_diffuseColor = in.m_diffuseColor;
  239. out.m_radius = in.m_distance;
  240. out.m_squareRadiusOverOne = 1.0f / (in.m_distance * in.m_distance);
  241. out.m_shadowLayer = (in.hasShadow()) ? in.m_shadowLayer : MAX_U32;
  242. out.m_direction = -in.m_worldTransform.getRotationPart().getZAxis();
  243. out.m_outerCos = cos(in.m_outerAngle / 2.0f);
  244. out.m_innerCos = cos(in.m_innerAngle / 2.0f);
  245. if(in.hasShadow())
  246. {
  247. // bias * proj_l * view_l
  248. out.m_textureMatrix = in.m_textureMatrix;
  249. }
  250. else
  251. {
  252. out.m_textureMatrix = Mat4::getIdentity();
  253. }
  254. }
  255. }
  256. // Reflection probes
  257. if(rqueue.m_reflectionProbes.getSize())
  258. {
  259. ReflectionProbe* probes = static_cast<ReflectionProbe*>(cs.m_reflectionProbesAddress);
  260. for(U32 i = 0; i < rqueue.m_reflectionProbes.getSize(); ++i)
  261. {
  262. const ReflectionProbeQueueElement& in = rqueue.m_reflectionProbes[i];
  263. ReflectionProbe& out = probes[i];
  264. out.m_position = in.m_worldPosition;
  265. out.m_cubemapIndex = F32(in.m_textureArrayIndex);
  266. out.m_aabbMin = in.m_aabbMin;
  267. out.m_aabbMax = in.m_aabbMax;
  268. }
  269. }
  270. // Decals
  271. if(rqueue.m_decals.getSize())
  272. {
  273. Decal* decals = static_cast<Decal*>(cs.m_decalsAddress);
  274. TextureView* diffuseAtlas = nullptr;
  275. TextureView* specularRoughnessAtlas = nullptr;
  276. for(U32 i = 0; i < rqueue.m_decals.getSize(); ++i)
  277. {
  278. const DecalQueueElement& in = rqueue.m_decals[i];
  279. Decal& out = decals[i];
  280. if((diffuseAtlas != nullptr && diffuseAtlas != in.m_diffuseAtlas)
  281. || (specularRoughnessAtlas != nullptr && specularRoughnessAtlas != in.m_specularRoughnessAtlas))
  282. {
  283. ANKI_R_LOGF("All decals should have the same tex atlas");
  284. }
  285. diffuseAtlas = in.m_diffuseAtlas;
  286. specularRoughnessAtlas = in.m_specularRoughnessAtlas;
  287. // Diff
  288. Vec4 uv = in.m_diffuseAtlasUv;
  289. out.m_diffuseUv = Vec4(uv.x(), uv.y(), uv.z() - uv.x(), uv.w() - uv.y());
  290. out.m_blendFactors[0] = in.m_diffuseAtlasBlendFactor;
  291. // Other
  292. uv = in.m_specularRoughnessAtlasUv;
  293. out.m_normRoughnessUv = Vec4(uv.x(), uv.y(), uv.z() - uv.x(), uv.w() - uv.y());
  294. out.m_blendFactors[1] = in.m_specularRoughnessAtlasBlendFactor;
  295. // bias * proj_l * view
  296. out.m_textureMatrix = in.m_textureMatrix;
  297. // Transform
  298. const Mat4 trf(in.m_obbCenter.xyz1(), in.m_obbRotation, 1.0f);
  299. out.m_invertedTransform = trf.getInverse();
  300. out.m_obbExtend = in.m_obbExtend;
  301. }
  302. ANKI_ASSERT(diffuseAtlas || specularRoughnessAtlas);
  303. ctx.m_clusteredShading.m_diffuseDecalTextureView.reset(diffuseAtlas);
  304. ctx.m_clusteredShading.m_specularRoughnessDecalTextureView.reset(specularRoughnessAtlas);
  305. }
  306. // Fog volumes
  307. if(rqueue.m_fogDensityVolumes.getSize())
  308. {
  309. FogDensityVolume* volumes = static_cast<FogDensityVolume*>(cs.m_fogDensityVolumesAddress);
  310. for(U32 i = 0; i < rqueue.m_fogDensityVolumes.getSize(); ++i)
  311. {
  312. const FogDensityQueueElement& in = rqueue.m_fogDensityVolumes[i];
  313. FogDensityVolume& out = volumes[i];
  314. out.m_density = in.m_density;
  315. if(in.m_isBox)
  316. {
  317. out.m_isBox = 1;
  318. out.m_aabbMinOrSphereCenter = in.m_aabbMin;
  319. out.m_aabbMaxOrSphereRadiusSquared = in.m_aabbMax;
  320. }
  321. else
  322. {
  323. out.m_isBox = 0;
  324. out.m_aabbMinOrSphereCenter = in.m_sphereCenter;
  325. out.m_aabbMaxOrSphereRadiusSquared = Vec3(in.m_sphereRadius * in.m_sphereRadius);
  326. }
  327. }
  328. }
  329. // GI
  330. if(rqueue.m_giProbes.getSize())
  331. {
  332. GlobalIlluminationProbe* probes = static_cast<GlobalIlluminationProbe*>(cs.m_globalIlluminationProbesAddress);
  333. for(U32 i = 0; i < rqueue.m_giProbes.getSize(); ++i)
  334. {
  335. const GlobalIlluminationProbeQueueElement& in = rqueue.m_giProbes[i];
  336. GlobalIlluminationProbe& out = probes[i];
  337. out.m_aabbMin = in.m_aabbMin;
  338. out.m_aabbMax = in.m_aabbMax;
  339. out.m_textureIndex = U32(&in - &rqueue.m_giProbes.getFront());
  340. out.m_halfTexelSizeU = 1.0f / F32(F32(in.m_cellCounts.x()) * 6.0f) / 2.0f;
  341. out.m_fadeDistance = in.m_fadeDistance;
  342. }
  343. }
  344. // General uniforms
  345. {
  346. ClusteredShadingUniforms& unis = *static_cast<ClusteredShadingUniforms*>(cs.m_clusteredShadingUniformsAddress);
  347. unis.m_renderingSize = Vec2(F32(m_r->getInternalResolution().x()), F32(m_r->getInternalResolution().y()));
  348. unis.m_time = F32(HighRezTimer::getCurrentTime());
  349. unis.m_frame = m_r->getFrameCount() & MAX_U32;
  350. Plane nearPlane;
  351. extractClipPlane(rqueue.m_viewProjectionMatrix, FrustumPlaneType::NEAR, nearPlane);
  352. unis.m_nearPlaneWSpace = Vec4(nearPlane.getNormal().xyz(), nearPlane.getOffset());
  353. unis.m_near = rqueue.m_cameraNear;
  354. unis.m_far = rqueue.m_cameraFar;
  355. unis.m_cameraPosition = rqueue.m_cameraTransform.getTranslationPart().xyz();
  356. unis.m_tileCounts = m_r->getTileCounts();
  357. unis.m_zSplitCount = m_r->getZSplitCount();
  358. unis.m_zSplitCountOverFrustumLength = F32(m_r->getZSplitCount()) / (rqueue.m_cameraFar - rqueue.m_cameraNear);
  359. unis.m_zSplitMagic.x() =
  360. (rqueue.m_cameraNear - rqueue.m_cameraFar) / (rqueue.m_cameraNear * F32(m_r->getZSplitCount()));
  361. unis.m_zSplitMagic.y() = rqueue.m_cameraFar / (rqueue.m_cameraNear * F32(m_r->getZSplitCount()));
  362. unis.m_tileSize = m_r->getTileSize();
  363. unis.m_lightVolumeLastZSplit = m_r->getVolumetricLightingAccumulation().getFinalZSplit();
  364. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_POINT_LIGHT] = rqueue.m_pointLights.getSize();
  365. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_SPOT_LIGHT] =
  366. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_SPOT_LIGHT - 1] + rqueue.m_spotLights.getSize();
  367. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_DECAL] =
  368. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_DECAL - 1] + rqueue.m_decals.getSize();
  369. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_FOG_DENSITY_VOLUME] =
  370. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_FOG_DENSITY_VOLUME - 1] + rqueue.m_fogDensityVolumes.getSize();
  371. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_REFLECTION_PROBE] =
  372. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_REFLECTION_PROBE - 1] + rqueue.m_reflectionProbes.getSize();
  373. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_GLOBAL_ILLUMINATION_PROBE] =
  374. unis.m_objectCountsUpTo[CLUSTER_OBJECT_TYPE_GLOBAL_ILLUMINATION_PROBE - 1] + rqueue.m_giProbes.getSize();
  375. unis.m_matrices = ctx.m_matrices;
  376. unis.m_previousMatrices = ctx.m_prevMatrices;
  377. // Directional light
  378. if(rqueue.m_directionalLight.m_uuid != 0)
  379. {
  380. DirectionalLight& out = unis.m_directionalLight;
  381. const DirectionalLightQueueElement& in = rqueue.m_directionalLight;
  382. out.m_diffuseColor = in.m_diffuseColor;
  383. out.m_cascadeCount = in.m_shadowCascadeCount;
  384. out.m_direction = in.m_direction;
  385. out.m_active = 1;
  386. out.m_effectiveShadowDistance = in.m_effectiveShadowDistance;
  387. out.m_shadowCascadesDistancePower = in.m_shadowCascadesDistancePower;
  388. out.m_shadowLayer = (in.hasShadow()) ? in.m_shadowLayer : MAX_U32;
  389. for(U cascade = 0; cascade < in.m_shadowCascadeCount; ++cascade)
  390. {
  391. out.m_textureMatrices[cascade] = in.m_textureMatrices[cascade];
  392. }
  393. }
  394. else
  395. {
  396. unis.m_directionalLight.m_active = 0;
  397. }
  398. }
  399. // Zero the memory because atomics will happen
  400. memset(cs.m_clustersAddress, 0, sizeof(Cluster) * m_clusterCount);
  401. }
  402. } // end namespace anki