GlobalIllumination.cpp 27 KB

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