IndirectDiffuseProbes.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. // Copyright (C) 2009-2023, 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. class IndirectDiffuseProbes::InternalContext
  14. {
  15. public:
  16. IndirectDiffuseProbes* m_gi = nullptr;
  17. RenderingContext* m_ctx = nullptr;
  18. GlobalIlluminationProbeQueueElementForRefresh* m_probeToUpdateThisFrame = nullptr;
  19. Array<RenderTargetHandle, kGBufferColorRenderTargetCount> m_gbufferColorRts;
  20. RenderTargetHandle m_gbufferDepthRt;
  21. RenderTargetHandle m_shadowsRt;
  22. RenderTargetHandle m_lightShadingRt;
  23. RenderTargetHandle m_irradianceVolume;
  24. U32 m_gbufferDrawcallCount = kMaxU32;
  25. U32 m_smDrawcallCount = kMaxU32;
  26. static void foo()
  27. {
  28. static_assert(std::is_trivially_destructible<InternalContext>::value, "See file");
  29. }
  30. };
  31. IndirectDiffuseProbes::~IndirectDiffuseProbes()
  32. {
  33. }
  34. RenderTargetHandle IndirectDiffuseProbes::getCurrentlyRefreshedVolumeRt() const
  35. {
  36. ANKI_ASSERT(m_giCtx && m_giCtx->m_irradianceVolume.isValid());
  37. return m_giCtx->m_irradianceVolume;
  38. }
  39. Bool IndirectDiffuseProbes::hasCurrentlyRefreshedVolumeRt() const
  40. {
  41. return m_giCtx != nullptr;
  42. }
  43. Error IndirectDiffuseProbes::init()
  44. {
  45. const Error err = initInternal();
  46. if(err)
  47. {
  48. ANKI_R_LOGE("Failed to initialize global illumination");
  49. }
  50. return err;
  51. }
  52. Error IndirectDiffuseProbes::initInternal()
  53. {
  54. m_tileSize = ConfigSet::getSingleton().getRIndirectDiffuseProbeTileResolution();
  55. ANKI_CHECK(initGBuffer());
  56. ANKI_CHECK(initLightShading());
  57. ANKI_CHECK(initShadowMapping());
  58. ANKI_CHECK(initIrradiance());
  59. return Error::kNone;
  60. }
  61. Error IndirectDiffuseProbes::initGBuffer()
  62. {
  63. // Create RT descriptions
  64. {
  65. RenderTargetDescription texinit = m_r->create2DRenderTargetDescription(
  66. m_tileSize * 6, m_tileSize, kGBufferColorRenderTargetFormats[0], "GI GBuffer");
  67. // Create color RT descriptions
  68. for(U32 i = 0; i < kGBufferColorRenderTargetCount; ++i)
  69. {
  70. texinit.m_format = kGBufferColorRenderTargetFormats[i];
  71. m_gbuffer.m_colorRtDescrs[i] = texinit;
  72. m_gbuffer.m_colorRtDescrs[i].setName(
  73. StringRaii(&getMemoryPool()).sprintf("GI GBuff Col #%u", i).toCString());
  74. m_gbuffer.m_colorRtDescrs[i].bake();
  75. }
  76. // Create depth RT
  77. texinit.m_format = m_r->getDepthNoStencilFormat();
  78. texinit.setName("GI GBuff Depth");
  79. m_gbuffer.m_depthRtDescr = texinit;
  80. m_gbuffer.m_depthRtDescr.bake();
  81. }
  82. // Create FB descr
  83. {
  84. m_gbuffer.m_fbDescr.m_colorAttachmentCount = kGBufferColorRenderTargetCount;
  85. for(U j = 0; j < kGBufferColorRenderTargetCount; ++j)
  86. {
  87. m_gbuffer.m_fbDescr.m_colorAttachments[j].m_loadOperation = AttachmentLoadOperation::kClear;
  88. }
  89. m_gbuffer.m_fbDescr.m_depthStencilAttachment.m_aspect = DepthStencilAspectBit::kDepth;
  90. m_gbuffer.m_fbDescr.m_depthStencilAttachment.m_loadOperation = AttachmentLoadOperation::kClear;
  91. m_gbuffer.m_fbDescr.m_depthStencilAttachment.m_clearValue.m_depthStencil.m_depth = 1.0f;
  92. m_gbuffer.m_fbDescr.bake();
  93. }
  94. return Error::kNone;
  95. }
  96. Error IndirectDiffuseProbes::initShadowMapping()
  97. {
  98. const U32 resolution = ConfigSet::getSingleton().getRIndirectDiffuseProbeShadowMapResolution();
  99. ANKI_ASSERT(resolution > 8);
  100. // RT descr
  101. m_shadowMapping.m_rtDescr =
  102. m_r->create2DRenderTargetDescription(resolution * 6, resolution, m_r->getDepthNoStencilFormat(), "GI SM");
  103. m_shadowMapping.m_rtDescr.bake();
  104. // FB descr
  105. m_shadowMapping.m_fbDescr.m_colorAttachmentCount = 0;
  106. m_shadowMapping.m_fbDescr.m_depthStencilAttachment.m_aspect = DepthStencilAspectBit::kDepth;
  107. m_shadowMapping.m_fbDescr.m_depthStencilAttachment.m_clearValue.m_depthStencil.m_depth = 1.0f;
  108. m_shadowMapping.m_fbDescr.m_depthStencilAttachment.m_loadOperation = AttachmentLoadOperation::kClear;
  109. m_shadowMapping.m_fbDescr.bake();
  110. return Error::kNone;
  111. }
  112. Error IndirectDiffuseProbes::initLightShading()
  113. {
  114. // Init RT descr
  115. {
  116. m_lightShading.m_rtDescr =
  117. m_r->create2DRenderTargetDescription(m_tileSize * 6, m_tileSize, m_r->getHdrFormat(), "GI LS");
  118. m_lightShading.m_rtDescr.bake();
  119. }
  120. // Create FB descr
  121. {
  122. m_lightShading.m_fbDescr.m_colorAttachmentCount = 1;
  123. m_lightShading.m_fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::kClear;
  124. m_lightShading.m_fbDescr.bake();
  125. }
  126. // Init deferred
  127. ANKI_CHECK(m_lightShading.m_deferred.init());
  128. return Error::kNone;
  129. }
  130. Error IndirectDiffuseProbes::initIrradiance()
  131. {
  132. ANKI_CHECK(
  133. ResourceManager::getSingleton().loadResource("ShaderBinaries/IrradianceDice.ankiprogbin", m_irradiance.m_prog));
  134. ShaderProgramResourceVariantInitInfo variantInitInfo(m_irradiance.m_prog);
  135. variantInitInfo.addMutation("WORKGROUP_SIZE_XY", m_tileSize);
  136. variantInitInfo.addMutation("LIGHT_SHADING_TEX", 0);
  137. variantInitInfo.addMutation("STORE_LOCATION", 0);
  138. variantInitInfo.addMutation("SECOND_BOUNCE", 1);
  139. const ShaderProgramResourceVariant* variant;
  140. m_irradiance.m_prog->getOrCreateVariant(variantInitInfo, variant);
  141. m_irradiance.m_grProg = variant->getProgram();
  142. return Error::kNone;
  143. }
  144. void IndirectDiffuseProbes::populateRenderGraph(RenderingContext& rctx)
  145. {
  146. ANKI_TRACE_SCOPED_EVENT(RIndirectDiffuse);
  147. if(rctx.m_renderQueue->m_giProbeForRefresh == nullptr) [[likely]]
  148. {
  149. m_giCtx = nullptr;
  150. return;
  151. }
  152. InternalContext* giCtx = newInstance<InternalContext>(*rctx.m_tempPool);
  153. m_giCtx = giCtx;
  154. giCtx->m_gi = this;
  155. giCtx->m_ctx = &rctx;
  156. giCtx->m_probeToUpdateThisFrame = rctx.m_renderQueue->m_giProbeForRefresh;
  157. RenderGraphDescription& rgraph = rctx.m_renderGraphDescr;
  158. // Compute task counts for some of the passes
  159. U32 gbufferTaskCount, smTaskCount;
  160. {
  161. giCtx->m_gbufferDrawcallCount = 0;
  162. giCtx->m_smDrawcallCount = 0;
  163. for(const RenderQueue* rq : giCtx->m_probeToUpdateThisFrame->m_renderQueues)
  164. {
  165. ANKI_ASSERT(rq);
  166. giCtx->m_gbufferDrawcallCount += rq->m_renderables.getSize();
  167. if(rq->m_directionalLight.hasShadow())
  168. {
  169. giCtx->m_smDrawcallCount += rq->m_directionalLight.m_shadowRenderQueues[0]->m_renderables.getSize();
  170. }
  171. }
  172. gbufferTaskCount = computeNumberOfSecondLevelCommandBuffers(giCtx->m_gbufferDrawcallCount);
  173. smTaskCount = computeNumberOfSecondLevelCommandBuffers(giCtx->m_smDrawcallCount);
  174. }
  175. // GBuffer
  176. {
  177. // RTs
  178. for(U i = 0; i < kGBufferColorRenderTargetCount; ++i)
  179. {
  180. giCtx->m_gbufferColorRts[i] = rgraph.newRenderTarget(m_gbuffer.m_colorRtDescrs[i]);
  181. }
  182. giCtx->m_gbufferDepthRt = rgraph.newRenderTarget(m_gbuffer.m_depthRtDescr);
  183. // Pass
  184. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("GI gbuff");
  185. pass.setFramebufferInfo(m_gbuffer.m_fbDescr, giCtx->m_gbufferColorRts, giCtx->m_gbufferDepthRt);
  186. pass.setWork(gbufferTaskCount, [this, giCtx](RenderPassWorkContext& rgraphCtx) {
  187. runGBufferInThread(rgraphCtx, *giCtx);
  188. });
  189. for(U i = 0; i < kGBufferColorRenderTargetCount; ++i)
  190. {
  191. pass.newTextureDependency(giCtx->m_gbufferColorRts[i], TextureUsageBit::kFramebufferWrite);
  192. }
  193. TextureSubresourceInfo subresource(DepthStencilAspectBit::kDepth);
  194. pass.newTextureDependency(giCtx->m_gbufferDepthRt, TextureUsageBit::kAllFramebuffer, subresource);
  195. pass.newBufferDependency(m_r->getGpuSceneBufferHandle(),
  196. BufferUsageBit::kStorageGeometryRead | BufferUsageBit::kStorageFragmentRead);
  197. }
  198. // Shadow pass. Optional
  199. if(giCtx->m_probeToUpdateThisFrame->m_renderQueues[0]->m_directionalLight.m_uuid
  200. && giCtx->m_probeToUpdateThisFrame->m_renderQueues[0]->m_directionalLight.m_shadowCascadeCount > 0)
  201. {
  202. // Update light matrices
  203. for(U i = 0; i < 6; ++i)
  204. {
  205. ANKI_ASSERT(giCtx->m_probeToUpdateThisFrame->m_renderQueues[i]->m_directionalLight.m_uuid
  206. && giCtx->m_probeToUpdateThisFrame->m_renderQueues[i]->m_directionalLight.m_shadowCascadeCount
  207. == 1);
  208. const F32 xScale = 1.0f / 6.0f;
  209. const F32 yScale = 1.0f;
  210. const F32 xOffset = F32(i) * (1.0f / 6.0f);
  211. const F32 yOffset = 0.0f;
  212. 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,
  213. 0.0f, 0.0f, 1.0f);
  214. Mat4& lightMat =
  215. giCtx->m_probeToUpdateThisFrame->m_renderQueues[i]->m_directionalLight.m_textureMatrices[0];
  216. lightMat = atlasMtx * lightMat;
  217. }
  218. // RT
  219. giCtx->m_shadowsRt = rgraph.newRenderTarget(m_shadowMapping.m_rtDescr);
  220. // Pass
  221. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("GI SM");
  222. pass.setFramebufferInfo(m_shadowMapping.m_fbDescr, {}, giCtx->m_shadowsRt);
  223. pass.setWork(smTaskCount, [this, giCtx](RenderPassWorkContext& rgraphCtx) {
  224. runShadowmappingInThread(rgraphCtx, *giCtx);
  225. });
  226. TextureSubresourceInfo subresource(DepthStencilAspectBit::kDepth);
  227. pass.newTextureDependency(giCtx->m_shadowsRt, TextureUsageBit::kAllFramebuffer, subresource);
  228. pass.newBufferDependency(m_r->getGpuSceneBufferHandle(),
  229. BufferUsageBit::kStorageGeometryRead | BufferUsageBit::kStorageFragmentRead);
  230. }
  231. else
  232. {
  233. giCtx->m_shadowsRt = {};
  234. }
  235. // Light shading pass
  236. {
  237. // RT
  238. giCtx->m_lightShadingRt = rgraph.newRenderTarget(m_lightShading.m_rtDescr);
  239. // Pass
  240. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("GI LS");
  241. pass.setFramebufferInfo(m_lightShading.m_fbDescr, {giCtx->m_lightShadingRt});
  242. pass.setWork(1, [this, giCtx](RenderPassWorkContext& rgraphCtx) {
  243. runLightShading(rgraphCtx, *giCtx);
  244. });
  245. pass.newTextureDependency(giCtx->m_lightShadingRt, TextureUsageBit::kFramebufferWrite);
  246. for(U i = 0; i < kGBufferColorRenderTargetCount; ++i)
  247. {
  248. pass.newTextureDependency(giCtx->m_gbufferColorRts[i], TextureUsageBit::kSampledFragment);
  249. }
  250. pass.newTextureDependency(giCtx->m_gbufferDepthRt, TextureUsageBit::kSampledFragment,
  251. TextureSubresourceInfo(DepthStencilAspectBit::kDepth));
  252. if(giCtx->m_shadowsRt.isValid())
  253. {
  254. pass.newTextureDependency(giCtx->m_shadowsRt, TextureUsageBit::kSampledFragment);
  255. }
  256. }
  257. // Irradiance pass. First & 2nd bounce
  258. {
  259. m_giCtx->m_irradianceVolume = rgraph.importRenderTarget(
  260. TexturePtr(m_giCtx->m_probeToUpdateThisFrame->m_volumeTexture), TextureUsageBit::kNone);
  261. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("GI IR");
  262. pass.setWork([this, giCtx](RenderPassWorkContext& rgraphCtx) {
  263. runIrradiance(rgraphCtx, *giCtx);
  264. });
  265. pass.newTextureDependency(giCtx->m_lightShadingRt, TextureUsageBit::kSampledCompute);
  266. for(U32 i = 0; i < kGBufferColorRenderTargetCount - 1; ++i)
  267. {
  268. pass.newTextureDependency(giCtx->m_gbufferColorRts[i], TextureUsageBit::kSampledCompute);
  269. }
  270. pass.newTextureDependency(m_giCtx->m_irradianceVolume, TextureUsageBit::kImageComputeWrite);
  271. }
  272. }
  273. void IndirectDiffuseProbes::runGBufferInThread(RenderPassWorkContext& rgraphCtx, InternalContext& giCtx) const
  274. {
  275. ANKI_ASSERT(giCtx.m_probeToUpdateThisFrame);
  276. ANKI_TRACE_SCOPED_EVENT(RIndirectDiffuse);
  277. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  278. const GlobalIlluminationProbeQueueElementForRefresh& probe = *giCtx.m_probeToUpdateThisFrame;
  279. I32 start, end;
  280. U32 startu, endu;
  281. splitThreadedProblem(rgraphCtx.m_currentSecondLevelCommandBufferIndex, rgraphCtx.m_secondLevelCommandBufferCount,
  282. giCtx.m_gbufferDrawcallCount, startu, endu);
  283. start = I32(startu);
  284. end = I32(endu);
  285. I32 drawcallCount = 0;
  286. for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
  287. {
  288. const I32 faceDrawcallCount = I32(probe.m_renderQueues[faceIdx]->m_renderables.getSize());
  289. const I32 localStart = max(I32(0), start - drawcallCount);
  290. const I32 localEnd = min(faceDrawcallCount, end - drawcallCount);
  291. if(localStart < localEnd)
  292. {
  293. const U32 viewportX = faceIdx * m_tileSize;
  294. cmdb->setViewport(viewportX, 0, m_tileSize, m_tileSize);
  295. cmdb->setScissor(viewportX, 0, m_tileSize, m_tileSize);
  296. const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
  297. ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
  298. RenderableDrawerArguments args;
  299. args.m_viewMatrix = rqueue.m_viewMatrix;
  300. args.m_cameraTransform = Mat3x4::getIdentity(); // Don't care
  301. args.m_viewProjectionMatrix = rqueue.m_viewProjectionMatrix;
  302. args.m_previousViewProjectionMatrix = Mat4::getIdentity(); // Don't care
  303. args.m_sampler = m_r->getSamplers().m_trilinearRepeat;
  304. m_r->getSceneDrawer().drawRange(args, rqueue.m_renderables.getBegin() + localStart,
  305. rqueue.m_renderables.getBegin() + localEnd, cmdb);
  306. }
  307. drawcallCount += faceDrawcallCount;
  308. }
  309. ANKI_ASSERT(giCtx.m_gbufferDrawcallCount == U32(drawcallCount));
  310. // It's secondary, no need to restore the state
  311. }
  312. void IndirectDiffuseProbes::runShadowmappingInThread(RenderPassWorkContext& rgraphCtx, InternalContext& giCtx) const
  313. {
  314. ANKI_ASSERT(giCtx.m_probeToUpdateThisFrame);
  315. ANKI_TRACE_SCOPED_EVENT(RIndirectDiffuse);
  316. const GlobalIlluminationProbeQueueElementForRefresh& probe = *giCtx.m_probeToUpdateThisFrame;
  317. I32 start, end;
  318. U32 startu, endu;
  319. splitThreadedProblem(rgraphCtx.m_currentSecondLevelCommandBufferIndex, rgraphCtx.m_secondLevelCommandBufferCount,
  320. giCtx.m_smDrawcallCount, startu, endu);
  321. start = I32(startu);
  322. end = I32(endu);
  323. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  324. cmdb->setPolygonOffset(kShadowsPolygonOffsetFactor, kShadowsPolygonOffsetUnits);
  325. I32 drawcallCount = 0;
  326. for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
  327. {
  328. ANKI_ASSERT(probe.m_renderQueues[faceIdx]);
  329. const RenderQueue& faceRenderQueue = *probe.m_renderQueues[faceIdx];
  330. ANKI_ASSERT(faceRenderQueue.m_directionalLight.hasShadow());
  331. ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0]);
  332. const RenderQueue& cascadeRenderQueue = *faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0];
  333. const I32 faceDrawcallCount = I32(cascadeRenderQueue.m_renderables.getSize());
  334. const I32 localStart = max(I32(0), start - drawcallCount);
  335. const I32 localEnd = min(faceDrawcallCount, end - drawcallCount);
  336. if(localStart < localEnd)
  337. {
  338. const U32 rez = m_shadowMapping.m_rtDescr.m_height;
  339. cmdb->setViewport(rez * faceIdx, 0, rez, rez);
  340. cmdb->setScissor(rez * faceIdx, 0, rez, rez);
  341. ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
  342. RenderableDrawerArguments args;
  343. args.m_viewMatrix = cascadeRenderQueue.m_viewMatrix;
  344. args.m_cameraTransform = Mat3x4::getIdentity(); // Don't care
  345. args.m_viewProjectionMatrix = cascadeRenderQueue.m_viewProjectionMatrix;
  346. args.m_previousViewProjectionMatrix = Mat4::getIdentity(); // Don't care
  347. args.m_sampler = m_r->getSamplers().m_trilinearRepeatAniso;
  348. m_r->getSceneDrawer().drawRange(args, cascadeRenderQueue.m_renderables.getBegin() + localStart,
  349. cascadeRenderQueue.m_renderables.getBegin() + localEnd, cmdb);
  350. }
  351. }
  352. // It's secondary, no need to restore the state
  353. }
  354. void IndirectDiffuseProbes::runLightShading(RenderPassWorkContext& rgraphCtx, InternalContext& giCtx)
  355. {
  356. ANKI_TRACE_SCOPED_EVENT(RIndirectDiffuse);
  357. ANKI_ASSERT(giCtx.m_probeToUpdateThisFrame);
  358. const GlobalIlluminationProbeQueueElementForRefresh& probe = *giCtx.m_probeToUpdateThisFrame;
  359. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  360. for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
  361. {
  362. ANKI_ASSERT(probe.m_renderQueues[faceIdx]);
  363. const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
  364. const U32 rez = m_tileSize;
  365. cmdb->setScissor(rez * faceIdx, 0, rez, rez);
  366. cmdb->setViewport(rez * faceIdx, 0, rez, rez);
  367. // Draw light shading
  368. TraditionalDeferredLightShadingDrawInfo dsInfo;
  369. dsInfo.m_viewProjectionMatrix = rqueue.m_viewProjectionMatrix;
  370. dsInfo.m_invViewProjectionMatrix = rqueue.m_viewProjectionMatrix.getInverse();
  371. dsInfo.m_cameraPosWSpace = rqueue.m_cameraTransform.getTranslationPart().xyz1();
  372. dsInfo.m_viewport = UVec4(faceIdx * m_tileSize, 0, m_tileSize, m_tileSize);
  373. dsInfo.m_gbufferTexCoordsScale = Vec2(1.0f / F32(m_tileSize * 6), 1.0f / F32(m_tileSize));
  374. dsInfo.m_gbufferTexCoordsBias = Vec2(0.0f, 0.0f);
  375. dsInfo.m_lightbufferTexCoordsBias = Vec2(-F32(faceIdx), 0.0f);
  376. dsInfo.m_lightbufferTexCoordsScale = Vec2(1.0f / F32(m_tileSize), 1.0f / F32(m_tileSize));
  377. dsInfo.m_cameraNear = rqueue.m_cameraNear;
  378. dsInfo.m_cameraFar = rqueue.m_cameraFar;
  379. dsInfo.m_directionalLight = (rqueue.m_directionalLight.isEnabled()) ? &rqueue.m_directionalLight : nullptr;
  380. dsInfo.m_pointLights = rqueue.m_pointLights;
  381. dsInfo.m_spotLights = rqueue.m_spotLights;
  382. dsInfo.m_commandBuffer = cmdb;
  383. dsInfo.m_gbufferRenderTargets[0] = giCtx.m_gbufferColorRts[0];
  384. dsInfo.m_gbufferRenderTargets[1] = giCtx.m_gbufferColorRts[1];
  385. dsInfo.m_gbufferRenderTargets[2] = giCtx.m_gbufferColorRts[2];
  386. dsInfo.m_gbufferDepthRenderTarget = giCtx.m_gbufferDepthRt;
  387. if(dsInfo.m_directionalLight && dsInfo.m_directionalLight->hasShadow())
  388. {
  389. dsInfo.m_directionalLightShadowmapRenderTarget = giCtx.m_shadowsRt;
  390. }
  391. dsInfo.m_renderpassContext = &rgraphCtx;
  392. dsInfo.m_skybox = &giCtx.m_ctx->m_renderQueue->m_skybox;
  393. m_lightShading.m_deferred.drawLights(dsInfo);
  394. }
  395. }
  396. void IndirectDiffuseProbes::runIrradiance(RenderPassWorkContext& rgraphCtx, InternalContext& giCtx)
  397. {
  398. ANKI_TRACE_SCOPED_EVENT(RIndirectDiffuse);
  399. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  400. ANKI_ASSERT(giCtx.m_probeToUpdateThisFrame);
  401. const GlobalIlluminationProbeQueueElementForRefresh& probe = *giCtx.m_probeToUpdateThisFrame;
  402. cmdb->bindShaderProgram(m_irradiance.m_grProg);
  403. // Bind resources
  404. cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);
  405. rgraphCtx.bindColorTexture(0, 1, giCtx.m_lightShadingRt);
  406. for(U32 i = 0; i < kGBufferColorRenderTargetCount - 1; ++i)
  407. {
  408. rgraphCtx.bindColorTexture(0, 2, giCtx.m_gbufferColorRts[i], i);
  409. }
  410. rgraphCtx.bindImage(0, 3, giCtx.m_irradianceVolume, TextureSubresourceInfo());
  411. class
  412. {
  413. public:
  414. IVec3 m_volumeTexel;
  415. I32 m_nextTexelOffsetInU;
  416. } unis;
  417. unis.m_volumeTexel = IVec3(probe.m_cellToRefresh.x(), probe.m_cellToRefresh.y(), probe.m_cellToRefresh.z());
  418. unis.m_nextTexelOffsetInU = probe.m_cellCounts.x();
  419. cmdb->setPushConstants(&unis, sizeof(unis));
  420. // Dispatch
  421. cmdb->dispatchCompute(1, 1, 1);
  422. }
  423. } // end namespace anki