LightBin.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. // Copyright (C) 2009-2018, 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/LightBin.h>
  6. #include <anki/renderer/RenderQueue.h>
  7. #include <anki/core/Trace.h>
  8. #include <anki/util/ThreadPool.h>
  9. #include <anki/collision/Sphere.h>
  10. #include <anki/collision/Frustum.h>
  11. #include <shaders/glsl_cpp_common/ClusteredShading.h>
  12. namespace anki
  13. {
  14. /// This should be the number of light types. For now it's spots & points & probes & decals.
  15. const U SIZE_IDX_COUNT = 4;
  16. // Shader structs and block representations. All positions and directions in viewspace
  17. // For documentation see the shaders
  18. class LightBin::ShaderCluster
  19. {
  20. public:
  21. U32 m_firstIdx;
  22. };
  23. static const U MAX_TYPED_LIGHTS_PER_CLUSTER = 16;
  24. static const U MAX_PROBES_PER_CLUSTER = 12;
  25. static const U MAX_DECALS_PER_CLUSTER = 8;
  26. static const F32 INVALID_TEXTURE_INDEX = -1.0;
  27. class LightBin::ClusterLightIndex
  28. {
  29. public:
  30. ClusterLightIndex()
  31. {
  32. // Do nothing. No need to initialize
  33. }
  34. U getIndex() const
  35. {
  36. return m_index;
  37. }
  38. void setIndex(U i)
  39. {
  40. ANKI_ASSERT(i <= MAX_U16);
  41. m_index = i;
  42. }
  43. friend Bool operator<(const ClusterLightIndex& a, const ClusterLightIndex& b)
  44. {
  45. return a.getIndex() < b.getIndex();
  46. }
  47. private:
  48. U16 m_index;
  49. };
  50. /// Store the probe radius for sorting the indices.
  51. /// WARNING: Keep it as small as possible, that's why the members are U16
  52. class LightBin::ClusterProbeIndex
  53. {
  54. public:
  55. ClusterProbeIndex()
  56. {
  57. // Do nothing. No need to initialize
  58. static_assert(sizeof(ClusterProbeIndex) == sizeof(U16) * 2, "Because we memcmp");
  59. }
  60. U getIndex() const
  61. {
  62. return m_index;
  63. }
  64. void setIndex(U i)
  65. {
  66. ANKI_ASSERT(i <= MAX_U16);
  67. m_index = i;
  68. }
  69. void setProbeVolume(F32 v)
  70. {
  71. ANKI_ASSERT(v < MAX_PROBE_VOLUME);
  72. m_probeVolume = v / F32(MAX_PROBE_VOLUME) * F32(MAX_U16);
  73. }
  74. Bool operator<(const ClusterProbeIndex& b) const
  75. {
  76. ANKI_ASSERT(m_probeVolume > 0 && b.m_probeVolume > 0);
  77. return (m_probeVolume != b.m_probeVolume) ? (m_probeVolume > b.m_probeVolume) : (m_index < b.m_index);
  78. }
  79. private:
  80. static const U MAX_PROBE_VOLUME = 1000;
  81. U16 m_index;
  82. U16 m_probeVolume;
  83. };
  84. /// WARNING: Keep it as small as possible. The number of clusters is huge
  85. class alignas(U32) LightBin::ClusterData
  86. {
  87. public:
  88. Atomic<U8> m_pointCount;
  89. Atomic<U8> m_spotCount;
  90. Atomic<U8> m_probeCount;
  91. Atomic<U8> m_decalCount;
  92. Array<ClusterLightIndex, MAX_TYPED_LIGHTS_PER_CLUSTER> m_pointIds;
  93. Array<ClusterLightIndex, MAX_TYPED_LIGHTS_PER_CLUSTER> m_spotIds;
  94. Array<ClusterProbeIndex, MAX_PROBES_PER_CLUSTER> m_probeIds;
  95. Array<ClusterLightIndex, MAX_DECALS_PER_CLUSTER> m_decalIds;
  96. ClusterData()
  97. {
  98. // Do nothing. No need to initialize
  99. }
  100. void reset()
  101. {
  102. // Set the counts to zero and try to be faster
  103. *reinterpret_cast<U32*>(&m_pointCount) = 0;
  104. }
  105. void normalizeCounts()
  106. {
  107. normalize(m_pointCount, MAX_TYPED_LIGHTS_PER_CLUSTER, "point lights");
  108. normalize(m_spotCount, MAX_TYPED_LIGHTS_PER_CLUSTER, "spot lights");
  109. normalize(m_probeCount, MAX_PROBES_PER_CLUSTER, "probes");
  110. normalize(m_decalCount, MAX_DECALS_PER_CLUSTER, "decals");
  111. }
  112. void sortLightIds()
  113. {
  114. const U pointCount = m_pointCount.get();
  115. if(pointCount > 1)
  116. {
  117. std::sort(&m_pointIds[0], &m_pointIds[0] + pointCount);
  118. }
  119. const U spotCount = m_spotCount.get();
  120. if(spotCount > 1)
  121. {
  122. std::sort(&m_spotIds[0], &m_spotIds[0] + spotCount);
  123. }
  124. const U probeCount = m_probeCount.get();
  125. if(probeCount > 1)
  126. {
  127. std::sort(m_probeIds.getBegin(), m_probeIds.getBegin() + probeCount);
  128. }
  129. const U decalCount = m_decalCount.get();
  130. if(decalCount > 1)
  131. {
  132. std::sort(&m_decalIds[0], &m_decalIds[0] + decalCount);
  133. }
  134. }
  135. Bool operator==(const ClusterData& b) const
  136. {
  137. const U pointCount = m_pointCount.get();
  138. const U spotCount = m_spotCount.get();
  139. const U probeCount = m_probeCount.get();
  140. const U decalCount = m_decalCount.get();
  141. const U pointCount2 = b.m_pointCount.get();
  142. const U spotCount2 = b.m_spotCount.get();
  143. const U probeCount2 = b.m_probeCount.get();
  144. const U decalCount2 = b.m_decalCount.get();
  145. if(pointCount != pointCount2 || spotCount != spotCount2 || probeCount != probeCount2
  146. || decalCount != decalCount2)
  147. {
  148. return false;
  149. }
  150. if(pointCount > 0)
  151. {
  152. if(memcmp(&m_pointIds[0], &b.m_pointIds[0], sizeof(m_pointIds[0]) * pointCount) != 0)
  153. {
  154. return false;
  155. }
  156. }
  157. if(spotCount > 0)
  158. {
  159. if(memcmp(&m_spotIds[0], &b.m_spotIds[0], sizeof(m_spotIds[0]) * spotCount) != 0)
  160. {
  161. return false;
  162. }
  163. }
  164. if(probeCount > 0)
  165. {
  166. if(memcmp(&m_probeIds[0], &b.m_probeIds[0], sizeof(b.m_probeIds[0]) * probeCount) != 0)
  167. {
  168. return false;
  169. }
  170. }
  171. if(decalCount > 0)
  172. {
  173. if(memcmp(&m_decalIds[0], &b.m_decalIds[0], sizeof(b.m_decalIds[0]) * decalCount) != 0)
  174. {
  175. return false;
  176. }
  177. }
  178. return true;
  179. }
  180. private:
  181. static void normalize(Atomic<U8>& count, const U maxCount, CString what)
  182. {
  183. U8 a = count.get();
  184. count.set(a % maxCount);
  185. if(ANKI_UNLIKELY(a >= maxCount))
  186. {
  187. ANKI_R_LOGW("Increase cluster limit: %s", &what[0]);
  188. }
  189. }
  190. };
  191. /// Common data for all tasks.
  192. class LightBin::BinContext
  193. {
  194. public:
  195. BinContext(StackAllocator<U8> alloc)
  196. : m_alloc(alloc)
  197. , m_tempClusters(alloc)
  198. {
  199. }
  200. Mat4 m_viewMat;
  201. Mat4 m_viewProjMat;
  202. Mat4 m_camTrf;
  203. U32 m_maxLightIndices = 0;
  204. Bool m_shadowsEnabled = false;
  205. StackAllocator<U8> m_alloc;
  206. // To fill the light buffers
  207. WeakArray<PointLight> m_pointLights;
  208. WeakArray<SpotLight> m_spotLights;
  209. WeakArray<ReflectionProbe> m_probes;
  210. WeakArray<Decal> m_decals;
  211. WeakArray<U32> m_lightIds;
  212. WeakArray<ShaderCluster> m_clusters;
  213. Atomic<U32> m_pointLightsCount = {0};
  214. Atomic<U32> m_spotLightsCount = {0};
  215. Atomic<U32> m_probeCount = {0};
  216. Atomic<U32> m_decalCount = {0};
  217. // To fill the tile buffers
  218. DynamicArrayAuto<ClusterData> m_tempClusters;
  219. // To fill the light index buffer
  220. Atomic<U32> m_lightIdsCount = {0};
  221. // Misc
  222. WeakArray<const PointLightQueueElement> m_vPointLights;
  223. WeakArray<const SpotLightQueueElement> m_vSpotLights;
  224. WeakArray<const ReflectionProbeQueueElement> m_vProbes;
  225. WeakArray<const DecalQueueElement> m_vDecals;
  226. Atomic<U32> m_count = {0};
  227. Atomic<U32> m_count2 = {0};
  228. TextureViewPtr m_diffDecalTexAtlas;
  229. SpinLock m_diffDecalTexAtlasMtx;
  230. TextureViewPtr m_specularRoughnessDecalTexAtlas;
  231. SpinLock m_specularRoughnessDecalTexAtlasMtx;
  232. LightBin* m_bin = nullptr;
  233. };
  234. /// Write the lights to the GPU buffers.
  235. class LightBin::WriteLightsTask : public ThreadPoolTask
  236. {
  237. public:
  238. BinContext* m_ctx = nullptr;
  239. Error operator()(U32 threadId, PtrSize threadsCount)
  240. {
  241. m_ctx->m_bin->binLights(threadId, threadsCount, *m_ctx);
  242. return Error::NONE;
  243. }
  244. };
  245. LightBin::LightBin(const GenericMemoryPoolAllocator<U8>& alloc,
  246. U clusterCountX,
  247. U clusterCountY,
  248. U clusterCountZ,
  249. ThreadPool* threadPool,
  250. StagingGpuMemoryManager* stagingMem)
  251. : m_alloc(alloc)
  252. , m_clusterCount(clusterCountX * clusterCountY * clusterCountZ)
  253. , m_threadPool(threadPool)
  254. , m_stagingMem(stagingMem)
  255. , m_barrier(threadPool->getThreadCount())
  256. {
  257. m_clusterer.init(alloc, clusterCountX, clusterCountY, clusterCountZ);
  258. }
  259. LightBin::~LightBin()
  260. {
  261. }
  262. Error LightBin::bin(const Mat4& viewMat,
  263. const Mat4& projMat,
  264. const Mat4& viewProjMat,
  265. const Mat4& camTrf,
  266. const RenderQueue& rqueue,
  267. StackAllocator<U8> frameAlloc,
  268. U maxLightIndices,
  269. Bool shadowsEnabled,
  270. LightBinOut& out)
  271. {
  272. ANKI_TRACE_SCOPED_EVENT(R_LIGHT_BINNING);
  273. // Prepare the clusterer
  274. ClustererPrepareInfo pinf;
  275. pinf.m_viewMat = viewMat;
  276. pinf.m_projMat = projMat;
  277. pinf.m_viewProjMat = viewProjMat;
  278. pinf.m_camTrf = Transform(camTrf);
  279. pinf.m_near = rqueue.m_cameraNear;
  280. pinf.m_far = rqueue.m_cameraFar;
  281. m_clusterer.prepare(*m_threadPool, pinf);
  282. //
  283. // Quickly get the lights
  284. //
  285. const U visiblePointLightsCount = rqueue.m_pointLights.getSize();
  286. const U visibleSpotLightsCount = rqueue.m_spotLights.getSize();
  287. const U visibleProbeCount = rqueue.m_reflectionProbes.getSize();
  288. const U visibleDecalCount = rqueue.m_decals.getSize();
  289. ANKI_TRACE_INC_COUNTER(R_LIGHTS, visiblePointLightsCount + visibleSpotLightsCount);
  290. //
  291. // Write the lights and tiles UBOs
  292. //
  293. Array<WriteLightsTask, ThreadPool::MAX_THREADS> tasks;
  294. BinContext ctx(frameAlloc);
  295. ctx.m_viewMat = viewMat;
  296. ctx.m_viewProjMat = viewProjMat;
  297. ctx.m_camTrf = camTrf;
  298. ctx.m_maxLightIndices = maxLightIndices;
  299. ctx.m_shadowsEnabled = shadowsEnabled;
  300. ctx.m_tempClusters.create(m_clusterCount);
  301. if(visiblePointLightsCount)
  302. {
  303. PointLight* data = static_cast<PointLight*>(m_stagingMem->allocateFrame(
  304. sizeof(PointLight) * visiblePointLightsCount, StagingGpuMemoryType::UNIFORM, out.m_pointLightsToken));
  305. ctx.m_pointLights = WeakArray<PointLight>(data, visiblePointLightsCount);
  306. ctx.m_vPointLights =
  307. WeakArray<const PointLightQueueElement>(rqueue.m_pointLights.getBegin(), visiblePointLightsCount);
  308. }
  309. else
  310. {
  311. out.m_pointLightsToken.markUnused();
  312. }
  313. if(visibleSpotLightsCount)
  314. {
  315. SpotLight* data = static_cast<SpotLight*>(m_stagingMem->allocateFrame(
  316. sizeof(SpotLight) * visibleSpotLightsCount, StagingGpuMemoryType::UNIFORM, out.m_spotLightsToken));
  317. ctx.m_spotLights = WeakArray<SpotLight>(data, visibleSpotLightsCount);
  318. ctx.m_vSpotLights =
  319. WeakArray<const SpotLightQueueElement>(rqueue.m_spotLights.getBegin(), visibleSpotLightsCount);
  320. }
  321. else
  322. {
  323. out.m_spotLightsToken.markUnused();
  324. }
  325. if(visibleProbeCount)
  326. {
  327. ReflectionProbe* data = static_cast<ReflectionProbe*>(m_stagingMem->allocateFrame(
  328. sizeof(ReflectionProbe) * visibleProbeCount, StagingGpuMemoryType::UNIFORM, out.m_probesToken));
  329. ctx.m_probes = WeakArray<ReflectionProbe>(data, visibleProbeCount);
  330. ctx.m_vProbes =
  331. WeakArray<const ReflectionProbeQueueElement>(rqueue.m_reflectionProbes.getBegin(), visibleProbeCount);
  332. }
  333. else
  334. {
  335. out.m_probesToken.markUnused();
  336. }
  337. if(visibleDecalCount)
  338. {
  339. Decal* data = static_cast<Decal*>(m_stagingMem->allocateFrame(
  340. sizeof(Decal) * visibleDecalCount, StagingGpuMemoryType::UNIFORM, out.m_decalsToken));
  341. ctx.m_decals = WeakArray<Decal>(data, visibleDecalCount);
  342. ctx.m_vDecals = WeakArray<const DecalQueueElement>(rqueue.m_decals.getBegin(), visibleDecalCount);
  343. }
  344. else
  345. {
  346. out.m_decalsToken.markUnused();
  347. }
  348. ctx.m_bin = this;
  349. // Get mem for clusters
  350. ShaderCluster* data = static_cast<ShaderCluster*>(m_stagingMem->allocateFrame(
  351. sizeof(ShaderCluster) * m_clusterCount, StagingGpuMemoryType::STORAGE, out.m_clustersToken));
  352. ctx.m_clusters = WeakArray<ShaderCluster>(data, m_clusterCount);
  353. // Allocate light IDs
  354. U32* data2 = static_cast<U32*>(m_stagingMem->allocateFrame(
  355. maxLightIndices * sizeof(U32), StagingGpuMemoryType::STORAGE, out.m_lightIndicesToken));
  356. ctx.m_lightIds = WeakArray<U32>(data2, maxLightIndices);
  357. // Fill the first part of light ids with invalid indices. Will be used for empty clusters
  358. for(U i = 0; i < SIZE_IDX_COUNT; ++i)
  359. {
  360. ctx.m_lightIds[i] = 0;
  361. }
  362. ctx.m_lightIdsCount.set(SIZE_IDX_COUNT);
  363. // Fire the async job
  364. for(U i = 0; i < m_threadPool->getThreadCount(); i++)
  365. {
  366. tasks[i].m_ctx = &ctx;
  367. m_threadPool->assignNewTask(i, &tasks[i]);
  368. }
  369. // Sync
  370. ANKI_CHECK(m_threadPool->waitForAllThreadsToFinish());
  371. out.m_diffDecalTexView = ctx.m_diffDecalTexAtlas;
  372. out.m_specularRoughnessDecalTexView = ctx.m_specularRoughnessDecalTexAtlas;
  373. return Error::NONE;
  374. }
  375. void LightBin::binLights(U32 threadId, PtrSize threadsCount, BinContext& ctx)
  376. {
  377. U clusterCount = m_clusterCount;
  378. PtrSize start, end;
  379. //
  380. // Initialize the temp clusters
  381. //
  382. {
  383. ANKI_TRACE_SCOPED_EVENT(R_LIGHT_BINNING);
  384. ThreadPoolTask::choseStartEnd(threadId, threadsCount, clusterCount, start, end);
  385. for(U i = start; i < end; ++i)
  386. {
  387. ctx.m_tempClusters[i].reset();
  388. }
  389. }
  390. m_barrier.wait();
  391. //
  392. // Iterate lights and probes and bin them
  393. //
  394. {
  395. ANKI_TRACE_SCOPED_EVENT(R_LIGHT_BINNING);
  396. ClustererTestResult testResult;
  397. m_clusterer.initTestResults(ctx.m_alloc, testResult);
  398. U lightCount = ctx.m_vPointLights.getSize() + ctx.m_vSpotLights.getSize();
  399. U totalCount = lightCount + ctx.m_vProbes.getSize() + ctx.m_vDecals.getSize();
  400. const U TO_BIN_COUNT = 1;
  401. while((start = ctx.m_count2.fetchAdd(TO_BIN_COUNT)) < totalCount)
  402. {
  403. end = min<U>(start + TO_BIN_COUNT, totalCount);
  404. for(U j = start; j < end; ++j)
  405. {
  406. if(j >= lightCount + ctx.m_vDecals.getSize())
  407. {
  408. U i = j - (lightCount + ctx.m_vDecals.getSize());
  409. writeAndBinProbe(ctx.m_vProbes[i], ctx, testResult);
  410. }
  411. else if(j >= ctx.m_vPointLights.getSize() + ctx.m_vDecals.getSize())
  412. {
  413. U i = j - (ctx.m_vPointLights.getSize() + ctx.m_vDecals.getSize());
  414. writeAndBinSpotLight(ctx.m_vSpotLights[i], ctx, testResult);
  415. }
  416. else if(j >= ctx.m_vDecals.getSize())
  417. {
  418. U i = j - ctx.m_vDecals.getSize();
  419. writeAndBinPointLight(ctx.m_vPointLights[i], ctx, testResult);
  420. }
  421. else
  422. {
  423. U i = j;
  424. writeAndBinDecal(ctx.m_vDecals[i], ctx, testResult);
  425. }
  426. }
  427. }
  428. }
  429. m_barrier.wait();
  430. //
  431. // Last thing, update the real clusters
  432. //
  433. {
  434. ANKI_TRACE_SCOPED_EVENT(R_LIGHT_BINNING);
  435. // Run per cluster
  436. const U CLUSTER_GROUP = 16;
  437. while((start = ctx.m_count.fetchAdd(CLUSTER_GROUP)) < clusterCount)
  438. {
  439. end = min<U>(start + CLUSTER_GROUP, clusterCount);
  440. for(U i = start; i < end; ++i)
  441. {
  442. auto& cluster = ctx.m_tempClusters[i];
  443. cluster.normalizeCounts();
  444. const U countP = cluster.m_pointCount.get();
  445. const U countS = cluster.m_spotCount.get();
  446. const U countProbe = cluster.m_probeCount.get();
  447. const U countDecal = cluster.m_decalCount.get();
  448. const U count = countP + countS + countProbe + countDecal;
  449. auto& c = ctx.m_clusters[i];
  450. c.m_firstIdx = 0; // Point to the first empty indices
  451. // Early exit
  452. if(ANKI_UNLIKELY(count == 0))
  453. {
  454. continue;
  455. }
  456. // Check if the previous cluster contains the same lights as this one and if yes then merge them. This
  457. // will avoid allocating new IDs (and thrashing GPU caches).
  458. cluster.sortLightIds();
  459. if(i != start)
  460. {
  461. const auto& clusterB = ctx.m_tempClusters[i - 1];
  462. if(cluster == clusterB)
  463. {
  464. c.m_firstIdx = ctx.m_clusters[i - 1].m_firstIdx;
  465. continue;
  466. }
  467. }
  468. U offset = ctx.m_lightIdsCount.fetchAdd(count + SIZE_IDX_COUNT);
  469. U initialOffset = offset;
  470. (void)initialOffset;
  471. if(offset + count + SIZE_IDX_COUNT <= ctx.m_maxLightIndices)
  472. {
  473. c.m_firstIdx = offset;
  474. ctx.m_lightIds[offset++] = countDecal;
  475. for(U i = 0; i < countDecal; ++i)
  476. {
  477. ctx.m_lightIds[offset++] = cluster.m_decalIds[i].getIndex();
  478. }
  479. ctx.m_lightIds[offset++] = countP;
  480. for(U i = 0; i < countP; ++i)
  481. {
  482. ctx.m_lightIds[offset++] = cluster.m_pointIds[i].getIndex();
  483. }
  484. ctx.m_lightIds[offset++] = countS;
  485. for(U i = 0; i < countS; ++i)
  486. {
  487. ctx.m_lightIds[offset++] = cluster.m_spotIds[i].getIndex();
  488. }
  489. ctx.m_lightIds[offset++] = countProbe;
  490. for(U i = 0; i < countProbe; ++i)
  491. {
  492. ctx.m_lightIds[offset++] = cluster.m_probeIds[i].getIndex();
  493. }
  494. ANKI_ASSERT(offset - initialOffset == count + SIZE_IDX_COUNT);
  495. }
  496. else
  497. {
  498. ANKI_R_LOGW("Light IDs buffer too small");
  499. }
  500. } // end for
  501. } // end while
  502. } // scope
  503. }
  504. void LightBin::writeAndBinPointLight(
  505. const PointLightQueueElement& lightEl, BinContext& ctx, ClustererTestResult& testResult)
  506. {
  507. // Get GPU light
  508. I idx = ctx.m_pointLightsCount.fetchAdd(1);
  509. PointLight& slight = ctx.m_pointLights[idx];
  510. slight.m_posRadius = Vec4(lightEl.m_worldPosition.xyz(), 1.0f / (lightEl.m_radius * lightEl.m_radius));
  511. slight.m_diffuseColorTileSize = lightEl.m_diffuseColor.xyz0();
  512. if(lightEl.m_shadowRenderQueues[0] == nullptr || !ctx.m_shadowsEnabled)
  513. {
  514. slight.m_diffuseColorTileSize.w() = INVALID_TEXTURE_INDEX;
  515. }
  516. else
  517. {
  518. slight.m_diffuseColorTileSize.w() = lightEl.m_atlasTileSize;
  519. slight.m_atlasTiles = UVec2(lightEl.m_atlasTiles.x(), lightEl.m_atlasTiles.y());
  520. }
  521. slight.m_radiusPad1 = Vec2(lightEl.m_radius);
  522. // Now bin it
  523. Sphere sphere(lightEl.m_worldPosition.xyz0(), lightEl.m_radius);
  524. Aabb box;
  525. sphere.computeAabb(box);
  526. m_clusterer.bin(sphere, box, testResult);
  527. auto it = testResult.getClustersBegin();
  528. auto end = testResult.getClustersEnd();
  529. for(; it != end; ++it)
  530. {
  531. U x = (*it).x();
  532. U y = (*it).y();
  533. U z = (*it).z();
  534. U i = m_clusterer.getClusterCountX() * (z * m_clusterer.getClusterCountY() + y) + x;
  535. auto& cluster = ctx.m_tempClusters[i];
  536. i = cluster.m_pointCount.fetchAdd(1) % MAX_TYPED_LIGHTS_PER_CLUSTER;
  537. cluster.m_pointIds[i].setIndex(idx);
  538. }
  539. }
  540. void LightBin::writeAndBinSpotLight(
  541. const SpotLightQueueElement& lightEl, BinContext& ctx, ClustererTestResult& testResult)
  542. {
  543. I idx = ctx.m_spotLightsCount.fetchAdd(1);
  544. SpotLight& light = ctx.m_spotLights[idx];
  545. F32 shadowmapIndex = INVALID_TEXTURE_INDEX;
  546. if(lightEl.hasShadow() && ctx.m_shadowsEnabled)
  547. {
  548. // bias * proj_l * view_l
  549. light.m_texProjectionMat = lightEl.m_textureMatrix;
  550. shadowmapIndex = 1.0f; // Just set a value
  551. }
  552. // Pos & dist
  553. light.m_posRadius =
  554. Vec4(lightEl.m_worldTransform.getTranslationPart().xyz(), 1.0f / (lightEl.m_distance * lightEl.m_distance));
  555. // Diff color and shadowmap ID now
  556. light.m_diffuseColorShadowmapId = Vec4(lightEl.m_diffuseColor, shadowmapIndex);
  557. // Light dir & radius
  558. Vec3 lightDir = -lightEl.m_worldTransform.getRotationPart().getZAxis();
  559. light.m_lightDirRadius = Vec4(lightDir, lightEl.m_distance);
  560. // Angles
  561. light.m_outerCosInnerCos = Vec4(cos(lightEl.m_outerAngle / 2.0f), cos(lightEl.m_innerAngle / 2.0f), 1.0f, 1.0f);
  562. // Bin lights
  563. PerspectiveFrustum shape(lightEl.m_outerAngle, lightEl.m_outerAngle, 0.01f, lightEl.m_distance);
  564. shape.transform(Transform(lightEl.m_worldTransform));
  565. Aabb box;
  566. shape.computeAabb(box);
  567. m_clusterer.binPerspectiveFrustum(shape, box, testResult);
  568. auto it = testResult.getClustersBegin();
  569. auto end = testResult.getClustersEnd();
  570. for(; it != end; ++it)
  571. {
  572. U x = (*it).x();
  573. U y = (*it).y();
  574. U z = (*it).z();
  575. U i = m_clusterer.getClusterCountX() * (z * m_clusterer.getClusterCountY() + y) + x;
  576. auto& cluster = ctx.m_tempClusters[i];
  577. i = cluster.m_spotCount.fetchAdd(1) % MAX_TYPED_LIGHTS_PER_CLUSTER;
  578. cluster.m_spotIds[i].setIndex(idx);
  579. }
  580. }
  581. void LightBin::writeAndBinProbe(
  582. const ReflectionProbeQueueElement& probeEl, BinContext& ctx, ClustererTestResult& testResult)
  583. {
  584. // Write it
  585. ReflectionProbe probe;
  586. probe.m_positionCubemapIndex = Vec4(probeEl.m_worldPosition, probeEl.m_textureArrayIndex);
  587. probe.m_aabbMinPad1 = probeEl.m_aabbMin.xyz0();
  588. probe.m_aabbMaxPad1 = probeEl.m_aabbMax.xyz0();
  589. U idx = ctx.m_probeCount.fetchAdd(1);
  590. ctx.m_probes[idx] = probe;
  591. // Bin it
  592. Aabb box(probeEl.m_aabbMin, probeEl.m_aabbMax);
  593. m_clusterer.bin(box, box, testResult);
  594. auto it = testResult.getClustersBegin();
  595. auto end = testResult.getClustersEnd();
  596. for(; it != end; ++it)
  597. {
  598. U x = (*it).x();
  599. U y = (*it).y();
  600. U z = (*it).z();
  601. U i = m_clusterer.getClusterCountX() * (z * m_clusterer.getClusterCountY() + y) + x;
  602. auto& cluster = ctx.m_tempClusters[i];
  603. i = cluster.m_probeCount.fetchAdd(1) % MAX_PROBES_PER_CLUSTER;
  604. cluster.m_probeIds[i].setIndex(idx);
  605. Vec3 edges = probeEl.m_aabbMax - probeEl.m_aabbMin;
  606. cluster.m_probeIds[i].setProbeVolume(edges.x() * edges.y() * edges.z());
  607. }
  608. }
  609. void LightBin::writeAndBinDecal(const DecalQueueElement& decalEl, BinContext& ctx, ClustererTestResult& testResult)
  610. {
  611. I idx = ctx.m_decalCount.fetchAdd(1);
  612. Decal& decal = ctx.m_decals[idx];
  613. TextureViewPtr atlas(const_cast<TextureView*>(decalEl.m_diffuseAtlas));
  614. Vec4 uv = decalEl.m_diffuseAtlasUv;
  615. decal.m_diffUv = Vec4(uv.x(), uv.y(), uv.z() - uv.x(), uv.w() - uv.y());
  616. decal.m_blendFactors[0] = decalEl.m_diffuseAtlasBlendFactor;
  617. {
  618. LockGuard<SpinLock> lock(ctx.m_diffDecalTexAtlasMtx);
  619. if(ctx.m_diffDecalTexAtlas && ctx.m_diffDecalTexAtlas != atlas)
  620. {
  621. ANKI_R_LOGF("All decals should have the same tex atlas");
  622. }
  623. ctx.m_diffDecalTexAtlas = atlas;
  624. }
  625. atlas.reset(const_cast<TextureView*>(decalEl.m_specularRoughnessAtlas));
  626. uv = decalEl.m_specularRoughnessAtlasUv;
  627. decal.m_normRoughnessUv = Vec4(uv.x(), uv.y(), uv.z() - uv.x(), uv.w() - uv.y());
  628. decal.m_blendFactors[1] = decalEl.m_specularRoughnessAtlasBlendFactor;
  629. if(atlas)
  630. {
  631. LockGuard<SpinLock> lock(ctx.m_specularRoughnessDecalTexAtlasMtx);
  632. if(ctx.m_specularRoughnessDecalTexAtlas && ctx.m_specularRoughnessDecalTexAtlas != atlas)
  633. {
  634. ANKI_R_LOGF("All decals should have the same tex atlas");
  635. }
  636. ctx.m_specularRoughnessDecalTexAtlas = atlas;
  637. }
  638. // bias * proj_l * view_
  639. decal.m_texProjectionMat = decalEl.m_textureMatrix;
  640. // Bin it
  641. Obb obb(decalEl.m_obbCenter.xyz0(), Mat3x4(decalEl.m_obbRotation), decalEl.m_obbExtend.xyz0());
  642. Aabb box;
  643. obb.computeAabb(box);
  644. m_clusterer.bin(obb, box, testResult);
  645. auto it = testResult.getClustersBegin();
  646. auto end = testResult.getClustersEnd();
  647. for(; it != end; ++it)
  648. {
  649. U x = (*it).x();
  650. U y = (*it).y();
  651. U z = (*it).z();
  652. U i = m_clusterer.getClusterCountX() * (z * m_clusterer.getClusterCountY() + y) + x;
  653. auto& cluster = ctx.m_tempClusters[i];
  654. i = cluster.m_decalCount.fetchAdd(1) % MAX_DECALS_PER_CLUSTER;
  655. cluster.m_decalIds[i].setIndex(idx);
  656. }
  657. }
  658. } // end namespace anki