ProbeReflections.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  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/ProbeReflections.h>
  6. #include <AnKi/Renderer/LightShading.h>
  7. #include <AnKi/Renderer/FinalComposite.h>
  8. #include <AnKi/Renderer/GBuffer.h>
  9. #include <AnKi/Renderer/RenderQueue.h>
  10. #include <AnKi/Core/ConfigSet.h>
  11. #include <AnKi/Util/Tracer.h>
  12. #include <AnKi/Resource/MeshResource.h>
  13. #include <AnKi/Shaders/Include/TraditionalDeferredShadingTypes.h>
  14. namespace anki {
  15. ProbeReflections::ProbeReflections(Renderer* r)
  16. : RendererObject(r)
  17. , m_lightShading(r)
  18. {
  19. }
  20. ProbeReflections::~ProbeReflections()
  21. {
  22. m_cacheEntries.destroy(getAllocator());
  23. m_probeUuidToCacheEntryIdx.destroy(getAllocator());
  24. }
  25. Error ProbeReflections::init()
  26. {
  27. const Error err = initInternal();
  28. if(err)
  29. {
  30. ANKI_R_LOGE("Failed to initialize image reflections");
  31. }
  32. return err;
  33. }
  34. Error ProbeReflections::initInternal()
  35. {
  36. // Init cache entries
  37. m_cacheEntries.create(getAllocator(), getConfig().getRProbeRefectionMaxCachedProbes());
  38. ANKI_CHECK(initGBuffer());
  39. ANKI_CHECK(initLightShading());
  40. ANKI_CHECK(initIrradiance());
  41. ANKI_CHECK(initIrradianceToRefl());
  42. ANKI_CHECK(initShadowMapping());
  43. // Load split sum integration LUT
  44. ANKI_CHECK(getResourceManager().loadResource("EngineAssets/IblDfg.png", m_integrationLut));
  45. SamplerInitInfo sinit;
  46. sinit.m_minMagFilter = SamplingFilter::LINEAR;
  47. sinit.m_mipmapFilter = SamplingFilter::BASE;
  48. sinit.m_minLod = 0.0;
  49. sinit.m_maxLod = 1.0;
  50. sinit.m_addressing = SamplingAddressing::CLAMP;
  51. m_integrationLutSampler = getGrManager().newSampler(sinit);
  52. return Error::NONE;
  53. }
  54. Error ProbeReflections::initGBuffer()
  55. {
  56. m_gbuffer.m_tileSize = getConfig().getRProbeReflectionResolution();
  57. // Create RT descriptions
  58. {
  59. RenderTargetDescription texinit =
  60. m_r->create2DRenderTargetDescription(m_gbuffer.m_tileSize * 6, m_gbuffer.m_tileSize,
  61. GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[0], "CubeRefl GBuffer");
  62. // Create color RT descriptions
  63. for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
  64. {
  65. texinit.m_format = GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[i];
  66. m_gbuffer.m_colorRtDescrs[i] = texinit;
  67. m_gbuffer.m_colorRtDescrs[i].setName(
  68. StringAuto(getAllocator()).sprintf("CubeRefl GBuff Col #%u", i).toCString());
  69. m_gbuffer.m_colorRtDescrs[i].bake();
  70. }
  71. // Create depth RT
  72. texinit.m_format = m_r->getDepthNoStencilFormat();
  73. texinit.setName("CubeRefl GBuff Depth");
  74. m_gbuffer.m_depthRtDescr = texinit;
  75. m_gbuffer.m_depthRtDescr.bake();
  76. }
  77. // Create FB descr
  78. {
  79. m_gbuffer.m_fbDescr.m_colorAttachmentCount = GBUFFER_COLOR_ATTACHMENT_COUNT;
  80. for(U j = 0; j < GBUFFER_COLOR_ATTACHMENT_COUNT; ++j)
  81. {
  82. m_gbuffer.m_fbDescr.m_colorAttachments[j].m_loadOperation = AttachmentLoadOperation::CLEAR;
  83. }
  84. m_gbuffer.m_fbDescr.m_depthStencilAttachment.m_aspect = DepthStencilAspectBit::DEPTH;
  85. m_gbuffer.m_fbDescr.m_depthStencilAttachment.m_loadOperation = AttachmentLoadOperation::CLEAR;
  86. m_gbuffer.m_fbDescr.m_depthStencilAttachment.m_clearValue.m_depthStencil.m_depth = 1.0f;
  87. m_gbuffer.m_fbDescr.bake();
  88. }
  89. return Error::NONE;
  90. }
  91. Error ProbeReflections::initLightShading()
  92. {
  93. m_lightShading.m_tileSize = getConfig().getRProbeReflectionResolution();
  94. m_lightShading.m_mipCount = computeMaxMipmapCount2d(m_lightShading.m_tileSize, m_lightShading.m_tileSize, 8);
  95. // Init cube arr
  96. {
  97. TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(
  98. m_lightShading.m_tileSize, m_lightShading.m_tileSize, m_r->getHdrFormat(),
  99. TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_COMPUTE | TextureUsageBit::IMAGE_COMPUTE_READ
  100. | TextureUsageBit::IMAGE_COMPUTE_WRITE | TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT
  101. | TextureUsageBit::GENERATE_MIPMAPS,
  102. "CubeRefl refl");
  103. texinit.m_mipmapCount = U8(m_lightShading.m_mipCount);
  104. texinit.m_type = TextureType::CUBE_ARRAY;
  105. texinit.m_layerCount = m_cacheEntries.getSize();
  106. m_lightShading.m_cubeArr = m_r->createAndClearRenderTarget(texinit, TextureUsageBit::SAMPLED_FRAGMENT);
  107. }
  108. // Init deferred
  109. ANKI_CHECK(m_lightShading.m_deferred.init());
  110. return Error::NONE;
  111. }
  112. Error ProbeReflections::initIrradiance()
  113. {
  114. m_irradiance.m_workgroupSize = getConfig().getRProbeReflectionIrradianceResolution();
  115. // Create prog
  116. {
  117. ANKI_CHECK(
  118. m_r->getResourceManager().loadResource("ShaderBinaries/IrradianceDice.ankiprogbin", m_irradiance.m_prog));
  119. ShaderProgramResourceVariantInitInfo variantInitInfo(m_irradiance.m_prog);
  120. variantInitInfo.addMutation("WORKGROUP_SIZE_XY", U32(m_irradiance.m_workgroupSize));
  121. variantInitInfo.addMutation("LIGHT_SHADING_TEX", 1);
  122. variantInitInfo.addMutation("STORE_LOCATION", 1);
  123. variantInitInfo.addMutation("SECOND_BOUNCE", 0);
  124. const ShaderProgramResourceVariant* variant;
  125. m_irradiance.m_prog->getOrCreateVariant(variantInitInfo, variant);
  126. m_irradiance.m_grProg = variant->getProgram();
  127. }
  128. // Create buff
  129. {
  130. BufferInitInfo init;
  131. init.m_usage = BufferUsageBit::ALL_STORAGE;
  132. init.m_size = 6 * sizeof(Vec4);
  133. m_irradiance.m_diceValuesBuff = getGrManager().newBuffer(init);
  134. }
  135. return Error::NONE;
  136. }
  137. Error ProbeReflections::initIrradianceToRefl()
  138. {
  139. // Create program
  140. ANKI_CHECK(m_r->getResourceManager().loadResource("ShaderBinaries/ApplyIrradianceToReflection.ankiprogbin",
  141. m_irradianceToRefl.m_prog));
  142. const ShaderProgramResourceVariant* variant;
  143. m_irradianceToRefl.m_prog->getOrCreateVariant(ShaderProgramResourceVariantInitInfo(m_irradianceToRefl.m_prog),
  144. variant);
  145. m_irradianceToRefl.m_grProg = variant->getProgram();
  146. return Error::NONE;
  147. }
  148. Error ProbeReflections::initShadowMapping()
  149. {
  150. const U32 resolution = getConfig().getRProbeReflectionShadowMapResolution();
  151. ANKI_ASSERT(resolution > 8);
  152. // RT descr
  153. m_shadowMapping.m_rtDescr =
  154. m_r->create2DRenderTargetDescription(resolution * 6, resolution, m_r->getDepthNoStencilFormat(), "CubeRefl SM");
  155. m_shadowMapping.m_rtDescr.bake();
  156. // FB descr
  157. m_shadowMapping.m_fbDescr.m_colorAttachmentCount = 0;
  158. m_shadowMapping.m_fbDescr.m_depthStencilAttachment.m_aspect = DepthStencilAspectBit::DEPTH;
  159. m_shadowMapping.m_fbDescr.m_depthStencilAttachment.m_clearValue.m_depthStencil.m_depth = 1.0f;
  160. m_shadowMapping.m_fbDescr.m_depthStencilAttachment.m_loadOperation = AttachmentLoadOperation::CLEAR;
  161. m_shadowMapping.m_fbDescr.bake();
  162. return Error::NONE;
  163. }
  164. void ProbeReflections::initCacheEntry(U32 cacheEntryIdx)
  165. {
  166. CacheEntry& cacheEntry = m_cacheEntries[cacheEntryIdx];
  167. for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
  168. {
  169. // Light pass FB
  170. FramebufferDescription& fbDescr = cacheEntry.m_lightShadingFbDescrs[faceIdx];
  171. ANKI_ASSERT(!fbDescr.isBacked());
  172. fbDescr.m_colorAttachmentCount = 1;
  173. fbDescr.m_colorAttachments[0].m_surface.m_layer = cacheEntryIdx;
  174. fbDescr.m_colorAttachments[0].m_surface.m_face = faceIdx;
  175. fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::CLEAR;
  176. fbDescr.bake();
  177. }
  178. }
  179. void ProbeReflections::prepareProbes(RenderingContext& ctx, ReflectionProbeQueueElement*& probeToUpdateThisFrame,
  180. U32& probeToUpdateThisFrameCacheEntryIdx)
  181. {
  182. probeToUpdateThisFrame = nullptr;
  183. probeToUpdateThisFrameCacheEntryIdx = MAX_U32;
  184. if(ANKI_UNLIKELY(ctx.m_renderQueue->m_reflectionProbes.getSize() == 0))
  185. {
  186. return;
  187. }
  188. // Iterate the probes and:
  189. // - Find a probe to update this frame
  190. // - Find a probe to update next frame
  191. // - Find the cache entries for each probe
  192. DynamicArray<ReflectionProbeQueueElement> newListOfProbes;
  193. newListOfProbes.create(ctx.m_tempAllocator, ctx.m_renderQueue->m_reflectionProbes.getSize());
  194. U32 newListOfProbeCount = 0;
  195. Bool foundProbeToUpdateNextFrame = false;
  196. for(U32 probeIdx = 0; probeIdx < ctx.m_renderQueue->m_reflectionProbes.getSize(); ++probeIdx)
  197. {
  198. ReflectionProbeQueueElement& probe = ctx.m_renderQueue->m_reflectionProbes[probeIdx];
  199. // Find cache entry
  200. const U32 cacheEntryIdx = findBestCacheEntry(probe.m_uuid, m_r->getGlobalTimestamp(), m_cacheEntries,
  201. m_probeUuidToCacheEntryIdx, getAllocator());
  202. if(ANKI_UNLIKELY(cacheEntryIdx == MAX_U32))
  203. {
  204. // Failed
  205. ANKI_R_LOGW("There is not enough space in the indirect lighting atlas for more probes. "
  206. "Increase the r_probeRefectionlMaxSimultaneousProbeCount or decrease the scene's probes");
  207. continue;
  208. }
  209. const Bool probeFoundInCache = m_cacheEntries[cacheEntryIdx].m_uuid == probe.m_uuid;
  210. // Check if we _should_ and _can_ update the probe
  211. const Bool needsUpdate = !probeFoundInCache;
  212. if(ANKI_UNLIKELY(needsUpdate))
  213. {
  214. const Bool canUpdateThisFrame = probeToUpdateThisFrame == nullptr && probe.m_renderQueues[0] != nullptr;
  215. const Bool canUpdateNextFrame = !foundProbeToUpdateNextFrame;
  216. if(!canUpdateThisFrame && canUpdateNextFrame)
  217. {
  218. // Probe will be updated next frame
  219. foundProbeToUpdateNextFrame = true;
  220. probe.m_feedbackCallback(true, probe.m_feedbackCallbackUserData);
  221. continue;
  222. }
  223. else if(!canUpdateThisFrame)
  224. {
  225. // Can't be updated this frame so remove it from the list
  226. continue;
  227. }
  228. else
  229. {
  230. // Can be updated this frame so continue with it
  231. probeToUpdateThisFrameCacheEntryIdx = cacheEntryIdx;
  232. probeToUpdateThisFrame = &newListOfProbes[newListOfProbeCount];
  233. }
  234. }
  235. // All good, can use this probe in this frame
  236. // Update the cache entry
  237. m_cacheEntries[cacheEntryIdx].m_uuid = probe.m_uuid;
  238. m_cacheEntries[cacheEntryIdx].m_lastUsedTimestamp = m_r->getGlobalTimestamp();
  239. // Update the probe
  240. probe.m_textureArrayIndex = cacheEntryIdx;
  241. // Push the probe to the new list
  242. newListOfProbes[newListOfProbeCount++] = probe;
  243. // Update cache map
  244. if(!probeFoundInCache)
  245. {
  246. m_probeUuidToCacheEntryIdx.emplace(getAllocator(), probe.m_uuid, cacheEntryIdx);
  247. }
  248. // Don't gather renderables next frame
  249. if(probe.m_renderQueues[0] != nullptr)
  250. {
  251. probe.m_feedbackCallback(false, probe.m_feedbackCallbackUserData);
  252. }
  253. }
  254. // Replace the probe list in the queue
  255. if(newListOfProbeCount > 0)
  256. {
  257. ReflectionProbeQueueElement* firstProbe;
  258. U32 probeCount, storage;
  259. newListOfProbes.moveAndReset(firstProbe, probeCount, storage);
  260. ctx.m_renderQueue->m_reflectionProbes = WeakArray<ReflectionProbeQueueElement>(firstProbe, newListOfProbeCount);
  261. }
  262. else
  263. {
  264. ctx.m_renderQueue->m_reflectionProbes = WeakArray<ReflectionProbeQueueElement>();
  265. newListOfProbes.destroy(ctx.m_tempAllocator);
  266. }
  267. }
  268. void ProbeReflections::runGBuffer(RenderPassWorkContext& rgraphCtx)
  269. {
  270. ANKI_ASSERT(m_ctx.m_probe);
  271. ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
  272. const ReflectionProbeQueueElement& probe = *m_ctx.m_probe;
  273. const CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  274. I32 start, end;
  275. U32 startu, endu;
  276. splitThreadedProblem(rgraphCtx.m_currentSecondLevelCommandBufferIndex, rgraphCtx.m_secondLevelCommandBufferCount,
  277. m_ctx.m_gbufferRenderableCount, startu, endu);
  278. start = I32(startu);
  279. end = I32(endu);
  280. I32 drawcallCount = 0;
  281. for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
  282. {
  283. const I32 faceDrawcallCount = I32(probe.m_renderQueues[faceIdx]->m_renderables.getSize());
  284. const I32 localStart = max(I32(0), start - drawcallCount);
  285. const I32 localEnd = min(faceDrawcallCount, end - drawcallCount);
  286. if(localStart < localEnd)
  287. {
  288. const U32 viewportX = faceIdx * m_gbuffer.m_tileSize;
  289. cmdb->setViewport(viewportX, 0, m_gbuffer.m_tileSize, m_gbuffer.m_tileSize);
  290. cmdb->setScissor(viewportX, 0, m_gbuffer.m_tileSize, m_gbuffer.m_tileSize);
  291. const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
  292. ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
  293. m_r->getSceneDrawer().drawRange(
  294. RenderingTechnique::GBUFFER, rqueue.m_viewMatrix, rqueue.m_viewProjectionMatrix,
  295. Mat4::getIdentity(), // Don't care about prev mats
  296. cmdb, m_r->getSamplers().m_trilinearRepeat, rqueue.m_renderables.getBegin() + localStart,
  297. rqueue.m_renderables.getBegin() + localEnd, MAX_LOD_COUNT - 1, MAX_LOD_COUNT - 1);
  298. }
  299. }
  300. // Restore state
  301. cmdb->setScissor(0, 0, MAX_U32, MAX_U32);
  302. }
  303. void ProbeReflections::runLightShading(U32 faceIdx, const RenderingContext& rctx, RenderPassWorkContext& rgraphCtx)
  304. {
  305. ANKI_ASSERT(faceIdx <= 6);
  306. ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
  307. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  308. ANKI_ASSERT(m_ctx.m_probe);
  309. const ReflectionProbeQueueElement& probe = *m_ctx.m_probe;
  310. const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
  311. const Bool hasDirLight = probe.m_renderQueues[0]->m_directionalLight.m_uuid;
  312. TraditionalDeferredLightShadingDrawInfo dsInfo;
  313. dsInfo.m_viewProjectionMatrix = rqueue.m_viewProjectionMatrix;
  314. dsInfo.m_invViewProjectionMatrix = rqueue.m_viewProjectionMatrix.getInverse();
  315. dsInfo.m_cameraPosWSpace = rqueue.m_cameraTransform.getTranslationPart();
  316. dsInfo.m_viewport = UVec4(0, 0, m_lightShading.m_tileSize, m_lightShading.m_tileSize);
  317. dsInfo.m_gbufferTexCoordsScale =
  318. Vec2(1.0f / F32(m_lightShading.m_tileSize * 6), 1.0f / F32(m_lightShading.m_tileSize));
  319. dsInfo.m_gbufferTexCoordsBias = Vec2(F32(faceIdx) * (1.0f / 6.0f), 0.0f);
  320. dsInfo.m_lightbufferTexCoordsScale =
  321. Vec2(1.0f / F32(m_lightShading.m_tileSize), 1.0f / F32(m_lightShading.m_tileSize));
  322. dsInfo.m_lightbufferTexCoordsBias = Vec2(0.0f, 0.0f);
  323. dsInfo.m_cameraNear = probe.m_renderQueues[faceIdx]->m_cameraNear;
  324. dsInfo.m_cameraFar = probe.m_renderQueues[faceIdx]->m_cameraFar;
  325. dsInfo.m_directionalLight = (hasDirLight) ? &probe.m_renderQueues[faceIdx]->m_directionalLight : nullptr;
  326. dsInfo.m_pointLights = rqueue.m_pointLights;
  327. dsInfo.m_spotLights = rqueue.m_spotLights;
  328. dsInfo.m_commandBuffer = cmdb;
  329. dsInfo.m_gbufferRenderTargets[0] = m_ctx.m_gbufferColorRts[0];
  330. dsInfo.m_gbufferRenderTargets[1] = m_ctx.m_gbufferColorRts[1];
  331. dsInfo.m_gbufferRenderTargets[2] = m_ctx.m_gbufferColorRts[2];
  332. dsInfo.m_gbufferDepthRenderTarget = m_ctx.m_gbufferDepthRt;
  333. if(hasDirLight && dsInfo.m_directionalLight->hasShadow())
  334. {
  335. dsInfo.m_directionalLightShadowmapRenderTarget = m_ctx.m_shadowMapRt;
  336. }
  337. dsInfo.m_renderpassContext = &rgraphCtx;
  338. dsInfo.m_skybox = &rctx.m_renderQueue->m_skybox;
  339. m_lightShading.m_deferred.drawLights(dsInfo);
  340. }
  341. void ProbeReflections::runMipmappingOfLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
  342. {
  343. ANKI_ASSERT(faceIdx < 6);
  344. ANKI_ASSERT(m_ctx.m_cacheEntryIdx < m_cacheEntries.getSize());
  345. ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
  346. TextureSubresourceInfo subresource(TextureSurfaceInfo(0, 0, faceIdx, m_ctx.m_cacheEntryIdx));
  347. subresource.m_mipmapCount = m_lightShading.m_mipCount;
  348. TexturePtr texToBind;
  349. rgraphCtx.getRenderTargetState(m_ctx.m_lightShadingRt, subresource, texToBind);
  350. TextureViewInitInfo viewInit(texToBind, subresource);
  351. rgraphCtx.m_commandBuffer->generateMipmaps2d(getGrManager().newTextureView(viewInit));
  352. }
  353. void ProbeReflections::runIrradiance(RenderPassWorkContext& rgraphCtx)
  354. {
  355. ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
  356. const U32 cacheEntryIdx = m_ctx.m_cacheEntryIdx;
  357. ANKI_ASSERT(cacheEntryIdx < m_cacheEntries.getSize());
  358. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  359. cmdb->bindShaderProgram(m_irradiance.m_grProg);
  360. // Bind stuff
  361. cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);
  362. TextureSubresourceInfo subresource;
  363. subresource.m_faceCount = 6;
  364. subresource.m_firstLayer = cacheEntryIdx;
  365. rgraphCtx.bindTexture(0, 1, m_ctx.m_lightShadingRt, subresource);
  366. cmdb->bindStorageBuffer(0, 3, m_irradiance.m_diceValuesBuff, 0, m_irradiance.m_diceValuesBuff->getSize());
  367. // Draw
  368. cmdb->dispatchCompute(1, 1, 1);
  369. }
  370. void ProbeReflections::runIrradianceToRefl(RenderPassWorkContext& rgraphCtx)
  371. {
  372. ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
  373. const U32 cacheEntryIdx = m_ctx.m_cacheEntryIdx;
  374. ANKI_ASSERT(cacheEntryIdx < m_cacheEntries.getSize());
  375. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  376. cmdb->bindShaderProgram(m_irradianceToRefl.m_grProg);
  377. // Bind resources
  378. cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);
  379. rgraphCtx.bindColorTexture(0, 1, m_ctx.m_gbufferColorRts[0], 0);
  380. rgraphCtx.bindColorTexture(0, 1, m_ctx.m_gbufferColorRts[1], 1);
  381. rgraphCtx.bindColorTexture(0, 1, m_ctx.m_gbufferColorRts[2], 2);
  382. cmdb->bindStorageBuffer(0, 2, m_irradiance.m_diceValuesBuff, 0, m_irradiance.m_diceValuesBuff->getSize());
  383. TextureSubresourceInfo subresource;
  384. subresource.m_faceCount = 6;
  385. subresource.m_firstLayer = cacheEntryIdx;
  386. rgraphCtx.bindImage(0, 3, m_ctx.m_lightShadingRt, subresource);
  387. dispatchPPCompute(cmdb, 8, 8, m_lightShading.m_tileSize, m_lightShading.m_tileSize);
  388. }
  389. void ProbeReflections::populateRenderGraph(RenderingContext& rctx)
  390. {
  391. ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
  392. #if ANKI_EXTRA_CHECKS
  393. m_ctx = {};
  394. #endif
  395. RenderGraphDescription& rgraph = rctx.m_renderGraphDescr;
  396. // Prepare the probes and maybe get one to render this frame
  397. ReflectionProbeQueueElement* probeToUpdate;
  398. U32 probeToUpdateCacheEntryIdx;
  399. prepareProbes(rctx, probeToUpdate, probeToUpdateCacheEntryIdx);
  400. // Render a probe if needed
  401. if(!probeToUpdate)
  402. {
  403. // Just import and exit
  404. m_ctx.m_lightShadingRt = rgraph.importRenderTarget(m_lightShading.m_cubeArr, TextureUsageBit::SAMPLED_FRAGMENT);
  405. return;
  406. }
  407. m_ctx.m_cacheEntryIdx = probeToUpdateCacheEntryIdx;
  408. m_ctx.m_probe = probeToUpdate;
  409. if(!m_cacheEntries[probeToUpdateCacheEntryIdx].m_lightShadingFbDescrs[0].isBacked())
  410. {
  411. initCacheEntry(probeToUpdateCacheEntryIdx);
  412. }
  413. // G-buffer pass
  414. {
  415. // RTs
  416. Array<RenderTargetHandle, MAX_COLOR_ATTACHMENTS> rts;
  417. for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
  418. {
  419. m_ctx.m_gbufferColorRts[i] = rgraph.newRenderTarget(m_gbuffer.m_colorRtDescrs[i]);
  420. rts[i] = m_ctx.m_gbufferColorRts[i];
  421. }
  422. m_ctx.m_gbufferDepthRt = rgraph.newRenderTarget(m_gbuffer.m_depthRtDescr);
  423. // Compute task count
  424. m_ctx.m_gbufferRenderableCount = 0;
  425. for(U32 i = 0; i < 6; ++i)
  426. {
  427. m_ctx.m_gbufferRenderableCount += probeToUpdate->m_renderQueues[i]->m_renderables.getSize();
  428. }
  429. const U32 taskCount = computeNumberOfSecondLevelCommandBuffers(m_ctx.m_gbufferRenderableCount);
  430. // Pass
  431. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("CubeRefl gbuff");
  432. pass.setFramebufferInfo(m_gbuffer.m_fbDescr, rts, m_ctx.m_gbufferDepthRt);
  433. pass.setWork(taskCount, [this](RenderPassWorkContext& rgraphCtx) {
  434. runGBuffer(rgraphCtx);
  435. });
  436. for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
  437. {
  438. pass.newDependency({m_ctx.m_gbufferColorRts[i], TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  439. }
  440. TextureSubresourceInfo subresource(DepthStencilAspectBit::DEPTH);
  441. pass.newDependency({m_ctx.m_gbufferDepthRt, TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT, subresource});
  442. }
  443. // Shadow pass. Optional
  444. if(probeToUpdate->m_renderQueues[0]->m_directionalLight.m_uuid
  445. && probeToUpdate->m_renderQueues[0]->m_directionalLight.m_shadowCascadeCount > 0)
  446. {
  447. // Update light matrices
  448. for(U i = 0; i < 6; ++i)
  449. {
  450. ANKI_ASSERT(probeToUpdate->m_renderQueues[i]->m_directionalLight.m_uuid
  451. && probeToUpdate->m_renderQueues[i]->m_directionalLight.m_shadowCascadeCount == 1);
  452. const F32 xScale = 1.0f / 6.0f;
  453. const F32 yScale = 1.0f;
  454. const F32 xOffset = F32(i) * (1.0f / 6.0f);
  455. const F32 yOffset = 0.0f;
  456. 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,
  457. 0.0f, 0.0f, 1.0f);
  458. Mat4& lightMat = probeToUpdate->m_renderQueues[i]->m_directionalLight.m_textureMatrices[0];
  459. lightMat = atlasMtx * lightMat;
  460. }
  461. // Compute task count
  462. m_ctx.m_shadowRenderableCount = 0;
  463. for(U32 i = 0; i < 6; ++i)
  464. {
  465. m_ctx.m_shadowRenderableCount +=
  466. probeToUpdate->m_renderQueues[i]->m_directionalLight.m_shadowRenderQueues[0]->m_renderables.getSize();
  467. }
  468. const U32 taskCount = computeNumberOfSecondLevelCommandBuffers(m_ctx.m_shadowRenderableCount);
  469. // RT
  470. m_ctx.m_shadowMapRt = rgraph.newRenderTarget(m_shadowMapping.m_rtDescr);
  471. // Pass
  472. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("CubeRefl SM");
  473. pass.setFramebufferInfo(m_shadowMapping.m_fbDescr, {}, m_ctx.m_shadowMapRt);
  474. pass.setWork(taskCount, [this](RenderPassWorkContext& rgraphCtx) {
  475. runShadowMapping(rgraphCtx);
  476. });
  477. TextureSubresourceInfo subresource(DepthStencilAspectBit::DEPTH);
  478. pass.newDependency({m_ctx.m_shadowMapRt, TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT, subresource});
  479. }
  480. else
  481. {
  482. m_ctx.m_shadowMapRt = {};
  483. }
  484. // Light shading passes
  485. {
  486. // RT
  487. m_ctx.m_lightShadingRt = rgraph.importRenderTarget(m_lightShading.m_cubeArr, TextureUsageBit::SAMPLED_FRAGMENT);
  488. // Passes
  489. static const Array<CString, 6> passNames = {"CubeRefl LightShad #0", "CubeRefl LightShad #1",
  490. "CubeRefl LightShad #2", "CubeRefl LightShad #3",
  491. "CubeRefl LightShad #4", "CubeRefl LightShad #5"};
  492. for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
  493. {
  494. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass(passNames[faceIdx]);
  495. pass.setFramebufferInfo(m_cacheEntries[probeToUpdateCacheEntryIdx].m_lightShadingFbDescrs[faceIdx],
  496. {m_ctx.m_lightShadingRt});
  497. pass.setWork([this, faceIdx, &rctx](RenderPassWorkContext& rgraphCtx) {
  498. runLightShading(faceIdx, rctx, rgraphCtx);
  499. });
  500. TextureSubresourceInfo subresource(TextureSurfaceInfo(0, 0, faceIdx, probeToUpdateCacheEntryIdx));
  501. pass.newDependency({m_ctx.m_lightShadingRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, subresource});
  502. for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
  503. {
  504. pass.newDependency({m_ctx.m_gbufferColorRts[i], TextureUsageBit::SAMPLED_FRAGMENT});
  505. }
  506. pass.newDependency({m_ctx.m_gbufferDepthRt, TextureUsageBit::SAMPLED_FRAGMENT,
  507. TextureSubresourceInfo(DepthStencilAspectBit::DEPTH)});
  508. if(m_ctx.m_shadowMapRt.isValid())
  509. {
  510. pass.newDependency({m_ctx.m_shadowMapRt, TextureUsageBit::SAMPLED_FRAGMENT});
  511. }
  512. }
  513. }
  514. // Irradiance passes
  515. {
  516. m_ctx.m_irradianceDiceValuesBuffHandle =
  517. rgraph.importBuffer(m_irradiance.m_diceValuesBuff, BufferUsageBit::NONE);
  518. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("CubeRefl Irradiance");
  519. pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
  520. runIrradiance(rgraphCtx);
  521. });
  522. // Read a cube but only one layer and level
  523. TextureSubresourceInfo readSubresource;
  524. readSubresource.m_faceCount = 6;
  525. readSubresource.m_firstLayer = probeToUpdateCacheEntryIdx;
  526. pass.newDependency({m_ctx.m_lightShadingRt, TextureUsageBit::SAMPLED_COMPUTE, readSubresource});
  527. pass.newDependency({m_ctx.m_irradianceDiceValuesBuffHandle, BufferUsageBit::STORAGE_COMPUTE_WRITE});
  528. }
  529. // Write irradiance back to refl
  530. {
  531. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("CubeRefl apply indirect");
  532. pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
  533. runIrradianceToRefl(rgraphCtx);
  534. });
  535. for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT - 1; ++i)
  536. {
  537. pass.newDependency({m_ctx.m_gbufferColorRts[i], TextureUsageBit::SAMPLED_COMPUTE});
  538. }
  539. TextureSubresourceInfo subresource;
  540. subresource.m_faceCount = 6;
  541. subresource.m_firstLayer = probeToUpdateCacheEntryIdx;
  542. pass.newDependency({m_ctx.m_lightShadingRt,
  543. TextureUsageBit::IMAGE_COMPUTE_READ | TextureUsageBit::IMAGE_COMPUTE_WRITE, subresource});
  544. pass.newDependency({m_ctx.m_irradianceDiceValuesBuffHandle, BufferUsageBit::STORAGE_COMPUTE_READ});
  545. }
  546. // Mipmapping "passes"
  547. {
  548. static const Array<CString, 6> passNames = {"CubeRefl Mip #0", "CubeRefl Mip #1", "CubeRefl Mip #2",
  549. "CubeRefl Mip #3", "CubeRefl Mip #4", "CubeRefl Mip #5"};
  550. for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
  551. {
  552. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass(passNames[faceIdx]);
  553. pass.setWork([this, faceIdx](RenderPassWorkContext& rgraphCtx) {
  554. runMipmappingOfLightShading(faceIdx, rgraphCtx);
  555. });
  556. TextureSubresourceInfo subresource(TextureSurfaceInfo(0, 0, faceIdx, probeToUpdateCacheEntryIdx));
  557. subresource.m_mipmapCount = m_lightShading.m_mipCount;
  558. pass.newDependency({m_ctx.m_lightShadingRt, TextureUsageBit::GENERATE_MIPMAPS, subresource});
  559. }
  560. }
  561. }
  562. void ProbeReflections::runShadowMapping(RenderPassWorkContext& rgraphCtx)
  563. {
  564. ANKI_ASSERT(m_ctx.m_probe);
  565. ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
  566. I32 start, end;
  567. U32 startu, endu;
  568. splitThreadedProblem(rgraphCtx.m_currentSecondLevelCommandBufferIndex, rgraphCtx.m_secondLevelCommandBufferCount,
  569. m_ctx.m_shadowRenderableCount, startu, endu);
  570. start = I32(startu);
  571. end = I32(endu);
  572. const CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  573. cmdb->setPolygonOffset(1.0f, 1.0f);
  574. I32 drawcallCount = 0;
  575. for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
  576. {
  577. ANKI_ASSERT(m_ctx.m_probe->m_renderQueues[faceIdx]);
  578. const RenderQueue& faceRenderQueue = *m_ctx.m_probe->m_renderQueues[faceIdx];
  579. ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_uuid != 0);
  580. ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_shadowCascadeCount == 1);
  581. ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0]);
  582. const RenderQueue& cascadeRenderQueue = *faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0];
  583. const I32 faceDrawcallCount = I32(cascadeRenderQueue.m_renderables.getSize());
  584. const I32 localStart = max(I32(0), start - drawcallCount);
  585. const I32 localEnd = min(faceDrawcallCount, end - drawcallCount);
  586. if(localStart < localEnd)
  587. {
  588. const U32 rez = m_shadowMapping.m_rtDescr.m_height;
  589. cmdb->setViewport(rez * faceIdx, 0, rez, rez);
  590. cmdb->setScissor(rez * faceIdx, 0, rez, rez);
  591. ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
  592. m_r->getSceneDrawer().drawRange(
  593. RenderingTechnique::SHADOW, cascadeRenderQueue.m_viewMatrix, cascadeRenderQueue.m_viewProjectionMatrix,
  594. Mat4::getIdentity(), // Don't care about prev matrices here
  595. cmdb, m_r->getSamplers().m_trilinearRepeatAniso,
  596. cascadeRenderQueue.m_renderables.getBegin() + localStart,
  597. cascadeRenderQueue.m_renderables.getBegin() + localEnd, MAX_LOD_COUNT - 1, MAX_LOD_COUNT - 1);
  598. }
  599. }
  600. }
  601. } // end namespace anki