| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722 |
- // Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #include <AnKi/Renderer/IndirectDiffuseProbes.h>
- #include <AnKi/Renderer/Renderer.h>
- #include <AnKi/Renderer/RenderQueue.h>
- #include <AnKi/Core/ConfigSet.h>
- #include <AnKi/Util/Tracer.h>
- #include <AnKi/Collision/Aabb.h>
- #include <AnKi/Collision/Functions.h>
- namespace anki {
- /// Given a cell index compute its world position.
- static Vec3 computeProbeCellPosition(U32 cellIdx, const GlobalIlluminationProbeQueueElement& probe)
- {
- ANKI_ASSERT(cellIdx < probe.m_totalCellCount);
- UVec3 cellCoords;
- unflatten3dArrayIndex(probe.m_cellCounts.z(), probe.m_cellCounts.y(), probe.m_cellCounts.x(), cellIdx,
- cellCoords.z(), cellCoords.y(), cellCoords.x());
- const Vec3 halfCellSize = probe.m_cellSizes / 2.0f;
- const Vec3 cellPos = Vec3(cellCoords) * probe.m_cellSizes + halfCellSize + probe.m_aabbMin;
- ANKI_ASSERT(cellPos < probe.m_aabbMax);
- return cellPos;
- }
- class IndirectDiffuseProbes::InternalContext
- {
- public:
- IndirectDiffuseProbes* m_gi ANKI_DEBUG_CODE(= numberToPtr<IndirectDiffuseProbes*>(1));
- RenderingContext* m_ctx ANKI_DEBUG_CODE(= numberToPtr<RenderingContext*>(1));
- GlobalIlluminationProbeQueueElement*
- m_probeToUpdateThisFrame ANKI_DEBUG_CODE(= numberToPtr<GlobalIlluminationProbeQueueElement*>(1));
- UVec3 m_cellOfTheProbeToUpdateThisFrame ANKI_DEBUG_CODE(= UVec3(MAX_U32));
- Array<RenderTargetHandle, GBUFFER_COLOR_ATTACHMENT_COUNT> m_gbufferColorRts;
- RenderTargetHandle m_gbufferDepthRt;
- RenderTargetHandle m_shadowsRt;
- RenderTargetHandle m_lightShadingRt;
- WeakArray<RenderTargetHandle> m_irradianceProbeRts;
- U32 m_gbufferDrawcallCount ANKI_DEBUG_CODE(= MAX_U32);
- U32 m_smDrawcallCount ANKI_DEBUG_CODE(= MAX_U32);
- static void foo()
- {
- static_assert(std::is_trivially_destructible<InternalContext>::value, "See file");
- }
- };
- IndirectDiffuseProbes::~IndirectDiffuseProbes()
- {
- m_cacheEntries.destroy(getAllocator());
- m_probeUuidToCacheEntryIdx.destroy(getAllocator());
- }
- const RenderTargetHandle&
- IndirectDiffuseProbes::getVolumeRenderTarget(const GlobalIlluminationProbeQueueElement& probe) const
- {
- ANKI_ASSERT(m_giCtx);
- ANKI_ASSERT(&probe >= &m_giCtx->m_ctx->m_renderQueue->m_giProbes.getFront()
- && &probe <= &m_giCtx->m_ctx->m_renderQueue->m_giProbes.getBack());
- const U32 idx = U32(&probe - &m_giCtx->m_ctx->m_renderQueue->m_giProbes.getFront());
- return m_giCtx->m_irradianceProbeRts[idx];
- }
- void IndirectDiffuseProbes::setRenderGraphDependencies(const RenderingContext& ctx, RenderPassDescriptionBase& pass,
- TextureUsageBit usage) const
- {
- for(U32 idx = 0; idx < ctx.m_renderQueue->m_giProbes.getSize(); ++idx)
- {
- pass.newDependency({getVolumeRenderTarget(ctx.m_renderQueue->m_giProbes[idx]), usage});
- }
- }
- void IndirectDiffuseProbes::bindVolumeTextures(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx, U32 set,
- U32 binding) const
- {
- for(U32 idx = 0; idx < MAX_VISIBLE_GLOBAL_ILLUMINATION_PROBES; ++idx)
- {
- if(idx < ctx.m_renderQueue->m_giProbes.getSize())
- {
- rgraphCtx.bindColorTexture(set, binding, getVolumeRenderTarget(ctx.m_renderQueue->m_giProbes[idx]), idx);
- }
- else
- {
- rgraphCtx.m_commandBuffer->bindTexture(set, binding, m_r->getDummyTextureView3d(), idx);
- }
- }
- }
- Error IndirectDiffuseProbes::init()
- {
- const Error err = initInternal();
- if(err)
- {
- ANKI_R_LOGE("Failed to initialize global illumination");
- }
- return err;
- }
- Error IndirectDiffuseProbes::initInternal()
- {
- m_tileSize = getConfig().getRIndirectDiffuseProbeTileResolution();
- m_cacheEntries.create(getAllocator(), getConfig().getRIndirectDiffuseProbeMaxCachedProbes());
- m_maxVisibleProbes = getConfig().getRIndirectDiffuseProbeMaxVisibleProbes();
- ANKI_ASSERT(m_maxVisibleProbes <= MAX_VISIBLE_GLOBAL_ILLUMINATION_PROBES);
- ANKI_ASSERT(m_cacheEntries.getSize() >= m_maxVisibleProbes);
- ANKI_CHECK(initGBuffer());
- ANKI_CHECK(initLightShading());
- ANKI_CHECK(initShadowMapping());
- ANKI_CHECK(initIrradiance());
- return Error::NONE;
- }
- Error IndirectDiffuseProbes::initGBuffer()
- {
- // Create RT descriptions
- {
- RenderTargetDescription texinit = m_r->create2DRenderTargetDescription(
- m_tileSize * 6, m_tileSize, GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[0], "GI GBuffer");
- // Create color RT descriptions
- for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
- {
- texinit.m_format = GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[i];
- m_gbuffer.m_colorRtDescrs[i] = texinit;
- m_gbuffer.m_colorRtDescrs[i].setName(StringAuto(getAllocator()).sprintf("GI GBuff Col #%u", i).toCString());
- m_gbuffer.m_colorRtDescrs[i].bake();
- }
- // Create depth RT
- texinit.m_format = m_r->getDepthNoStencilFormat();
- texinit.setName("GI GBuff Depth");
- m_gbuffer.m_depthRtDescr = texinit;
- m_gbuffer.m_depthRtDescr.bake();
- }
- // Create FB descr
- {
- m_gbuffer.m_fbDescr.m_colorAttachmentCount = GBUFFER_COLOR_ATTACHMENT_COUNT;
- for(U j = 0; j < GBUFFER_COLOR_ATTACHMENT_COUNT; ++j)
- {
- m_gbuffer.m_fbDescr.m_colorAttachments[j].m_loadOperation = AttachmentLoadOperation::CLEAR;
- }
- m_gbuffer.m_fbDescr.m_depthStencilAttachment.m_aspect = DepthStencilAspectBit::DEPTH;
- m_gbuffer.m_fbDescr.m_depthStencilAttachment.m_loadOperation = AttachmentLoadOperation::CLEAR;
- m_gbuffer.m_fbDescr.m_depthStencilAttachment.m_clearValue.m_depthStencil.m_depth = 1.0f;
- m_gbuffer.m_fbDescr.bake();
- }
- return Error::NONE;
- }
- Error IndirectDiffuseProbes::initShadowMapping()
- {
- const U32 resolution = getConfig().getRIndirectDiffuseProbeShadowMapResolution();
- ANKI_ASSERT(resolution > 8);
- // RT descr
- m_shadowMapping.m_rtDescr =
- m_r->create2DRenderTargetDescription(resolution * 6, resolution, m_r->getDepthNoStencilFormat(), "GI SM");
- m_shadowMapping.m_rtDescr.bake();
- // FB descr
- m_shadowMapping.m_fbDescr.m_colorAttachmentCount = 0;
- m_shadowMapping.m_fbDescr.m_depthStencilAttachment.m_aspect = DepthStencilAspectBit::DEPTH;
- m_shadowMapping.m_fbDescr.m_depthStencilAttachment.m_clearValue.m_depthStencil.m_depth = 1.0f;
- m_shadowMapping.m_fbDescr.m_depthStencilAttachment.m_loadOperation = AttachmentLoadOperation::CLEAR;
- m_shadowMapping.m_fbDescr.bake();
- return Error::NONE;
- }
- Error IndirectDiffuseProbes::initLightShading()
- {
- // Init RT descr
- {
- m_lightShading.m_rtDescr =
- m_r->create2DRenderTargetDescription(m_tileSize * 6, m_tileSize, m_r->getHdrFormat(), "GI LS");
- m_lightShading.m_rtDescr.bake();
- }
- // Create FB descr
- {
- m_lightShading.m_fbDescr.m_colorAttachmentCount = 1;
- m_lightShading.m_fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::CLEAR;
- m_lightShading.m_fbDescr.bake();
- }
- // Init deferred
- ANKI_CHECK(m_lightShading.m_deferred.init());
- return Error::NONE;
- }
- Error IndirectDiffuseProbes::initIrradiance()
- {
- ANKI_CHECK(
- m_r->getResourceManager().loadResource("ShaderBinaries/IrradianceDice.ankiprogbin", m_irradiance.m_prog));
- ShaderProgramResourceVariantInitInfo variantInitInfo(m_irradiance.m_prog);
- variantInitInfo.addMutation("WORKGROUP_SIZE_XY", m_tileSize);
- variantInitInfo.addMutation("LIGHT_SHADING_TEX", 0);
- variantInitInfo.addMutation("STORE_LOCATION", 0);
- variantInitInfo.addMutation("SECOND_BOUNCE", 1);
- const ShaderProgramResourceVariant* variant;
- m_irradiance.m_prog->getOrCreateVariant(variantInitInfo, variant);
- m_irradiance.m_grProg = variant->getProgram();
- return Error::NONE;
- }
- void IndirectDiffuseProbes::populateRenderGraph(RenderingContext& rctx)
- {
- ANKI_TRACE_SCOPED_EVENT(R_GI);
- InternalContext* giCtx = rctx.m_tempAllocator.newInstance<InternalContext>();
- m_giCtx = giCtx;
- giCtx->m_gi = this;
- giCtx->m_ctx = &rctx;
- RenderGraphDescription& rgraph = rctx.m_renderGraphDescr;
- // Prepare the probes
- prepareProbes(*giCtx);
- const Bool haveProbeToRender = giCtx->m_probeToUpdateThisFrame != nullptr;
- if(!haveProbeToRender)
- {
- // Early exit
- return;
- }
- // Compute task counts for some of the passes
- U32 gbufferTaskCount, smTaskCount;
- {
- giCtx->m_gbufferDrawcallCount = 0;
- giCtx->m_smDrawcallCount = 0;
- for(const RenderQueue* rq : giCtx->m_probeToUpdateThisFrame->m_renderQueues)
- {
- ANKI_ASSERT(rq);
- giCtx->m_gbufferDrawcallCount += rq->m_renderables.getSize();
- if(rq->m_directionalLight.hasShadow())
- {
- giCtx->m_smDrawcallCount += rq->m_directionalLight.m_shadowRenderQueues[0]->m_renderables.getSize();
- }
- }
- gbufferTaskCount = computeNumberOfSecondLevelCommandBuffers(giCtx->m_gbufferDrawcallCount);
- smTaskCount = computeNumberOfSecondLevelCommandBuffers(giCtx->m_smDrawcallCount);
- }
- // GBuffer
- {
- // RTs
- for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
- {
- giCtx->m_gbufferColorRts[i] = rgraph.newRenderTarget(m_gbuffer.m_colorRtDescrs[i]);
- }
- giCtx->m_gbufferDepthRt = rgraph.newRenderTarget(m_gbuffer.m_depthRtDescr);
- // Pass
- GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("GI gbuff");
- pass.setFramebufferInfo(m_gbuffer.m_fbDescr, giCtx->m_gbufferColorRts, giCtx->m_gbufferDepthRt);
- pass.setWork(gbufferTaskCount, [this, giCtx](RenderPassWorkContext& rgraphCtx) {
- runGBufferInThread(rgraphCtx, *giCtx);
- });
- for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
- {
- pass.newDependency({giCtx->m_gbufferColorRts[i], TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
- }
- TextureSubresourceInfo subresource(DepthStencilAspectBit::DEPTH);
- pass.newDependency({giCtx->m_gbufferDepthRt, TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT, subresource});
- }
- // Shadow pass. Optional
- if(giCtx->m_probeToUpdateThisFrame->m_renderQueues[0]->m_directionalLight.m_uuid
- && giCtx->m_probeToUpdateThisFrame->m_renderQueues[0]->m_directionalLight.m_shadowCascadeCount > 0)
- {
- // Update light matrices
- for(U i = 0; i < 6; ++i)
- {
- ANKI_ASSERT(giCtx->m_probeToUpdateThisFrame->m_renderQueues[i]->m_directionalLight.m_uuid
- && giCtx->m_probeToUpdateThisFrame->m_renderQueues[i]->m_directionalLight.m_shadowCascadeCount
- == 1);
- const F32 xScale = 1.0f / 6.0f;
- const F32 yScale = 1.0f;
- const F32 xOffset = F32(i) * (1.0f / 6.0f);
- const F32 yOffset = 0.0f;
- 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,
- 0.0f, 0.0f, 1.0f);
- Mat4& lightMat =
- giCtx->m_probeToUpdateThisFrame->m_renderQueues[i]->m_directionalLight.m_textureMatrices[0];
- lightMat = atlasMtx * lightMat;
- }
- // RT
- giCtx->m_shadowsRt = rgraph.newRenderTarget(m_shadowMapping.m_rtDescr);
- // Pass
- GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("GI SM");
- pass.setFramebufferInfo(m_shadowMapping.m_fbDescr, {}, giCtx->m_shadowsRt);
- pass.setWork(smTaskCount, [this, giCtx](RenderPassWorkContext& rgraphCtx) {
- runShadowmappingInThread(rgraphCtx, *giCtx);
- });
- TextureSubresourceInfo subresource(DepthStencilAspectBit::DEPTH);
- pass.newDependency({giCtx->m_shadowsRt, TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT, subresource});
- }
- else
- {
- giCtx->m_shadowsRt = {};
- }
- // Light shading pass
- {
- // RT
- giCtx->m_lightShadingRt = rgraph.newRenderTarget(m_lightShading.m_rtDescr);
- // Pass
- GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("GI LS");
- pass.setFramebufferInfo(m_lightShading.m_fbDescr, {giCtx->m_lightShadingRt});
- pass.setWork(1, [this, giCtx](RenderPassWorkContext& rgraphCtx) {
- runLightShading(rgraphCtx, *giCtx);
- });
- pass.newDependency({giCtx->m_lightShadingRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE});
- for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
- {
- pass.newDependency({giCtx->m_gbufferColorRts[i], TextureUsageBit::SAMPLED_FRAGMENT});
- }
- pass.newDependency({giCtx->m_gbufferDepthRt, TextureUsageBit::SAMPLED_FRAGMENT,
- TextureSubresourceInfo(DepthStencilAspectBit::DEPTH)});
- if(giCtx->m_shadowsRt.isValid())
- {
- pass.newDependency({giCtx->m_shadowsRt, TextureUsageBit::SAMPLED_FRAGMENT});
- }
- }
- // Irradiance pass. First & 2nd bounce
- {
- ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("GI IR");
- pass.setWork([this, giCtx](RenderPassWorkContext& rgraphCtx) {
- runIrradiance(rgraphCtx, *giCtx);
- });
- pass.newDependency({giCtx->m_lightShadingRt, TextureUsageBit::SAMPLED_COMPUTE});
- for(U32 i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT - 1; ++i)
- {
- pass.newDependency({giCtx->m_gbufferColorRts[i], TextureUsageBit::SAMPLED_COMPUTE});
- }
- const U32 probeIdx = U32(giCtx->m_probeToUpdateThisFrame - &giCtx->m_ctx->m_renderQueue->m_giProbes.getFront());
- pass.newDependency({giCtx->m_irradianceProbeRts[probeIdx], TextureUsageBit::IMAGE_COMPUTE_WRITE});
- }
- }
- void IndirectDiffuseProbes::prepareProbes(InternalContext& giCtx)
- {
- RenderingContext& ctx = *giCtx.m_ctx;
- giCtx.m_probeToUpdateThisFrame = nullptr;
- if(ANKI_UNLIKELY(ctx.m_renderQueue->m_giProbes.getSize() == 0))
- {
- return;
- }
- // Iterate the probes and:
- // - Find a probe to update this frame
- // - Find a probe to update next frame
- // - Find the cache entries for each probe
- DynamicArray<GlobalIlluminationProbeQueueElement> newListOfProbes;
- newListOfProbes.create(ctx.m_tempAllocator, ctx.m_renderQueue->m_giProbes.getSize());
- DynamicArray<RenderTargetHandle> volumeRts;
- volumeRts.create(ctx.m_tempAllocator, ctx.m_renderQueue->m_giProbes.getSize());
- U32 newListOfProbeCount = 0;
- Bool foundProbeToUpdateNextFrame = false;
- for(U32 probeIdx = 0; probeIdx < ctx.m_renderQueue->m_giProbes.getSize(); ++probeIdx)
- {
- if(newListOfProbeCount + 1 >= m_maxVisibleProbes)
- {
- ANKI_R_LOGW("Can't have more that %u visible probes. Increase the r_giMaxVisibleProbes or (somehow) "
- "decrease the visible probes",
- m_maxVisibleProbes);
- break;
- }
- GlobalIlluminationProbeQueueElement& probe = ctx.m_renderQueue->m_giProbes[probeIdx];
- // Find cache entry
- const U32 cacheEntryIdx = findBestCacheEntry(probe.m_uuid, m_r->getGlobalTimestamp(), m_cacheEntries,
- m_probeUuidToCacheEntryIdx, getAllocator());
- if(ANKI_UNLIKELY(cacheEntryIdx == MAX_U32))
- {
- // Failed
- ANKI_R_LOGW("There is not enough space in the indirect lighting atlas for more probes. "
- "Increase the r_giMaxCachedProbes or (somehow) decrease the visible probes");
- continue;
- }
- CacheEntry& entry = m_cacheEntries[cacheEntryIdx];
- const Bool cacheEntryDirty = entry.m_uuid != probe.m_uuid || entry.m_volumeSize != probe.m_cellCounts
- || entry.m_probeAabbMin != probe.m_aabbMin
- || entry.m_probeAabbMax != probe.m_aabbMax;
- const Bool needsUpdate = cacheEntryDirty || entry.m_renderedCells < probe.m_totalCellCount;
- if(ANKI_LIKELY(!needsUpdate))
- {
- // It's updated, early exit
- entry.m_lastUsedTimestamp = m_r->getGlobalTimestamp();
- volumeRts[newListOfProbeCount] =
- ctx.m_renderGraphDescr.importRenderTarget(entry.m_volumeTex, TextureUsageBit::SAMPLED_FRAGMENT);
- newListOfProbes[newListOfProbeCount++] = probe;
- continue;
- }
- // It needs update
- const Bool canUpdateThisFrame = giCtx.m_probeToUpdateThisFrame == nullptr && probe.m_renderQueues[0] != nullptr;
- const Bool canUpdateNextFrame = !foundProbeToUpdateNextFrame;
- if(!canUpdateThisFrame && canUpdateNextFrame)
- {
- // Probe will (possibly) be updated next frame, inform the probe
- foundProbeToUpdateNextFrame = true;
- const U32 cellToRender = (cacheEntryDirty) ? 0 : entry.m_renderedCells;
- const Vec3 cellPos = computeProbeCellPosition(cellToRender, probe);
- probe.m_feedbackCallback(true, probe.m_feedbackCallbackUserData, cellPos.xyz0());
- continue;
- }
- else if(!canUpdateThisFrame)
- {
- // Can't be updated this frame so remove it from the list
- continue;
- }
- // All good, can use this probe in this frame
- if(cacheEntryDirty)
- {
- entry.m_renderedCells = 0;
- entry.m_uuid = probe.m_uuid;
- entry.m_probeAabbMin = probe.m_aabbMin;
- entry.m_probeAabbMax = probe.m_aabbMax;
- entry.m_volumeSize = probe.m_cellCounts;
- m_probeUuidToCacheEntryIdx.emplace(getAllocator(), probe.m_uuid, cacheEntryIdx);
- }
- // Update the cache entry
- entry.m_lastUsedTimestamp = m_r->getGlobalTimestamp();
- // Init the cache entry textures
- const Bool shouldInitTextures = !entry.m_volumeTex.isCreated() || entry.m_volumeSize != probe.m_cellCounts;
- if(shouldInitTextures)
- {
- TextureInitInfo texInit("GiProbeVolume");
- texInit.m_type = TextureType::_3D;
- texInit.m_format = m_r->getHdrFormat();
- texInit.m_width = probe.m_cellCounts.x() * 6;
- texInit.m_height = probe.m_cellCounts.y();
- texInit.m_depth = probe.m_cellCounts.z();
- texInit.m_usage = TextureUsageBit::ALL_COMPUTE | TextureUsageBit::ALL_SAMPLED;
- entry.m_volumeTex = m_r->createAndClearRenderTarget(texInit, TextureUsageBit::SAMPLED_FRAGMENT);
- }
- // Compute the render position
- const U32 cellToRender = entry.m_renderedCells++;
- ANKI_ASSERT(cellToRender < probe.m_totalCellCount);
- unflatten3dArrayIndex(probe.m_cellCounts.z(), probe.m_cellCounts.y(), probe.m_cellCounts.x(), cellToRender,
- giCtx.m_cellOfTheProbeToUpdateThisFrame.z(), giCtx.m_cellOfTheProbeToUpdateThisFrame.y(),
- giCtx.m_cellOfTheProbeToUpdateThisFrame.x());
- // Inform probe about its next frame
- if(entry.m_renderedCells == probe.m_totalCellCount)
- {
- // Don't gather renderables next frame if it's done
- probe.m_feedbackCallback(false, probe.m_feedbackCallbackUserData, Vec4(0.0f));
- }
- else if(!foundProbeToUpdateNextFrame)
- {
- // Gather rendederables from the same probe next frame
- foundProbeToUpdateNextFrame = true;
- const Vec3 cellPos = computeProbeCellPosition(entry.m_renderedCells, probe);
- probe.m_feedbackCallback(true, probe.m_feedbackCallbackUserData, cellPos.xyz0());
- }
- // Push the probe to the new list
- giCtx.m_probeToUpdateThisFrame = &newListOfProbes[newListOfProbeCount];
- newListOfProbes[newListOfProbeCount] = probe;
- volumeRts[newListOfProbeCount] =
- ctx.m_renderGraphDescr.importRenderTarget(entry.m_volumeTex, TextureUsageBit::SAMPLED_FRAGMENT);
- ++newListOfProbeCount;
- }
- // Replace the probe list in the queue
- if(newListOfProbeCount > 0)
- {
- GlobalIlluminationProbeQueueElement* firstProbe;
- U32 probeCount, storage;
- newListOfProbes.moveAndReset(firstProbe, probeCount, storage);
- ctx.m_renderQueue->m_giProbes = WeakArray<GlobalIlluminationProbeQueueElement>(firstProbe, newListOfProbeCount);
- RenderTargetHandle* firstRt;
- volumeRts.moveAndReset(firstRt, probeCount, storage);
- m_giCtx->m_irradianceProbeRts = WeakArray<RenderTargetHandle>(firstRt, newListOfProbeCount);
- }
- else
- {
- ctx.m_renderQueue->m_giProbes = WeakArray<GlobalIlluminationProbeQueueElement>();
- newListOfProbes.destroy(ctx.m_tempAllocator);
- volumeRts.destroy(ctx.m_tempAllocator);
- }
- }
- void IndirectDiffuseProbes::runGBufferInThread(RenderPassWorkContext& rgraphCtx, InternalContext& giCtx) const
- {
- ANKI_ASSERT(giCtx.m_probeToUpdateThisFrame);
- ANKI_TRACE_SCOPED_EVENT(R_GI);
- CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
- const GlobalIlluminationProbeQueueElement& probe = *giCtx.m_probeToUpdateThisFrame;
- I32 start, end;
- U32 startu, endu;
- splitThreadedProblem(rgraphCtx.m_currentSecondLevelCommandBufferIndex, rgraphCtx.m_secondLevelCommandBufferCount,
- giCtx.m_gbufferDrawcallCount, startu, endu);
- start = I32(startu);
- end = I32(endu);
- I32 drawcallCount = 0;
- for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
- {
- const I32 faceDrawcallCount = I32(probe.m_renderQueues[faceIdx]->m_renderables.getSize());
- const I32 localStart = max(I32(0), start - drawcallCount);
- const I32 localEnd = min(faceDrawcallCount, end - drawcallCount);
- if(localStart < localEnd)
- {
- const U32 viewportX = faceIdx * m_tileSize;
- cmdb->setViewport(viewportX, 0, m_tileSize, m_tileSize);
- cmdb->setScissor(viewportX, 0, m_tileSize, m_tileSize);
- const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
- ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
- m_r->getSceneDrawer().drawRange(
- RenderingTechnique::GBUFFER, rqueue.m_viewMatrix, rqueue.m_viewProjectionMatrix,
- Mat4::getIdentity(), // Don't care about prev mats since we don't care about velocity
- cmdb, m_r->getSamplers().m_trilinearRepeat, rqueue.m_renderables.getBegin() + localStart,
- rqueue.m_renderables.getBegin() + localEnd, MAX_LOD_COUNT - 1, MAX_LOD_COUNT - 1);
- }
- drawcallCount += faceDrawcallCount;
- }
- ANKI_ASSERT(giCtx.m_gbufferDrawcallCount == U32(drawcallCount));
- // It's secondary, no need to restore the state
- }
- void IndirectDiffuseProbes::runShadowmappingInThread(RenderPassWorkContext& rgraphCtx, InternalContext& giCtx) const
- {
- ANKI_ASSERT(giCtx.m_probeToUpdateThisFrame);
- ANKI_TRACE_SCOPED_EVENT(R_GI);
- const GlobalIlluminationProbeQueueElement& probe = *giCtx.m_probeToUpdateThisFrame;
- I32 start, end;
- U32 startu, endu;
- splitThreadedProblem(rgraphCtx.m_currentSecondLevelCommandBufferIndex, rgraphCtx.m_secondLevelCommandBufferCount,
- giCtx.m_smDrawcallCount, startu, endu);
- start = I32(startu);
- end = I32(endu);
- CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
- cmdb->setPolygonOffset(1.0f, 1.0f);
- I32 drawcallCount = 0;
- for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
- {
- ANKI_ASSERT(probe.m_renderQueues[faceIdx]);
- const RenderQueue& faceRenderQueue = *probe.m_renderQueues[faceIdx];
- ANKI_ASSERT(faceRenderQueue.m_directionalLight.hasShadow());
- ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0]);
- const RenderQueue& cascadeRenderQueue = *faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0];
- const I32 faceDrawcallCount = I32(cascadeRenderQueue.m_renderables.getSize());
- const I32 localStart = max(I32(0), start - drawcallCount);
- const I32 localEnd = min(faceDrawcallCount, end - drawcallCount);
- if(localStart < localEnd)
- {
- const U32 rez = m_shadowMapping.m_rtDescr.m_height;
- cmdb->setViewport(rez * faceIdx, 0, rez, rez);
- cmdb->setScissor(rez * faceIdx, 0, rez, rez);
- ANKI_ASSERT(localStart >= 0 && localEnd <= faceDrawcallCount);
- m_r->getSceneDrawer().drawRange(
- RenderingTechnique::SHADOW, cascadeRenderQueue.m_viewMatrix, cascadeRenderQueue.m_viewProjectionMatrix,
- Mat4::getIdentity(), // Don't care about prev matrices here
- cmdb, m_r->getSamplers().m_trilinearRepeatAniso,
- cascadeRenderQueue.m_renderables.getBegin() + localStart,
- cascadeRenderQueue.m_renderables.getBegin() + localEnd, MAX_LOD_COUNT - 1, MAX_LOD_COUNT - 1);
- }
- }
- // It's secondary, no need to restore the state
- }
- void IndirectDiffuseProbes::runLightShading(RenderPassWorkContext& rgraphCtx, InternalContext& giCtx)
- {
- ANKI_TRACE_SCOPED_EVENT(R_GI);
- ANKI_ASSERT(giCtx.m_probeToUpdateThisFrame);
- const GlobalIlluminationProbeQueueElement& probe = *giCtx.m_probeToUpdateThisFrame;
- CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
- for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
- {
- ANKI_ASSERT(probe.m_renderQueues[faceIdx]);
- const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
- const U32 rez = m_tileSize;
- cmdb->setScissor(rez * faceIdx, 0, rez, rez);
- cmdb->setViewport(rez * faceIdx, 0, rez, rez);
- // Draw light shading
- TraditionalDeferredLightShadingDrawInfo dsInfo;
- dsInfo.m_viewProjectionMatrix = rqueue.m_viewProjectionMatrix;
- dsInfo.m_invViewProjectionMatrix = rqueue.m_viewProjectionMatrix.getInverse();
- dsInfo.m_cameraPosWSpace = rqueue.m_cameraTransform.getTranslationPart();
- dsInfo.m_viewport = UVec4(faceIdx * m_tileSize, 0, m_tileSize, m_tileSize);
- dsInfo.m_gbufferTexCoordsScale = Vec2(1.0f / F32(m_tileSize * 6), 1.0f / F32(m_tileSize));
- dsInfo.m_gbufferTexCoordsBias = Vec2(0.0f, 0.0f);
- dsInfo.m_lightbufferTexCoordsBias = Vec2(-F32(faceIdx), 0.0f);
- dsInfo.m_lightbufferTexCoordsScale = Vec2(1.0f / F32(m_tileSize), 1.0f / F32(m_tileSize));
- dsInfo.m_cameraNear = rqueue.m_cameraNear;
- dsInfo.m_cameraFar = rqueue.m_cameraFar;
- dsInfo.m_directionalLight = (rqueue.m_directionalLight.isEnabled()) ? &rqueue.m_directionalLight : nullptr;
- dsInfo.m_pointLights = rqueue.m_pointLights;
- dsInfo.m_spotLights = rqueue.m_spotLights;
- dsInfo.m_commandBuffer = cmdb;
- dsInfo.m_gbufferRenderTargets[0] = giCtx.m_gbufferColorRts[0];
- dsInfo.m_gbufferRenderTargets[1] = giCtx.m_gbufferColorRts[1];
- dsInfo.m_gbufferRenderTargets[2] = giCtx.m_gbufferColorRts[2];
- dsInfo.m_gbufferDepthRenderTarget = giCtx.m_gbufferDepthRt;
- if(dsInfo.m_directionalLight && dsInfo.m_directionalLight->hasShadow())
- {
- dsInfo.m_directionalLightShadowmapRenderTarget = giCtx.m_shadowsRt;
- }
- dsInfo.m_renderpassContext = &rgraphCtx;
- dsInfo.m_skybox = &giCtx.m_ctx->m_renderQueue->m_skybox;
- m_lightShading.m_deferred.drawLights(dsInfo);
- }
- }
- void IndirectDiffuseProbes::runIrradiance(RenderPassWorkContext& rgraphCtx, InternalContext& giCtx)
- {
- ANKI_TRACE_SCOPED_EVENT(R_GI);
- CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
- ANKI_ASSERT(giCtx.m_probeToUpdateThisFrame);
- const GlobalIlluminationProbeQueueElement& probe = *giCtx.m_probeToUpdateThisFrame;
- const U32 probeIdx = U32(&probe - &giCtx.m_ctx->m_renderQueue->m_giProbes.getFront());
- cmdb->bindShaderProgram(m_irradiance.m_grProg);
- // Bind resources
- cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);
- rgraphCtx.bindColorTexture(0, 1, giCtx.m_lightShadingRt);
- for(U32 i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT - 1; ++i)
- {
- rgraphCtx.bindColorTexture(0, 2, giCtx.m_gbufferColorRts[i], i);
- }
- rgraphCtx.bindImage(0, 3, giCtx.m_irradianceProbeRts[probeIdx], TextureSubresourceInfo());
- class
- {
- public:
- IVec3 m_volumeTexel;
- I32 m_nextTexelOffsetInU;
- } unis;
- unis.m_volumeTexel = IVec3(giCtx.m_cellOfTheProbeToUpdateThisFrame.x(), giCtx.m_cellOfTheProbeToUpdateThisFrame.y(),
- giCtx.m_cellOfTheProbeToUpdateThisFrame.z());
- unis.m_nextTexelOffsetInU = probe.m_cellCounts.x();
- cmdb->setPushConstants(&unis, sizeof(unis));
- // Dispatch
- cmdb->dispatchCompute(1, 1, 1);
- }
- } // end namespace anki
|