2
0

ProbeReflections.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  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(U32 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. 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. RenderableDrawerArguments args;
  294. args.m_viewMatrix = rqueue.m_viewMatrix;
  295. args.m_cameraTransform = rqueue.m_cameraTransform;
  296. args.m_viewProjectionMatrix = rqueue.m_viewProjectionMatrix;
  297. args.m_previousViewProjectionMatrix = Mat4::getIdentity(); // Don't care about prev mats
  298. args.m_sampler = m_r->getSamplers().m_trilinearRepeat;
  299. args.m_minLod = args.m_maxLod = MAX_LOD_COUNT - 1;
  300. m_r->getSceneDrawer().drawRange(RenderingTechnique::GBUFFER, args,
  301. rqueue.m_renderables.getBegin() + localStart,
  302. rqueue.m_renderables.getBegin() + localEnd, cmdb);
  303. }
  304. }
  305. // Restore state
  306. cmdb->setScissor(0, 0, MAX_U32, MAX_U32);
  307. }
  308. void ProbeReflections::runLightShading(U32 faceIdx, const RenderingContext& rctx, RenderPassWorkContext& rgraphCtx)
  309. {
  310. ANKI_ASSERT(faceIdx <= 6);
  311. ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
  312. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  313. ANKI_ASSERT(m_ctx.m_probe);
  314. const ReflectionProbeQueueElement& probe = *m_ctx.m_probe;
  315. const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
  316. const Bool hasDirLight = probe.m_renderQueues[0]->m_directionalLight.m_uuid;
  317. TraditionalDeferredLightShadingDrawInfo dsInfo;
  318. dsInfo.m_viewProjectionMatrix = rqueue.m_viewProjectionMatrix;
  319. dsInfo.m_invViewProjectionMatrix = rqueue.m_viewProjectionMatrix.getInverse();
  320. dsInfo.m_cameraPosWSpace = rqueue.m_cameraTransform.getTranslationPart().xyz1();
  321. dsInfo.m_viewport = UVec4(0, 0, m_lightShading.m_tileSize, m_lightShading.m_tileSize);
  322. dsInfo.m_gbufferTexCoordsScale =
  323. Vec2(1.0f / F32(m_lightShading.m_tileSize * 6), 1.0f / F32(m_lightShading.m_tileSize));
  324. dsInfo.m_gbufferTexCoordsBias = Vec2(F32(faceIdx) * (1.0f / 6.0f), 0.0f);
  325. dsInfo.m_lightbufferTexCoordsScale =
  326. Vec2(1.0f / F32(m_lightShading.m_tileSize), 1.0f / F32(m_lightShading.m_tileSize));
  327. dsInfo.m_lightbufferTexCoordsBias = Vec2(0.0f, 0.0f);
  328. dsInfo.m_cameraNear = probe.m_renderQueues[faceIdx]->m_cameraNear;
  329. dsInfo.m_cameraFar = probe.m_renderQueues[faceIdx]->m_cameraFar;
  330. dsInfo.m_directionalLight = (hasDirLight) ? &probe.m_renderQueues[faceIdx]->m_directionalLight : nullptr;
  331. dsInfo.m_pointLights = rqueue.m_pointLights;
  332. dsInfo.m_spotLights = rqueue.m_spotLights;
  333. dsInfo.m_commandBuffer = cmdb;
  334. dsInfo.m_gbufferRenderTargets[0] = m_ctx.m_gbufferColorRts[0];
  335. dsInfo.m_gbufferRenderTargets[1] = m_ctx.m_gbufferColorRts[1];
  336. dsInfo.m_gbufferRenderTargets[2] = m_ctx.m_gbufferColorRts[2];
  337. dsInfo.m_gbufferDepthRenderTarget = m_ctx.m_gbufferDepthRt;
  338. if(hasDirLight && dsInfo.m_directionalLight->hasShadow())
  339. {
  340. dsInfo.m_directionalLightShadowmapRenderTarget = m_ctx.m_shadowMapRt;
  341. }
  342. dsInfo.m_renderpassContext = &rgraphCtx;
  343. dsInfo.m_skybox = &rctx.m_renderQueue->m_skybox;
  344. m_lightShading.m_deferred.drawLights(dsInfo);
  345. }
  346. void ProbeReflections::runMipmappingOfLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
  347. {
  348. ANKI_ASSERT(faceIdx < 6);
  349. ANKI_ASSERT(m_ctx.m_cacheEntryIdx < m_cacheEntries.getSize());
  350. ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
  351. TextureSubresourceInfo subresource(TextureSurfaceInfo(0, 0, faceIdx, m_ctx.m_cacheEntryIdx));
  352. subresource.m_mipmapCount = m_lightShading.m_mipCount;
  353. TexturePtr texToBind;
  354. rgraphCtx.getRenderTargetState(m_ctx.m_lightShadingRt, subresource, texToBind);
  355. TextureViewInitInfo viewInit(texToBind, subresource);
  356. rgraphCtx.m_commandBuffer->generateMipmaps2d(getGrManager().newTextureView(viewInit));
  357. }
  358. void ProbeReflections::runIrradiance(RenderPassWorkContext& rgraphCtx)
  359. {
  360. ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
  361. const U32 cacheEntryIdx = m_ctx.m_cacheEntryIdx;
  362. ANKI_ASSERT(cacheEntryIdx < m_cacheEntries.getSize());
  363. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  364. cmdb->bindShaderProgram(m_irradiance.m_grProg);
  365. // Bind stuff
  366. cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);
  367. TextureSubresourceInfo subresource;
  368. subresource.m_faceCount = 6;
  369. subresource.m_firstLayer = cacheEntryIdx;
  370. rgraphCtx.bindTexture(0, 1, m_ctx.m_lightShadingRt, subresource);
  371. cmdb->bindStorageBuffer(0, 3, m_irradiance.m_diceValuesBuff, 0, m_irradiance.m_diceValuesBuff->getSize());
  372. // Draw
  373. cmdb->dispatchCompute(1, 1, 1);
  374. }
  375. void ProbeReflections::runIrradianceToRefl(RenderPassWorkContext& rgraphCtx)
  376. {
  377. ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
  378. const U32 cacheEntryIdx = m_ctx.m_cacheEntryIdx;
  379. ANKI_ASSERT(cacheEntryIdx < m_cacheEntries.getSize());
  380. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  381. cmdb->bindShaderProgram(m_irradianceToRefl.m_grProg);
  382. // Bind resources
  383. cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);
  384. rgraphCtx.bindColorTexture(0, 1, m_ctx.m_gbufferColorRts[0], 0);
  385. rgraphCtx.bindColorTexture(0, 1, m_ctx.m_gbufferColorRts[1], 1);
  386. rgraphCtx.bindColorTexture(0, 1, m_ctx.m_gbufferColorRts[2], 2);
  387. cmdb->bindStorageBuffer(0, 2, m_irradiance.m_diceValuesBuff, 0, m_irradiance.m_diceValuesBuff->getSize());
  388. TextureSubresourceInfo subresource;
  389. subresource.m_faceCount = 6;
  390. subresource.m_firstLayer = cacheEntryIdx;
  391. rgraphCtx.bindImage(0, 3, m_ctx.m_lightShadingRt, subresource);
  392. dispatchPPCompute(cmdb, 8, 8, m_lightShading.m_tileSize, m_lightShading.m_tileSize);
  393. }
  394. void ProbeReflections::populateRenderGraph(RenderingContext& rctx)
  395. {
  396. ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
  397. #if ANKI_EXTRA_CHECKS
  398. m_ctx = {};
  399. #endif
  400. RenderGraphDescription& rgraph = rctx.m_renderGraphDescr;
  401. // Prepare the probes and maybe get one to render this frame
  402. ReflectionProbeQueueElement* probeToUpdate;
  403. U32 probeToUpdateCacheEntryIdx;
  404. prepareProbes(rctx, probeToUpdate, probeToUpdateCacheEntryIdx);
  405. // Render a probe if needed
  406. if(!probeToUpdate)
  407. {
  408. // Just import and exit
  409. m_ctx.m_lightShadingRt = rgraph.importRenderTarget(m_lightShading.m_cubeArr, TextureUsageBit::SAMPLED_FRAGMENT);
  410. return;
  411. }
  412. m_ctx.m_cacheEntryIdx = probeToUpdateCacheEntryIdx;
  413. m_ctx.m_probe = probeToUpdate;
  414. if(!m_cacheEntries[probeToUpdateCacheEntryIdx].m_lightShadingFbDescrs[0].isBacked())
  415. {
  416. initCacheEntry(probeToUpdateCacheEntryIdx);
  417. }
  418. // G-buffer pass
  419. {
  420. // RTs
  421. Array<RenderTargetHandle, MAX_COLOR_ATTACHMENTS> rts;
  422. for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
  423. {
  424. m_ctx.m_gbufferColorRts[i] = rgraph.newRenderTarget(m_gbuffer.m_colorRtDescrs[i]);
  425. rts[i] = m_ctx.m_gbufferColorRts[i];
  426. }
  427. m_ctx.m_gbufferDepthRt = rgraph.newRenderTarget(m_gbuffer.m_depthRtDescr);
  428. // Compute task count
  429. m_ctx.m_gbufferRenderableCount = 0;
  430. for(U32 i = 0; i < 6; ++i)
  431. {
  432. m_ctx.m_gbufferRenderableCount += probeToUpdate->m_renderQueues[i]->m_renderables.getSize();
  433. }
  434. const U32 taskCount = computeNumberOfSecondLevelCommandBuffers(m_ctx.m_gbufferRenderableCount);
  435. // Pass
  436. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("CubeRefl gbuff");
  437. pass.setFramebufferInfo(m_gbuffer.m_fbDescr, rts, m_ctx.m_gbufferDepthRt);
  438. pass.setWork(taskCount, [this](RenderPassWorkContext& rgraphCtx) {
  439. runGBuffer(rgraphCtx);
  440. });
  441. for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
  442. {
  443. pass.newDependency({m_ctx.m_gbufferColorRts[i], TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
  444. }
  445. TextureSubresourceInfo subresource(DepthStencilAspectBit::DEPTH);
  446. pass.newDependency({m_ctx.m_gbufferDepthRt, TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT, subresource});
  447. }
  448. // Shadow pass. Optional
  449. if(probeToUpdate->m_renderQueues[0]->m_directionalLight.m_uuid
  450. && probeToUpdate->m_renderQueues[0]->m_directionalLight.m_shadowCascadeCount > 0)
  451. {
  452. // Update light matrices
  453. for(U i = 0; i < 6; ++i)
  454. {
  455. ANKI_ASSERT(probeToUpdate->m_renderQueues[i]->m_directionalLight.m_uuid
  456. && probeToUpdate->m_renderQueues[i]->m_directionalLight.m_shadowCascadeCount == 1);
  457. const F32 xScale = 1.0f / 6.0f;
  458. const F32 yScale = 1.0f;
  459. const F32 xOffset = F32(i) * (1.0f / 6.0f);
  460. const F32 yOffset = 0.0f;
  461. 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,
  462. 0.0f, 0.0f, 1.0f);
  463. Mat4& lightMat = probeToUpdate->m_renderQueues[i]->m_directionalLight.m_textureMatrices[0];
  464. lightMat = atlasMtx * lightMat;
  465. }
  466. // Compute task count
  467. m_ctx.m_shadowRenderableCount = 0;
  468. for(U32 i = 0; i < 6; ++i)
  469. {
  470. m_ctx.m_shadowRenderableCount +=
  471. probeToUpdate->m_renderQueues[i]->m_directionalLight.m_shadowRenderQueues[0]->m_renderables.getSize();
  472. }
  473. const U32 taskCount = computeNumberOfSecondLevelCommandBuffers(m_ctx.m_shadowRenderableCount);
  474. // RT
  475. m_ctx.m_shadowMapRt = rgraph.newRenderTarget(m_shadowMapping.m_rtDescr);
  476. // Pass
  477. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("CubeRefl SM");
  478. pass.setFramebufferInfo(m_shadowMapping.m_fbDescr, {}, m_ctx.m_shadowMapRt);
  479. pass.setWork(taskCount, [this](RenderPassWorkContext& rgraphCtx) {
  480. runShadowMapping(rgraphCtx);
  481. });
  482. TextureSubresourceInfo subresource(DepthStencilAspectBit::DEPTH);
  483. pass.newDependency({m_ctx.m_shadowMapRt, TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT, subresource});
  484. }
  485. else
  486. {
  487. m_ctx.m_shadowMapRt = {};
  488. }
  489. // Light shading passes
  490. {
  491. // RT
  492. m_ctx.m_lightShadingRt = rgraph.importRenderTarget(m_lightShading.m_cubeArr, TextureUsageBit::SAMPLED_FRAGMENT);
  493. // Passes
  494. static const Array<CString, 6> passNames = {"CubeRefl LightShad #0", "CubeRefl LightShad #1",
  495. "CubeRefl LightShad #2", "CubeRefl LightShad #3",
  496. "CubeRefl LightShad #4", "CubeRefl LightShad #5"};
  497. for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
  498. {
  499. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass(passNames[faceIdx]);
  500. pass.setFramebufferInfo(m_cacheEntries[probeToUpdateCacheEntryIdx].m_lightShadingFbDescrs[faceIdx],
  501. {m_ctx.m_lightShadingRt});
  502. pass.setWork([this, faceIdx, &rctx](RenderPassWorkContext& rgraphCtx) {
  503. runLightShading(faceIdx, rctx, rgraphCtx);
  504. });
  505. TextureSubresourceInfo subresource(TextureSurfaceInfo(0, 0, faceIdx, probeToUpdateCacheEntryIdx));
  506. pass.newDependency({m_ctx.m_lightShadingRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, subresource});
  507. for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
  508. {
  509. pass.newDependency({m_ctx.m_gbufferColorRts[i], TextureUsageBit::SAMPLED_FRAGMENT});
  510. }
  511. pass.newDependency({m_ctx.m_gbufferDepthRt, TextureUsageBit::SAMPLED_FRAGMENT,
  512. TextureSubresourceInfo(DepthStencilAspectBit::DEPTH)});
  513. if(m_ctx.m_shadowMapRt.isValid())
  514. {
  515. pass.newDependency({m_ctx.m_shadowMapRt, TextureUsageBit::SAMPLED_FRAGMENT});
  516. }
  517. }
  518. }
  519. // Irradiance passes
  520. {
  521. m_ctx.m_irradianceDiceValuesBuffHandle =
  522. rgraph.importBuffer(m_irradiance.m_diceValuesBuff, BufferUsageBit::NONE);
  523. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("CubeRefl Irradiance");
  524. pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
  525. runIrradiance(rgraphCtx);
  526. });
  527. // Read a cube but only one layer and level
  528. TextureSubresourceInfo readSubresource;
  529. readSubresource.m_faceCount = 6;
  530. readSubresource.m_firstLayer = probeToUpdateCacheEntryIdx;
  531. pass.newDependency({m_ctx.m_lightShadingRt, TextureUsageBit::SAMPLED_COMPUTE, readSubresource});
  532. pass.newDependency({m_ctx.m_irradianceDiceValuesBuffHandle, BufferUsageBit::STORAGE_COMPUTE_WRITE});
  533. }
  534. // Write irradiance back to refl
  535. {
  536. ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("CubeRefl apply indirect");
  537. pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
  538. runIrradianceToRefl(rgraphCtx);
  539. });
  540. for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT - 1; ++i)
  541. {
  542. pass.newDependency({m_ctx.m_gbufferColorRts[i], TextureUsageBit::SAMPLED_COMPUTE});
  543. }
  544. TextureSubresourceInfo subresource;
  545. subresource.m_faceCount = 6;
  546. subresource.m_firstLayer = probeToUpdateCacheEntryIdx;
  547. pass.newDependency({m_ctx.m_lightShadingRt,
  548. TextureUsageBit::IMAGE_COMPUTE_READ | TextureUsageBit::IMAGE_COMPUTE_WRITE, subresource});
  549. pass.newDependency({m_ctx.m_irradianceDiceValuesBuffHandle, BufferUsageBit::STORAGE_COMPUTE_READ});
  550. }
  551. // Mipmapping "passes"
  552. {
  553. static const Array<CString, 6> passNames = {"CubeRefl Mip #0", "CubeRefl Mip #1", "CubeRefl Mip #2",
  554. "CubeRefl Mip #3", "CubeRefl Mip #4", "CubeRefl Mip #5"};
  555. for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
  556. {
  557. GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass(passNames[faceIdx]);
  558. pass.setWork([this, faceIdx](RenderPassWorkContext& rgraphCtx) {
  559. runMipmappingOfLightShading(faceIdx, rgraphCtx);
  560. });
  561. TextureSubresourceInfo subresource(TextureSurfaceInfo(0, 0, faceIdx, probeToUpdateCacheEntryIdx));
  562. subresource.m_mipmapCount = m_lightShading.m_mipCount;
  563. pass.newDependency({m_ctx.m_lightShadingRt, TextureUsageBit::GENERATE_MIPMAPS, subresource});
  564. }
  565. }
  566. }
  567. void ProbeReflections::runShadowMapping(RenderPassWorkContext& rgraphCtx)
  568. {
  569. ANKI_ASSERT(m_ctx.m_probe);
  570. ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
  571. I32 start, end;
  572. U32 startu, endu;
  573. splitThreadedProblem(rgraphCtx.m_currentSecondLevelCommandBufferIndex, rgraphCtx.m_secondLevelCommandBufferCount,
  574. m_ctx.m_shadowRenderableCount, startu, endu);
  575. start = I32(startu);
  576. end = I32(endu);
  577. CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
  578. cmdb->setPolygonOffset(1.0f, 1.0f);
  579. I32 drawcallCount = 0;
  580. for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
  581. {
  582. ANKI_ASSERT(m_ctx.m_probe->m_renderQueues[faceIdx]);
  583. const RenderQueue& faceRenderQueue = *m_ctx.m_probe->m_renderQueues[faceIdx];
  584. ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_uuid != 0);
  585. ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_shadowCascadeCount == 1);
  586. ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0]);
  587. const RenderQueue& cascadeRenderQueue = *faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0];
  588. const I32 faceDrawcallCount = I32(cascadeRenderQueue.m_renderables.getSize());
  589. const I32 localStart = max(I32(0), start - drawcallCount);
  590. const I32 localEnd = min(faceDrawcallCount, end - drawcallCount);
  591. if(localStart < localEnd)
  592. {
  593. const U32 rez = m_shadowMapping.m_rtDescr.m_height;
  594. cmdb->setViewport(rez * faceIdx, 0, rez, rez);
  595. cmdb->setScissor(rez * faceIdx, 0, rez, rez);
  596. ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
  597. RenderableDrawerArguments args;
  598. args.m_viewMatrix = cascadeRenderQueue.m_viewMatrix;
  599. args.m_cameraTransform = Mat3x4::getIdentity(); // Don't care
  600. args.m_viewProjectionMatrix = cascadeRenderQueue.m_viewProjectionMatrix;
  601. args.m_previousViewProjectionMatrix = Mat4::getIdentity(); // Don't care
  602. args.m_sampler = m_r->getSamplers().m_trilinearRepeatAniso;
  603. args.m_minLod = args.m_maxLod = MAX_LOD_COUNT - 1;
  604. m_r->getSceneDrawer().drawRange(RenderingTechnique::SHADOW, args,
  605. cascadeRenderQueue.m_renderables.getBegin() + localStart,
  606. cascadeRenderQueue.m_renderables.getBegin() + localEnd, cmdb);
  607. }
  608. }
  609. }
  610. } // end namespace anki