IndirectDiffuseProbes.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  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/IndirectDiffuseProbes.h>
  6. #include <AnKi/Renderer/Renderer.h>
  7. #include <AnKi/Renderer/RenderQueue.h>
  8. #include <AnKi/Core/ConfigSet.h>
  9. #include <AnKi/Util/Tracer.h>
  10. #include <AnKi/Collision/Aabb.h>
  11. #include <AnKi/Collision/Functions.h>
  12. namespace anki {
  13. /// Given a cell index compute its world position.
  14. static Vec3 computeProbeCellPosition(U32 cellIdx, const GlobalIlluminationProbeQueueElement& probe)
  15. {
  16. ANKI_ASSERT(cellIdx < probe.m_totalCellCount);
  17. UVec3 cellCoords;
  18. unflatten3dArrayIndex(probe.m_cellCounts.z(), probe.m_cellCounts.y(), probe.m_cellCounts.x(), cellIdx,
  19. cellCoords.z(), cellCoords.y(), cellCoords.x());
  20. const Vec3 halfCellSize = probe.m_cellSizes / 2.0f;
  21. const Vec3 cellPos = Vec3(cellCoords) * probe.m_cellSizes + halfCellSize + probe.m_aabbMin;
  22. ANKI_ASSERT(cellPos < probe.m_aabbMax);
  23. return cellPos;
  24. }
  25. class IndirectDiffuseProbes::InternalContext
  26. {
  27. public:
  28. IndirectDiffuseProbes* m_gi ANKI_DEBUG_CODE(= numberToPtr<IndirectDiffuseProbes*>(1));
  29. RenderingContext* m_ctx ANKI_DEBUG_CODE(= numberToPtr<RenderingContext*>(1));
  30. GlobalIlluminationProbeQueueElement*
  31. m_probeToUpdateThisFrame ANKI_DEBUG_CODE(= numberToPtr<GlobalIlluminationProbeQueueElement*>(1));
  32. UVec3 m_cellOfTheProbeToUpdateThisFrame ANKI_DEBUG_CODE(= UVec3(MAX_U32));
  33. Array<RenderTargetHandle, GBUFFER_COLOR_ATTACHMENT_COUNT> m_gbufferColorRts;
  34. RenderTargetHandle m_gbufferDepthRt;
  35. RenderTargetHandle m_shadowsRt;
  36. RenderTargetHandle m_lightShadingRt;
  37. WeakArray<RenderTargetHandle> m_irradianceProbeRts;
  38. U32 m_gbufferDrawcallCount ANKI_DEBUG_CODE(= MAX_U32);
  39. U32 m_smDrawcallCount ANKI_DEBUG_CODE(= MAX_U32);
  40. static void foo()
  41. {
  42. static_assert(std::is_trivially_destructible<InternalContext>::value, "See file");
  43. }
  44. };
  45. IndirectDiffuseProbes::~IndirectDiffuseProbes()
  46. {
  47. m_cacheEntries.destroy(getAllocator());
  48. m_probeUuidToCacheEntryIdx.destroy(getAllocator());
  49. }
  50. const RenderTargetHandle&
  51. IndirectDiffuseProbes::getVolumeRenderTarget(const GlobalIlluminationProbeQueueElement& probe) const
  52. {
  53. ANKI_ASSERT(m_giCtx);
  54. ANKI_ASSERT(&probe >= &m_giCtx->m_ctx->m_renderQueue->m_giProbes.getFront()
  55. && &probe <= &m_giCtx->m_ctx->m_renderQueue->m_giProbes.getBack());
  56. const U32 idx = U32(&probe - &m_giCtx->m_ctx->m_renderQueue->m_giProbes.getFront());
  57. return m_giCtx->m_irradianceProbeRts[idx];
  58. }
  59. void IndirectDiffuseProbes::setRenderGraphDependencies(const RenderingContext& ctx, RenderPassDescriptionBase& pass,
  60. TextureUsageBit usage) const
  61. {
  62. for(U32 idx = 0; idx < ctx.m_renderQueue->m_giProbes.getSize(); ++idx)
  63. {
  64. pass.newDependency({getVolumeRenderTarget(ctx.m_renderQueue->m_giProbes[idx]), usage});
  65. }
  66. }
  67. void IndirectDiffuseProbes::bindVolumeTextures(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx, U32 set,
  68. U32 binding) const
  69. {
  70. for(U32 idx = 0; idx < MAX_VISIBLE_GLOBAL_ILLUMINATION_PROBES; ++idx)
  71. {
  72. if(idx < ctx.m_renderQueue->m_giProbes.getSize())
  73. {
  74. rgraphCtx.bindColorTexture(set, binding, getVolumeRenderTarget(ctx.m_renderQueue->m_giProbes[idx]), idx);
  75. }
  76. else
  77. {
  78. rgraphCtx.m_commandBuffer->bindTexture(set, binding, m_r->getDummyTextureView3d(), idx);
  79. }
  80. }
  81. }
  82. Error IndirectDiffuseProbes::init()
  83. {
  84. const Error err = initInternal();
  85. if(err)
  86. {
  87. ANKI_R_LOGE("Failed to initialize global illumination");
  88. }
  89. return err;
  90. }
  91. Error IndirectDiffuseProbes::initInternal()
  92. {
  93. m_tileSize = getConfig().getRIndirectDiffuseProbeTileResolution();
  94. m_cacheEntries.create(getAllocator(), getConfig().getRIndirectDiffuseProbeMaxCachedProbes());
  95. m_maxVisibleProbes = getConfig().getRIndirectDiffuseProbeMaxVisibleProbes();
  96. ANKI_ASSERT(m_maxVisibleProbes <= MAX_VISIBLE_GLOBAL_ILLUMINATION_PROBES);
  97. ANKI_ASSERT(m_cacheEntries.getSize() >= m_maxVisibleProbes);
  98. ANKI_CHECK(initGBuffer());
  99. ANKI_CHECK(initLightShading());
  100. ANKI_CHECK(initShadowMapping());
  101. ANKI_CHECK(initIrradiance());
  102. return Error::NONE;
  103. }
  104. Error IndirectDiffuseProbes::initGBuffer()
  105. {
  106. // Create RT descriptions
  107. {
  108. RenderTargetDescription texinit = m_r->create2DRenderTargetDescription(
  109. m_tileSize * 6, m_tileSize, GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[0], "GI GBuffer");
  110. // Create color RT descriptions
  111. for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
  112. {
  113. texinit.m_format = GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[i];
  114. m_gbuffer.m_colorRtDescrs[i] = texinit;
  115. m_gbuffer.m_colorRtDescrs[i].setName(StringAuto(getAllocator()).sprintf("GI GBuff Col #%u", i).toCString());
  116. m_gbuffer.m_colorRtDescrs[i].bake();
  117. }
  118. // Create depth RT
  119. texinit.m_format = m_r->getDepthNoStencilFormat();
  120. texinit.setName("GI GBuff Depth");
  121. m_gbuffer.m_depthRtDescr = texinit;
  122. m_gbuffer.m_depthRtDescr.bake();
  123. }
  124. // Create FB descr
  125. {
  126. m_gbuffer.m_fbDescr.m_colorAttachmentCount = GBUFFER_COLOR_ATTACHMENT_COUNT;
  127. for(U j = 0; j < GBUFFER_COLOR_ATTACHMENT_COUNT; ++j)
  128. {
  129. m_gbuffer.m_fbDescr.m_colorAttachments[j].m_loadOperation = AttachmentLoadOperation::CLEAR;
  130. }
  131. m_gbuffer.m_fbDescr.m_depthStencilAttachment.m_aspect = DepthStencilAspectBit::DEPTH;
  132. m_gbuffer.m_fbDescr.m_depthStencilAttachment.m_loadOperation = AttachmentLoadOperation::CLEAR;
  133. m_gbuffer.m_fbDescr.m_depthStencilAttachment.m_clearValue.m_depthStencil.m_depth = 1.0f;
  134. m_gbuffer.m_fbDescr.bake();
  135. }
  136. return Error::NONE;
  137. }
  138. Error IndirectDiffuseProbes::initShadowMapping()
  139. {
  140. const U32 resolution = getConfig().getRIndirectDiffuseProbeShadowMapResolution();
  141. ANKI_ASSERT(resolution > 8);
  142. // RT descr
  143. m_shadowMapping.m_rtDescr =
  144. m_r->create2DRenderTargetDescription(resolution * 6, resolution, m_r->getDepthNoStencilFormat(), "GI SM");
  145. m_shadowMapping.m_rtDescr.bake();
  146. // FB descr
  147. m_shadowMapping.m_fbDescr.m_colorAttachmentCount = 0;
  148. m_shadowMapping.m_fbDescr.m_depthStencilAttachment.m_aspect = DepthStencilAspectBit::DEPTH;
  149. m_shadowMapping.m_fbDescr.m_depthStencilAttachment.m_clearValue.m_depthStencil.m_depth = 1.0f;
  150. m_shadowMapping.m_fbDescr.m_depthStencilAttachment.m_loadOperation = AttachmentLoadOperation::CLEAR;
  151. m_shadowMapping.m_fbDescr.bake();
  152. return Error::NONE;
  153. }
  154. Error IndirectDiffuseProbes::initLightShading()
  155. {
  156. // Init RT descr
  157. {
  158. m_lightShading.m_rtDescr =
  159. m_r->create2DRenderTargetDescription(m_tileSize * 6, m_tileSize, m_r->getHdrFormat(), "GI LS");
  160. m_lightShading.m_rtDescr.bake();
  161. }
  162. // Create FB descr
  163. {
  164. m_lightShading.m_fbDescr.m_colorAttachmentCount = 1;
  165. m_lightShading.m_fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::CLEAR;
  166. m_lightShading.m_fbDescr.bake();
  167. }
  168. // Init deferred
  169. ANKI_CHECK(m_lightShading.m_deferred.init());
  170. return Error::NONE;
  171. }
  172. Error IndirectDiffuseProbes::initIrradiance()
  173. {
  174. ANKI_CHECK(
  175. m_r->getResourceManager().loadResource("ShaderBinaries/IrradianceDice.ankiprogbin", m_irradiance.m_prog));
  176. ShaderProgramResourceVariantInitInfo variantInitInfo(m_irradiance.m_prog);
  177. variantInitInfo.addMutation("WORKGROUP_SIZE_XY", m_tileSize);
  178. variantInitInfo.addMutation("LIGHT_SHADING_TEX", 0);
  179. variantInitInfo.addMutation("STORE_LOCATION", 0);
  180. variantInitInfo.addMutation("SECOND_BOUNCE", 1);
  181. const ShaderProgramResourceVariant* variant;
  182. m_irradiance.m_prog->getOrCreateVariant(variantInitInfo, variant);
  183. m_irradiance.m_grProg = variant->getProgram();
  184. return Error::NONE;
  185. }
  186. void IndirectDiffuseProbes::populateRenderGraph(RenderingContext& rctx)
  187. {
  188. ANKI_TRACE_SCOPED_EVENT(R_GI);
  189. InternalContext* giCtx = rctx.m_tempAllocator.newInstance<InternalContext>();
  190. m_giCtx = giCtx;
  191. giCtx->m_gi = this;
  192. giCtx->m_ctx = &rctx;
  193. RenderGraphDescription& rgraph = rctx.m_renderGraphDescr;
  194. // Prepare the probes
  195. prepareProbes(*giCtx);
  196. const Bool haveProbeToRender = giCtx->m_probeToUpdateThisFrame != nullptr;
  197. if(!haveProbeToRender)
  198. {
  199. // Early exit
  200. return;
  201. }
  202. // Compute task counts for some of the passes
  203. U32 gbufferTaskCount, smTaskCount;
  204. {
  205. giCtx->m_gbufferDrawcallCount = 0;
  206. giCtx->m_smDrawcallCount = 0;
  207. for(const RenderQueue* rq : giCtx->m_probeToUpdateThisFrame->m_renderQueues)
  208. {
  209. ANKI_ASSERT(rq);
  210. giCtx->m_gbufferDrawcallCount += rq->m_renderables.getSize();
  211. if(rq->m_directionalLight.hasShadow())
  212. {
  213. giCtx->m_smDrawcallCount += rq->m_directionalLight.m_shadowRenderQueues[0]->m_renderables.getSize();
  214. }
  215. }
  216. gbufferTaskCount = computeNumberOfSecondLevelCommandBuffers(giCtx->m_gbufferDrawcallCount);
  217. smTaskCount = computeNumberOfSecondLevelCommandBuffers(giCtx->m_smDrawcallCount);
  218. }
  219. // GBuffer
  220. {
  221. // RTs
  222. for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
  223. {
  224. giCtx->m_gbufferColorRts[i] = rgraph.newRenderTarget(m_gbuffer.m_colorRtDescrs[i]);
  225. }
  226. giCtx->m_gbufferDepthRt = rgraph.newRenderTarget(m_gbuffer.m_depthRtDescr);
  227. // Pass
  228. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("GI gbuff");
  229. pass.setFramebufferInfo(m_gbuffer.m_fbDescr, giCtx->m_gbufferColorRts, giCtx->m_gbufferDepthRt);
  230. pass.setWork(gbufferTaskCount, [this, giCtx](RenderPassWorkContext& rgraphCtx) {
  231. runGBufferInThread(rgraphCtx, *giCtx);
  232. });
  233. for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
  234. {
  235. pass.newDependency({giCtx->m_gbufferColorRts[i], TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  236. }
  237. TextureSubresourceInfo subresource(DepthStencilAspectBit::DEPTH);
  238. pass.newDependency({giCtx->m_gbufferDepthRt, TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT, subresource});
  239. }
  240. // Shadow pass. Optional
  241. if(giCtx->m_probeToUpdateThisFrame->m_renderQueues[0]->m_directionalLight.m_uuid
  242. && giCtx->m_probeToUpdateThisFrame->m_renderQueues[0]->m_directionalLight.m_shadowCascadeCount > 0)
  243. {
  244. // Update light matrices
  245. for(U i = 0; i < 6; ++i)
  246. {
  247. ANKI_ASSERT(giCtx->m_probeToUpdateThisFrame->m_renderQueues[i]->m_directionalLight.m_uuid
  248. && giCtx->m_probeToUpdateThisFrame->m_renderQueues[i]->m_directionalLight.m_shadowCascadeCount
  249. == 1);
  250. const F32 xScale = 1.0f / 6.0f;
  251. const F32 yScale = 1.0f;
  252. const F32 xOffset = F32(i) * (1.0f / 6.0f);
  253. const F32 yOffset = 0.0f;
  254. const Mat4 atlasMtx(xScale, 0.0f, 0.0f, xOffset, 0.0f, yScale, 0.0f, yOffset, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
  255. 0.0f, 0.0f, 1.0f);
  256. Mat4& lightMat =
  257. giCtx->m_probeToUpdateThisFrame->m_renderQueues[i]->m_directionalLight.m_textureMatrices[0];
  258. lightMat = atlasMtx * lightMat;
  259. }
  260. // RT
  261. giCtx->m_shadowsRt = rgraph.newRenderTarget(m_shadowMapping.m_rtDescr);
  262. // Pass
  263. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("GI SM");
  264. pass.setFramebufferInfo(m_shadowMapping.m_fbDescr, {}, giCtx->m_shadowsRt);
  265. pass.setWork(smTaskCount, [this, giCtx](RenderPassWorkContext& rgraphCtx) {
  266. runShadowmappingInThread(rgraphCtx, *giCtx);
  267. });
  268. TextureSubresourceInfo subresource(DepthStencilAspectBit::DEPTH);
  269. pass.newDependency({giCtx->m_shadowsRt, TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT, subresource});
  270. }
  271. else
  272. {
  273. giCtx->m_shadowsRt = {};
  274. }
  275. // Light shading pass
  276. {
  277. // RT
  278. giCtx->m_lightShadingRt = rgraph.newRenderTarget(m_lightShading.m_rtDescr);
  279. // Pass
  280. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("GI LS");
  281. pass.setFramebufferInfo(m_lightShading.m_fbDescr, {giCtx->m_lightShadingRt});
  282. pass.setWork(1, [this, giCtx](RenderPassWorkContext& rgraphCtx) {
  283. runLightShading(rgraphCtx, *giCtx);
  284. });
  285. pass.newDependency({giCtx->m_lightShadingRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  286. for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
  287. {
  288. pass.newDependency({giCtx->m_gbufferColorRts[i], TextureUsageBit::SAMPLED_FRAGMENT});
  289. }
  290. pass.newDependency({giCtx->m_gbufferDepthRt, TextureUsageBit::SAMPLED_FRAGMENT,
  291. TextureSubresourceInfo(DepthStencilAspectBit::DEPTH)});
  292. if(giCtx->m_shadowsRt.isValid())
  293. {
  294. pass.newDependency({giCtx->m_shadowsRt, TextureUsageBit::SAMPLED_FRAGMENT});
  295. }
  296. }
  297. // Irradiance pass. First & 2nd bounce
  298. {
  299. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("GI IR");
  300. pass.setWork([this, giCtx](RenderPassWorkContext& rgraphCtx) {
  301. runIrradiance(rgraphCtx, *giCtx);
  302. });
  303. pass.newDependency({giCtx->m_lightShadingRt, TextureUsageBit::SAMPLED_COMPUTE});
  304. for(U32 i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT - 1; ++i)
  305. {
  306. pass.newDependency({giCtx->m_gbufferColorRts[i], TextureUsageBit::SAMPLED_COMPUTE});
  307. }
  308. const U32 probeIdx = U32(giCtx->m_probeToUpdateThisFrame - &giCtx->m_ctx->m_renderQueue->m_giProbes.getFront());
  309. pass.newDependency({giCtx->m_irradianceProbeRts[probeIdx], TextureUsageBit::IMAGE_COMPUTE_WRITE});
  310. }
  311. }
  312. void IndirectDiffuseProbes::prepareProbes(InternalContext& giCtx)
  313. {
  314. RenderingContext& ctx = *giCtx.m_ctx;
  315. giCtx.m_probeToUpdateThisFrame = nullptr;
  316. if(ANKI_UNLIKELY(ctx.m_renderQueue->m_giProbes.getSize() == 0))
  317. {
  318. return;
  319. }
  320. // Iterate the probes and:
  321. // - Find a probe to update this frame
  322. // - Find a probe to update next frame
  323. // - Find the cache entries for each probe
  324. DynamicArray<GlobalIlluminationProbeQueueElement> newListOfProbes;
  325. newListOfProbes.create(ctx.m_tempAllocator, ctx.m_renderQueue->m_giProbes.getSize());
  326. DynamicArray<RenderTargetHandle> volumeRts;
  327. volumeRts.create(ctx.m_tempAllocator, ctx.m_renderQueue->m_giProbes.getSize());
  328. U32 newListOfProbeCount = 0;
  329. Bool foundProbeToUpdateNextFrame = false;
  330. for(U32 probeIdx = 0; probeIdx < ctx.m_renderQueue->m_giProbes.getSize(); ++probeIdx)
  331. {
  332. if(newListOfProbeCount + 1 >= m_maxVisibleProbes)
  333. {
  334. ANKI_R_LOGW("Can't have more that %u visible probes. Increase the r_giMaxVisibleProbes or (somehow) "
  335. "decrease the visible probes",
  336. m_maxVisibleProbes);
  337. break;
  338. }
  339. GlobalIlluminationProbeQueueElement& probe = ctx.m_renderQueue->m_giProbes[probeIdx];
  340. // Find cache entry
  341. const U32 cacheEntryIdx = findBestCacheEntry(probe.m_uuid, m_r->getGlobalTimestamp(), m_cacheEntries,
  342. m_probeUuidToCacheEntryIdx, getAllocator());
  343. if(ANKI_UNLIKELY(cacheEntryIdx == MAX_U32))
  344. {
  345. // Failed
  346. ANKI_R_LOGW("There is not enough space in the indirect lighting atlas for more probes. "
  347. "Increase the r_giMaxCachedProbes or (somehow) decrease the visible probes");
  348. continue;
  349. }
  350. CacheEntry& entry = m_cacheEntries[cacheEntryIdx];
  351. const Bool cacheEntryDirty = entry.m_uuid != probe.m_uuid || entry.m_volumeSize != probe.m_cellCounts
  352. || entry.m_probeAabbMin != probe.m_aabbMin
  353. || entry.m_probeAabbMax != probe.m_aabbMax;
  354. const Bool needsUpdate = cacheEntryDirty || entry.m_renderedCells < probe.m_totalCellCount;
  355. if(ANKI_LIKELY(!needsUpdate))
  356. {
  357. // It's updated, early exit
  358. entry.m_lastUsedTimestamp = m_r->getGlobalTimestamp();
  359. volumeRts[newListOfProbeCount] =
  360. ctx.m_renderGraphDescr.importRenderTarget(entry.m_volumeTex, TextureUsageBit::SAMPLED_FRAGMENT);
  361. newListOfProbes[newListOfProbeCount++] = probe;
  362. continue;
  363. }
  364. // It needs update
  365. const Bool canUpdateThisFrame = giCtx.m_probeToUpdateThisFrame == nullptr && probe.m_renderQueues[0] != nullptr;
  366. const Bool canUpdateNextFrame = !foundProbeToUpdateNextFrame;
  367. if(!canUpdateThisFrame && canUpdateNextFrame)
  368. {
  369. // Probe will (possibly) be updated next frame, inform the probe
  370. foundProbeToUpdateNextFrame = true;
  371. const U32 cellToRender = (cacheEntryDirty) ? 0 : entry.m_renderedCells;
  372. const Vec3 cellPos = computeProbeCellPosition(cellToRender, probe);
  373. probe.m_feedbackCallback(true, probe.m_feedbackCallbackUserData, cellPos.xyz0());
  374. continue;
  375. }
  376. else if(!canUpdateThisFrame)
  377. {
  378. // Can't be updated this frame so remove it from the list
  379. continue;
  380. }
  381. // All good, can use this probe in this frame
  382. if(cacheEntryDirty)
  383. {
  384. entry.m_renderedCells = 0;
  385. entry.m_uuid = probe.m_uuid;
  386. entry.m_probeAabbMin = probe.m_aabbMin;
  387. entry.m_probeAabbMax = probe.m_aabbMax;
  388. entry.m_volumeSize = probe.m_cellCounts;
  389. m_probeUuidToCacheEntryIdx.emplace(getAllocator(), probe.m_uuid, cacheEntryIdx);
  390. }
  391. // Update the cache entry
  392. entry.m_lastUsedTimestamp = m_r->getGlobalTimestamp();
  393. // Init the cache entry textures
  394. const Bool shouldInitTextures = !entry.m_volumeTex.isCreated() || entry.m_volumeSize != probe.m_cellCounts;
  395. if(shouldInitTextures)
  396. {
  397. TextureInitInfo texInit("GiProbeVolume");
  398. texInit.m_type = TextureType::_3D;
  399. texInit.m_format = m_r->getHdrFormat();
  400. texInit.m_width = probe.m_cellCounts.x() * 6;
  401. texInit.m_height = probe.m_cellCounts.y();
  402. texInit.m_depth = probe.m_cellCounts.z();
  403. texInit.m_usage = TextureUsageBit::ALL_COMPUTE | TextureUsageBit::ALL_SAMPLED;
  404. entry.m_volumeTex = m_r->createAndClearRenderTarget(texInit, TextureUsageBit::SAMPLED_FRAGMENT);
  405. }
  406. // Compute the render position
  407. const U32 cellToRender = entry.m_renderedCells++;
  408. ANKI_ASSERT(cellToRender < probe.m_totalCellCount);
  409. unflatten3dArrayIndex(probe.m_cellCounts.z(), probe.m_cellCounts.y(), probe.m_cellCounts.x(), cellToRender,
  410. giCtx.m_cellOfTheProbeToUpdateThisFrame.z(), giCtx.m_cellOfTheProbeToUpdateThisFrame.y(),
  411. giCtx.m_cellOfTheProbeToUpdateThisFrame.x());
  412. // Inform probe about its next frame
  413. if(entry.m_renderedCells == probe.m_totalCellCount)
  414. {
  415. // Don't gather renderables next frame if it's done
  416. probe.m_feedbackCallback(false, probe.m_feedbackCallbackUserData, Vec4(0.0f));
  417. }
  418. else if(!foundProbeToUpdateNextFrame)
  419. {
  420. // Gather rendederables from the same probe next frame
  421. foundProbeToUpdateNextFrame = true;
  422. const Vec3 cellPos = computeProbeCellPosition(entry.m_renderedCells, probe);
  423. probe.m_feedbackCallback(true, probe.m_feedbackCallbackUserData, cellPos.xyz0());
  424. }
  425. // Push the probe to the new list
  426. giCtx.m_probeToUpdateThisFrame = &newListOfProbes[newListOfProbeCount];
  427. newListOfProbes[newListOfProbeCount] = probe;
  428. volumeRts[newListOfProbeCount] =
  429. ctx.m_renderGraphDescr.importRenderTarget(entry.m_volumeTex, TextureUsageBit::SAMPLED_FRAGMENT);
  430. ++newListOfProbeCount;
  431. }
  432. // Replace the probe list in the queue
  433. if(newListOfProbeCount > 0)
  434. {
  435. GlobalIlluminationProbeQueueElement* firstProbe;
  436. U32 probeCount, storage;
  437. newListOfProbes.moveAndReset(firstProbe, probeCount, storage);
  438. ctx.m_renderQueue->m_giProbes = WeakArray<GlobalIlluminationProbeQueueElement>(firstProbe, newListOfProbeCount);
  439. RenderTargetHandle* firstRt;
  440. volumeRts.moveAndReset(firstRt, probeCount, storage);
  441. m_giCtx->m_irradianceProbeRts = WeakArray<RenderTargetHandle>(firstRt, newListOfProbeCount);
  442. }
  443. else
  444. {
  445. ctx.m_renderQueue->m_giProbes = WeakArray<GlobalIlluminationProbeQueueElement>();
  446. newListOfProbes.destroy(ctx.m_tempAllocator);
  447. volumeRts.destroy(ctx.m_tempAllocator);
  448. }
  449. }
  450. void IndirectDiffuseProbes::runGBufferInThread(RenderPassWorkContext& rgraphCtx, InternalContext& giCtx) const
  451. {
  452. ANKI_ASSERT(giCtx.m_probeToUpdateThisFrame);
  453. ANKI_TRACE_SCOPED_EVENT(R_GI);
  454. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  455. const GlobalIlluminationProbeQueueElement& probe = *giCtx.m_probeToUpdateThisFrame;
  456. I32 start, end;
  457. U32 startu, endu;
  458. splitThreadedProblem(rgraphCtx.m_currentSecondLevelCommandBufferIndex, rgraphCtx.m_secondLevelCommandBufferCount,
  459. giCtx.m_gbufferDrawcallCount, startu, endu);
  460. start = I32(startu);
  461. end = I32(endu);
  462. I32 drawcallCount = 0;
  463. for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
  464. {
  465. const I32 faceDrawcallCount = I32(probe.m_renderQueues[faceIdx]->m_renderables.getSize());
  466. const I32 localStart = max(I32(0), start - drawcallCount);
  467. const I32 localEnd = min(faceDrawcallCount, end - drawcallCount);
  468. if(localStart < localEnd)
  469. {
  470. const U32 viewportX = faceIdx * m_tileSize;
  471. cmdb->setViewport(viewportX, 0, m_tileSize, m_tileSize);
  472. cmdb->setScissor(viewportX, 0, m_tileSize, m_tileSize);
  473. const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
  474. ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
  475. m_r->getSceneDrawer().drawRange(
  476. RenderingTechnique::GBUFFER, rqueue.m_viewMatrix, rqueue.m_viewProjectionMatrix,
  477. Mat4::getIdentity(), // Don't care about prev mats since we don't care about velocity
  478. cmdb, m_r->getSamplers().m_trilinearRepeat, rqueue.m_renderables.getBegin() + localStart,
  479. rqueue.m_renderables.getBegin() + localEnd, MAX_LOD_COUNT - 1, MAX_LOD_COUNT - 1);
  480. }
  481. drawcallCount += faceDrawcallCount;
  482. }
  483. ANKI_ASSERT(giCtx.m_gbufferDrawcallCount == U32(drawcallCount));
  484. // It's secondary, no need to restore the state
  485. }
  486. void IndirectDiffuseProbes::runShadowmappingInThread(RenderPassWorkContext& rgraphCtx, InternalContext& giCtx) const
  487. {
  488. ANKI_ASSERT(giCtx.m_probeToUpdateThisFrame);
  489. ANKI_TRACE_SCOPED_EVENT(R_GI);
  490. const GlobalIlluminationProbeQueueElement& probe = *giCtx.m_probeToUpdateThisFrame;
  491. I32 start, end;
  492. U32 startu, endu;
  493. splitThreadedProblem(rgraphCtx.m_currentSecondLevelCommandBufferIndex, rgraphCtx.m_secondLevelCommandBufferCount,
  494. giCtx.m_smDrawcallCount, startu, endu);
  495. start = I32(startu);
  496. end = I32(endu);
  497. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  498. cmdb->setPolygonOffset(1.0f, 1.0f);
  499. I32 drawcallCount = 0;
  500. for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
  501. {
  502. ANKI_ASSERT(probe.m_renderQueues[faceIdx]);
  503. const RenderQueue& faceRenderQueue = *probe.m_renderQueues[faceIdx];
  504. ANKI_ASSERT(faceRenderQueue.m_directionalLight.hasShadow());
  505. ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0]);
  506. const RenderQueue& cascadeRenderQueue = *faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0];
  507. const I32 faceDrawcallCount = I32(cascadeRenderQueue.m_renderables.getSize());
  508. const I32 localStart = max(I32(0), start - drawcallCount);
  509. const I32 localEnd = min(faceDrawcallCount, end - drawcallCount);
  510. if(localStart < localEnd)
  511. {
  512. const U32 rez = m_shadowMapping.m_rtDescr.m_height;
  513. cmdb->setViewport(rez * faceIdx, 0, rez, rez);
  514. cmdb->setScissor(rez * faceIdx, 0, rez, rez);
  515. ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
  516. m_r->getSceneDrawer().drawRange(
  517. RenderingTechnique::SHADOW, cascadeRenderQueue.m_viewMatrix, cascadeRenderQueue.m_viewProjectionMatrix,
  518. Mat4::getIdentity(), // Don't care about prev matrices here
  519. cmdb, m_r->getSamplers().m_trilinearRepeatAniso,
  520. cascadeRenderQueue.m_renderables.getBegin() + localStart,
  521. cascadeRenderQueue.m_renderables.getBegin() + localEnd, MAX_LOD_COUNT - 1, MAX_LOD_COUNT - 1);
  522. }
  523. }
  524. // It's secondary, no need to restore the state
  525. }
  526. void IndirectDiffuseProbes::runLightShading(RenderPassWorkContext& rgraphCtx, InternalContext& giCtx)
  527. {
  528. ANKI_TRACE_SCOPED_EVENT(R_GI);
  529. ANKI_ASSERT(giCtx.m_probeToUpdateThisFrame);
  530. const GlobalIlluminationProbeQueueElement& probe = *giCtx.m_probeToUpdateThisFrame;
  531. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  532. for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
  533. {
  534. ANKI_ASSERT(probe.m_renderQueues[faceIdx]);
  535. const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
  536. const U32 rez = m_tileSize;
  537. cmdb->setScissor(rez * faceIdx, 0, rez, rez);
  538. cmdb->setViewport(rez * faceIdx, 0, rez, rez);
  539. // Draw light shading
  540. TraditionalDeferredLightShadingDrawInfo dsInfo;
  541. dsInfo.m_viewProjectionMatrix = rqueue.m_viewProjectionMatrix;
  542. dsInfo.m_invViewProjectionMatrix = rqueue.m_viewProjectionMatrix.getInverse();
  543. dsInfo.m_cameraPosWSpace = rqueue.m_cameraTransform.getTranslationPart();
  544. dsInfo.m_viewport = UVec4(faceIdx * m_tileSize, 0, m_tileSize, m_tileSize);
  545. dsInfo.m_gbufferTexCoordsScale = Vec2(1.0f / F32(m_tileSize * 6), 1.0f / F32(m_tileSize));
  546. dsInfo.m_gbufferTexCoordsBias = Vec2(0.0f, 0.0f);
  547. dsInfo.m_lightbufferTexCoordsBias = Vec2(-F32(faceIdx), 0.0f);
  548. dsInfo.m_lightbufferTexCoordsScale = Vec2(1.0f / F32(m_tileSize), 1.0f / F32(m_tileSize));
  549. dsInfo.m_cameraNear = rqueue.m_cameraNear;
  550. dsInfo.m_cameraFar = rqueue.m_cameraFar;
  551. dsInfo.m_directionalLight = (rqueue.m_directionalLight.isEnabled()) ? &rqueue.m_directionalLight : nullptr;
  552. dsInfo.m_pointLights = rqueue.m_pointLights;
  553. dsInfo.m_spotLights = rqueue.m_spotLights;
  554. dsInfo.m_commandBuffer = cmdb;
  555. dsInfo.m_gbufferRenderTargets[0] = giCtx.m_gbufferColorRts[0];
  556. dsInfo.m_gbufferRenderTargets[1] = giCtx.m_gbufferColorRts[1];
  557. dsInfo.m_gbufferRenderTargets[2] = giCtx.m_gbufferColorRts[2];
  558. dsInfo.m_gbufferDepthRenderTarget = giCtx.m_gbufferDepthRt;
  559. if(dsInfo.m_directionalLight && dsInfo.m_directionalLight->hasShadow())
  560. {
  561. dsInfo.m_directionalLightShadowmapRenderTarget = giCtx.m_shadowsRt;
  562. }
  563. dsInfo.m_renderpassContext = &rgraphCtx;
  564. dsInfo.m_skybox = &giCtx.m_ctx->m_renderQueue->m_skybox;
  565. m_lightShading.m_deferred.drawLights(dsInfo);
  566. }
  567. }
  568. void IndirectDiffuseProbes::runIrradiance(RenderPassWorkContext& rgraphCtx, InternalContext& giCtx)
  569. {
  570. ANKI_TRACE_SCOPED_EVENT(R_GI);
  571. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  572. ANKI_ASSERT(giCtx.m_probeToUpdateThisFrame);
  573. const GlobalIlluminationProbeQueueElement& probe = *giCtx.m_probeToUpdateThisFrame;
  574. const U32 probeIdx = U32(&probe - &giCtx.m_ctx->m_renderQueue->m_giProbes.getFront());
  575. cmdb->bindShaderProgram(m_irradiance.m_grProg);
  576. // Bind resources
  577. cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);
  578. rgraphCtx.bindColorTexture(0, 1, giCtx.m_lightShadingRt);
  579. for(U32 i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT - 1; ++i)
  580. {
  581. rgraphCtx.bindColorTexture(0, 2, giCtx.m_gbufferColorRts[i], i);
  582. }
  583. rgraphCtx.bindImage(0, 3, giCtx.m_irradianceProbeRts[probeIdx], TextureSubresourceInfo());
  584. class
  585. {
  586. public:
  587. IVec3 m_volumeTexel;
  588. I32 m_nextTexelOffsetInU;
  589. } unis;
  590. unis.m_volumeTexel = IVec3(giCtx.m_cellOfTheProbeToUpdateThisFrame.x(), giCtx.m_cellOfTheProbeToUpdateThisFrame.y(),
  591. giCtx.m_cellOfTheProbeToUpdateThisFrame.z());
  592. unis.m_nextTexelOffsetInU = probe.m_cellCounts.x();
  593. cmdb->setPushConstants(&unis, sizeof(unis));
  594. // Dispatch
  595. cmdb->dispatchCompute(1, 1, 1);
  596. }
  597. } // end namespace anki