ClusterBinning.cpp 17 KB

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