2
0

ProbeReflections.cpp 26 KB

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