浏览代码

Refactor history rejection/length

Panagiotis Christopoulos Charitos 3 年之前
父节点
当前提交
8cf38f2a71

+ 2 - 2
AnKi/Renderer/IndirectDiffuse.cpp

@@ -134,7 +134,7 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 		prpass->newDependency(RenderPassDependency(m_r->getDepthDownscale().getHiZRt(), readUsage, hizSubresource));
 		prpass->newDependency(RenderPassDependency(m_r->getDownscaleBlur().getRt(), readUsage));
 		prpass->newDependency(RenderPassDependency(m_r->getMotionVectors().getMotionVectorsRt(), readUsage));
-		prpass->newDependency(RenderPassDependency(m_r->getMotionVectors().getRejectionFactorRt(), readUsage));
+		prpass->newDependency(RenderPassDependency(m_r->getMotionVectors().getHistoryLengthRt(), readUsage));
 		prpass->newDependency(RenderPassDependency(m_runCtx.m_mainRtHandles[READ], readUsage));
 
 		prpass->setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
@@ -156,7 +156,7 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 			rgraphCtx.bindColorTexture(0, 7, m_r->getDownscaleBlur().getRt());
 			rgraphCtx.bindColorTexture(0, 8, m_runCtx.m_mainRtHandles[READ]);
 			rgraphCtx.bindColorTexture(0, 9, m_r->getMotionVectors().getMotionVectorsRt());
-			rgraphCtx.bindColorTexture(0, 10, m_r->getMotionVectors().getRejectionFactorRt());
+			rgraphCtx.bindColorTexture(0, 10, m_r->getMotionVectors().getHistoryLengthRt());
 
 			if(getConfig().getRPreferCompute())
 			{

+ 58 - 26
AnKi/Renderer/MotionVectors.cpp

@@ -35,23 +35,33 @@ Error MotionVectors::initInternal()
 													 : "Shaders/MotionVectorsRaster.ankiprog",
 												 m_prog));
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
-	if(getConfig().getRPreferCompute())
-	{
-		variantInitInfo.addConstant("FB_SIZE",
-									UVec2(m_r->getInternalResolution().x(), m_r->getInternalResolution().y()));
-	}
+	variantInitInfo.addConstant("FB_SIZE", UVec2(m_r->getInternalResolution().x(), m_r->getInternalResolution().y()));
 	const ShaderProgramResourceVariant* variant;
 	m_prog->getOrCreateVariant(variantInitInfo, variant);
 	m_grProg = variant->getProgram();
 
 	// RTs
 	m_motionVectorsRtDescr = m_r->create2DRenderTargetDescription(
-		m_r->getInternalResolution().x(), m_r->getInternalResolution().y(), Format::R16G16_SFLOAT, "Motion vectors");
+		m_r->getInternalResolution().x(), m_r->getInternalResolution().y(), Format::R16G16_SFLOAT, "MotionVectors");
 	m_motionVectorsRtDescr.bake();
 
-	m_rejectionFactorRtDescr = m_r->create2DRenderTargetDescription(
-		m_r->getInternalResolution().x(), m_r->getInternalResolution().y(), Format::R8_UNORM, "Motion vectors rej");
-	m_rejectionFactorRtDescr.bake();
+	TextureUsageBit historyLengthUsage = TextureUsageBit::ALL_SAMPLED;
+	if(getConfig().getRPreferCompute())
+	{
+		historyLengthUsage |= TextureUsageBit::IMAGE_COMPUTE_WRITE;
+	}
+	else
+	{
+		historyLengthUsage |= TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
+	}
+
+	TextureInitInfo historyLengthTexInit =
+		m_r->create2DRenderTargetInitInfo(m_r->getInternalResolution().x(), m_r->getInternalResolution().y(),
+										  Format::R8_UNORM, historyLengthUsage, "MotionVectorsHistoryLen#1");
+	historyLengthTexInit.m_initialUsage = TextureUsageBit::ALL_SAMPLED;
+	m_historyLengthTextures[0] = m_r->createAndClearRenderTarget(historyLengthTexInit);
+	historyLengthTexInit.setName("MotionVectorsHistoryLen#2");
+	m_historyLengthTextures[1] = m_r->createAndClearRenderTarget(historyLengthTexInit);
 
 	m_fbDescr.m_colorAttachmentCount = 2;
 	m_fbDescr.bake();
@@ -64,14 +74,32 @@ void MotionVectors::populateRenderGraph(RenderingContext& ctx)
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
 
 	m_runCtx.m_motionVectorsRtHandle = rgraph.newRenderTarget(m_motionVectorsRtDescr);
-	m_runCtx.m_rejectionFactorRtHandle = rgraph.newRenderTarget(m_rejectionFactorRtDescr);
+
+	const U32 writeHistoryLenTexIdx = m_r->getFrameCount() & 1;
+	const U32 readHistoryLenTexIdx = !writeHistoryLenTexIdx;
+
+	if(ANKI_LIKELY(m_historyLengthTexturesImportedOnce))
+	{
+		m_runCtx.m_historyLengthWriteRtHandle =
+			rgraph.importRenderTarget(m_historyLengthTextures[writeHistoryLenTexIdx]);
+		m_runCtx.m_historyLengthReadRtHandle = rgraph.importRenderTarget(m_historyLengthTextures[readHistoryLenTexIdx]);
+	}
+	else
+	{
+		m_runCtx.m_historyLengthWriteRtHandle =
+			rgraph.importRenderTarget(m_historyLengthTextures[writeHistoryLenTexIdx], TextureUsageBit::ALL_SAMPLED);
+		m_runCtx.m_historyLengthReadRtHandle =
+			rgraph.importRenderTarget(m_historyLengthTextures[readHistoryLenTexIdx], TextureUsageBit::ALL_SAMPLED);
+
+		m_historyLengthTexturesImportedOnce = true;
+	}
 
 	RenderPassDescriptionBase* ppass;
 	TextureUsageBit readUsage;
 	TextureUsageBit writeUsage;
 	if(getConfig().getRPreferCompute())
 	{
-		ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("Motion vectors");
+		ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("MotionVectors");
 
 		readUsage = TextureUsageBit::SAMPLED_COMPUTE;
 		writeUsage = TextureUsageBit::IMAGE_COMPUTE_WRITE;
@@ -79,8 +107,8 @@ void MotionVectors::populateRenderGraph(RenderingContext& ctx)
 	}
 	else
 	{
-		GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("Motion vectors");
-		pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_motionVectorsRtHandle, m_runCtx.m_rejectionFactorRtHandle});
+		GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("MotionVectors");
+		pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_motionVectorsRtHandle, m_runCtx.m_historyLengthWriteRtHandle});
 
 		readUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		writeUsage = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
@@ -92,7 +120,8 @@ void MotionVectors::populateRenderGraph(RenderingContext& ctx)
 	});
 
 	ppass->newDependency(RenderPassDependency(m_runCtx.m_motionVectorsRtHandle, writeUsage));
-	ppass->newDependency(RenderPassDependency(m_runCtx.m_rejectionFactorRtHandle, writeUsage));
+	ppass->newDependency(RenderPassDependency(m_runCtx.m_historyLengthWriteRtHandle, writeUsage));
+	ppass->newDependency(RenderPassDependency(m_runCtx.m_historyLengthReadRtHandle, readUsage));
 	ppass->newDependency(RenderPassDependency(m_r->getGBuffer().getColorRt(3), readUsage));
 	ppass->newDependency(RenderPassDependency(m_r->getGBuffer().getDepthRt(), readUsage));
 	ppass->newDependency(RenderPassDependency(m_r->getGBuffer().getPreviousFrameDepthRt(), readUsage));
@@ -104,28 +133,31 @@ void MotionVectors::run(const RenderingContext& ctx, RenderPassWorkContext& rgra
 
 	cmdb->bindShaderProgram(m_grProg);
 
-	cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);
+	cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
 	rgraphCtx.bindTexture(0, 1, m_r->getGBuffer().getDepthRt(), TextureSubresourceInfo(DepthStencilAspectBit::DEPTH));
 	rgraphCtx.bindTexture(0, 2, m_r->getGBuffer().getPreviousFrameDepthRt(),
 						  TextureSubresourceInfo(DepthStencilAspectBit::DEPTH));
 	rgraphCtx.bindColorTexture(0, 3, m_r->getGBuffer().getColorRt(3));
+	rgraphCtx.bindColorTexture(0, 4, m_runCtx.m_historyLengthReadRtHandle);
 
-	if(getConfig().getRPreferCompute())
-	{
-		rgraphCtx.bindImage(0, 4, m_runCtx.m_motionVectorsRtHandle, TextureSubresourceInfo());
-		rgraphCtx.bindImage(0, 5, m_runCtx.m_rejectionFactorRtHandle, TextureSubresourceInfo());
-	}
-
-	class PC
+	class Uniforms
 	{
 	public:
 		Mat4 m_reprojectionMat;
+		Mat4 m_viewProjectionInvMat;
 		Mat4 m_prevViewProjectionInvMat;
-	} pc;
+	} * pc;
+	pc = allocateAndBindUniforms<Uniforms*>(sizeof(*pc), cmdb, 0, 5);
+
+	pc->m_reprojectionMat = ctx.m_matrices.m_reprojection;
+	pc->m_viewProjectionInvMat = ctx.m_matrices.m_invertedViewProjectionJitter;
+	pc->m_prevViewProjectionInvMat = ctx.m_prevMatrices.m_invertedViewProjectionJitter;
 
-	pc.m_reprojectionMat = ctx.m_matrices.m_reprojection;
-	pc.m_prevViewProjectionInvMat = ctx.m_prevMatrices.m_invertedProjectionJitter;
-	cmdb->setPushConstants(&pc, sizeof(pc));
+	if(getConfig().getRPreferCompute())
+	{
+		rgraphCtx.bindImage(0, 6, m_runCtx.m_motionVectorsRtHandle, TextureSubresourceInfo());
+		rgraphCtx.bindImage(0, 7, m_runCtx.m_historyLengthWriteRtHandle, TextureSubresourceInfo());
+	}
 
 	if(getConfig().getRPreferCompute())
 	{

+ 10 - 7
AnKi/Renderer/MotionVectors.h

@@ -21,7 +21,7 @@ public:
 		: RendererObject(renderer)
 	{
 		registerDebugRenderTarget("MotionVectors");
-		registerDebugRenderTarget("MotionVectorsRejection");
+		registerDebugRenderTarget("MotionVectorsHistoryLength");
 	}
 
 	~MotionVectors();
@@ -35,9 +35,9 @@ public:
 		return m_runCtx.m_motionVectorsRtHandle;
 	}
 
-	RenderTargetHandle getRejectionFactorRt() const
+	RenderTargetHandle getHistoryLengthRt() const
 	{
-		return m_runCtx.m_rejectionFactorRtHandle;
+		return m_runCtx.m_historyLengthWriteRtHandle;
 	}
 
 	void getDebugRenderTarget(CString rtName, RenderTargetHandle& handle,
@@ -49,8 +49,8 @@ public:
 		}
 		else
 		{
-			ANKI_ASSERT(rtName == "MotionVectorsRejection");
-			handle = m_runCtx.m_rejectionFactorRtHandle;
+			ANKI_ASSERT(rtName == "MotionVectorsHistoryLength");
+			handle = m_runCtx.m_historyLengthWriteRtHandle;
 		}
 	}
 
@@ -58,14 +58,17 @@ private:
 	ShaderProgramResourcePtr m_prog;
 	ShaderProgramPtr m_grProg;
 	RenderTargetDescription m_motionVectorsRtDescr;
-	RenderTargetDescription m_rejectionFactorRtDescr;
 	FramebufferDescription m_fbDescr;
 
+	Array<TexturePtr, 2> m_historyLengthTextures;
+	Bool m_historyLengthTexturesImportedOnce = false;
+
 	class
 	{
 	public:
 		RenderTargetHandle m_motionVectorsRtHandle;
-		RenderTargetHandle m_rejectionFactorRtHandle;
+		RenderTargetHandle m_historyLengthReadRtHandle;
+		RenderTargetHandle m_historyLengthWriteRtHandle;
 	} m_runCtx;
 
 	void run(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx);

+ 13 - 36
AnKi/Renderer/RtShadows.cpp

@@ -161,20 +161,6 @@ Error RtShadows::initInternal()
 		m_momentsRts[1] = m_r->createAndClearRenderTarget(texinit);
 	}
 
-	// History len RT
-	{
-		TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(
-			m_r->getInternalResolution().x() / 2, m_r->getInternalResolution().y() / 2, Format::R8_UNORM,
-			TextureUsageBit::ALL_SAMPLED | TextureUsageBit::IMAGE_TRACE_RAYS_WRITE
-				| TextureUsageBit::IMAGE_COMPUTE_WRITE,
-			"RtShadows History Length #1");
-		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
-		m_historyLengthRts[0] = m_r->createAndClearRenderTarget(texinit);
-
-		texinit.setName("RtShadows History Length #2");
-		m_historyLengthRts[1] = m_r->createAndClearRenderTarget(texinit);
-	}
-
 	// Variance RT
 	if(m_useSvgf)
 	{
@@ -216,16 +202,12 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 			m_runCtx.m_prevMomentsRt =
 				rgraph.importRenderTarget(m_momentsRts[prevRtIdx], TextureUsageBit::SAMPLED_FRAGMENT);
 
-			m_runCtx.m_prevHistoryLengthRt =
-				rgraph.importRenderTarget(m_historyLengthRts[prevRtIdx], TextureUsageBit::SAMPLED_FRAGMENT);
-
 			m_rtsImportedOnce = true;
 		}
 		else
 		{
 			m_runCtx.m_historyRt = rgraph.importRenderTarget(m_historyRt);
 			m_runCtx.m_prevMomentsRt = rgraph.importRenderTarget(m_momentsRts[prevRtIdx]);
-			m_runCtx.m_prevHistoryLengthRt = rgraph.importRenderTarget(m_historyLengthRts[prevRtIdx]);
 		}
 
 		if((getPassCountWithoutUpscaling() % 2) == 1)
@@ -241,8 +223,6 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 		}
 
 		m_runCtx.m_currentMomentsRt = rgraph.importRenderTarget(m_momentsRts[!prevRtIdx], TextureUsageBit::NONE);
-		m_runCtx.m_currentHistoryLengthRt =
-			rgraph.importRenderTarget(m_historyLengthRts[!prevRtIdx], TextureUsageBit::NONE);
 
 		if(m_useSvgf)
 		{
@@ -277,16 +257,12 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 		rpass.newDependency(
 			RenderPassDependency(m_r->getMotionVectors().getMotionVectorsRt(), TextureUsageBit::SAMPLED_TRACE_RAYS));
 		rpass.newDependency(
-			RenderPassDependency(m_r->getMotionVectors().getRejectionFactorRt(), TextureUsageBit::SAMPLED_TRACE_RAYS));
+			RenderPassDependency(m_r->getMotionVectors().getHistoryLengthRt(), TextureUsageBit::SAMPLED_TRACE_RAYS));
 		rpass.newDependency(RenderPassDependency(m_r->getGBuffer().getColorRt(2), TextureUsageBit::SAMPLED_TRACE_RAYS));
 
 		rpass.newDependency(RenderPassDependency(m_runCtx.m_prevMomentsRt, TextureUsageBit::SAMPLED_TRACE_RAYS));
 		rpass.newDependency(RenderPassDependency(m_runCtx.m_currentMomentsRt, TextureUsageBit::IMAGE_TRACE_RAYS_WRITE));
 
-		rpass.newDependency(RenderPassDependency(m_runCtx.m_prevHistoryLengthRt, TextureUsageBit::SAMPLED_TRACE_RAYS));
-		rpass.newDependency(
-			RenderPassDependency(m_runCtx.m_currentHistoryLengthRt, TextureUsageBit::IMAGE_TRACE_RAYS_WRITE));
-
 		rpass.newDependency(RenderPassDependency(ctx.m_clusteredShading.m_clustersBufferHandle,
 												 BufferUsageBit::STORAGE_TRACE_RAYS_READ));
 	}
@@ -304,7 +280,8 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 		rpass.newDependency(depthDependency);
 		rpass.newDependency(RenderPassDependency(m_r->getGBuffer().getColorRt(2), TextureUsageBit::SAMPLED_COMPUTE));
 		rpass.newDependency(RenderPassDependency(m_runCtx.m_currentMomentsRt, TextureUsageBit::SAMPLED_COMPUTE));
-		rpass.newDependency(RenderPassDependency(m_runCtx.m_currentHistoryLengthRt, TextureUsageBit::SAMPLED_COMPUTE));
+		rpass.newDependency(
+			RenderPassDependency(m_r->getMotionVectors().getHistoryLengthRt(), TextureUsageBit::SAMPLED_COMPUTE));
 
 		rpass.newDependency(
 			RenderPassDependency(m_runCtx.m_intermediateShadowsRts[1], TextureUsageBit::IMAGE_COMPUTE_WRITE));
@@ -323,7 +300,8 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 		rpass.newDependency(depthDependency);
 		rpass.newDependency(RenderPassDependency(m_r->getGBuffer().getColorRt(2), TextureUsageBit::SAMPLED_COMPUTE));
 		rpass.newDependency(RenderPassDependency(m_runCtx.m_currentMomentsRt, TextureUsageBit::SAMPLED_COMPUTE));
-		rpass.newDependency(RenderPassDependency(m_runCtx.m_currentHistoryLengthRt, TextureUsageBit::SAMPLED_COMPUTE));
+		rpass.newDependency(
+			RenderPassDependency(m_r->getMotionVectors().getHistoryLengthRt(), TextureUsageBit::SAMPLED_COMPUTE));
 
 		rpass.newDependency(RenderPassDependency(m_runCtx.m_historyRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
 	}
@@ -339,7 +317,8 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 		rpass.newDependency(
 			RenderPassDependency(m_runCtx.m_intermediateShadowsRts[0], TextureUsageBit::SAMPLED_COMPUTE));
 		rpass.newDependency(RenderPassDependency(m_runCtx.m_currentMomentsRt, TextureUsageBit::SAMPLED_COMPUTE));
-		rpass.newDependency(RenderPassDependency(m_runCtx.m_currentHistoryLengthRt, TextureUsageBit::SAMPLED_COMPUTE));
+		rpass.newDependency(
+			RenderPassDependency(m_r->getMotionVectors().getHistoryLengthRt(), TextureUsageBit::SAMPLED_COMPUTE));
 		rpass.newDependency(depthDependency);
 		rpass.newDependency(RenderPassDependency(m_r->getGBuffer().getColorRt(2), TextureUsageBit::SAMPLED_COMPUTE));
 
@@ -496,14 +475,12 @@ void RtShadows::run(const RenderingContext& ctx, RenderPassWorkContext& rgraphCt
 	cmdb->bindSampler(0, 9, m_r->getSamplers().m_nearestNearestClamp);
 	rgraphCtx.bindTexture(0, 10, m_r->getDepthDownscale().getHiZRt(), HIZ_HALF_DEPTH);
 	rgraphCtx.bindColorTexture(0, 11, m_r->getMotionVectors().getMotionVectorsRt());
-	rgraphCtx.bindColorTexture(0, 12, m_r->getMotionVectors().getRejectionFactorRt());
+	rgraphCtx.bindColorTexture(0, 12, m_r->getMotionVectors().getHistoryLengthRt());
 	rgraphCtx.bindColorTexture(0, 13, m_r->getGBuffer().getColorRt(2));
 	rgraphCtx.bindAccelerationStructure(0, 14, m_r->getAccelerationStructureBuilder().getAccelerationStructureHandle());
-	rgraphCtx.bindColorTexture(0, 15, m_runCtx.m_prevHistoryLengthRt);
-	rgraphCtx.bindImage(0, 16, m_runCtx.m_currentHistoryLengthRt);
-	rgraphCtx.bindColorTexture(0, 17, m_runCtx.m_prevMomentsRt);
-	rgraphCtx.bindImage(0, 18, m_runCtx.m_currentMomentsRt);
-	cmdb->bindTexture(0, 19, m_blueNoiseImage->getTextureView());
+	rgraphCtx.bindColorTexture(0, 15, m_runCtx.m_prevMomentsRt);
+	rgraphCtx.bindImage(0, 16, m_runCtx.m_currentMomentsRt);
+	cmdb->bindTexture(0, 17, m_blueNoiseImage->getTextureView());
 
 	cmdb->bindAllBindless(1);
 
@@ -530,7 +507,7 @@ void RtShadows::runDenoise(const RenderingContext& ctx, RenderPassWorkContext& r
 	rgraphCtx.bindTexture(0, 3, m_r->getDepthDownscale().getHiZRt(), HIZ_HALF_DEPTH);
 	rgraphCtx.bindColorTexture(0, 4, m_r->getGBuffer().getColorRt(2));
 	rgraphCtx.bindColorTexture(0, 5, m_runCtx.m_currentMomentsRt);
-	rgraphCtx.bindColorTexture(0, 6, m_runCtx.m_currentHistoryLengthRt);
+	rgraphCtx.bindColorTexture(0, 6, m_r->getMotionVectors().getHistoryLengthRt());
 
 	rgraphCtx.bindImage(
 		0, 7, (m_runCtx.m_denoiseOrientation == 0) ? m_runCtx.m_intermediateShadowsRts[1] : m_runCtx.m_historyRt);
@@ -556,7 +533,7 @@ void RtShadows::runSvgfVariance(const RenderingContext& ctx, RenderPassWorkConte
 
 	rgraphCtx.bindColorTexture(0, 2, m_runCtx.m_intermediateShadowsRts[0]);
 	rgraphCtx.bindColorTexture(0, 3, m_runCtx.m_currentMomentsRt);
-	rgraphCtx.bindColorTexture(0, 4, m_runCtx.m_currentHistoryLengthRt);
+	rgraphCtx.bindColorTexture(0, 4, m_r->getMotionVectors().getHistoryLengthRt());
 	rgraphCtx.bindTexture(0, 5, m_r->getDepthDownscale().getHiZRt(), HIZ_HALF_DEPTH);
 
 	rgraphCtx.bindImage(0, 6, m_runCtx.m_intermediateShadowsRts[1]);

+ 0 - 4
AnKi/Renderer/RtShadows.h

@@ -57,7 +57,6 @@ public:
 	RenderTargetDescription m_upscaledRtDescr;
 
 	Array<TexturePtr, 2> m_momentsRts;
-	Array<TexturePtr, 2> m_historyLengthRts;
 
 	RenderTargetDescription m_varianceRtDescr;
 	/// @}
@@ -108,9 +107,6 @@ public:
 		RenderTargetHandle m_prevMomentsRt;
 		RenderTargetHandle m_currentMomentsRt;
 
-		RenderTargetHandle m_prevHistoryLengthRt;
-		RenderTargetHandle m_currentHistoryLengthRt;
-
 		Array<RenderTargetHandle, 2> m_varianceRts;
 
 		BufferPtr m_sbtBuffer;

+ 3 - 1
AnKi/Scene/CameraNode.cpp

@@ -7,6 +7,7 @@
 #include <AnKi/Scene/Components/FrustumComponent.h>
 #include <AnKi/Scene/Components/MoveComponent.h>
 #include <AnKi/Scene/Components/SpatialComponent.h>
+#include <AnKi/Scene/SceneGraph.h>
 #include <AnKi/Core/ConfigSet.h>
 
 namespace anki {
@@ -74,7 +75,8 @@ void CameraNode::initCommon(FrustumType frustumType)
 	frc->setLodDistance(1, getConfig().getLod1MaxDistance());
 
 	// Extended frustum for RT
-	if(getConfig().getSceneRayTracedShadows())
+	if(getSceneGraph().getGrManager().getDeviceCapabilities().m_rayTracingEnabled
+	   && getConfig().getSceneRayTracedShadows())
 	{
 		FrustumComponent* rtFrustumComponent = newComponent<FrustumComponent>();
 		rtFrustumComponent->setFrustumType(FrustumType::ORTHOGRAPHIC);

+ 1 - 1
AnKi/Scene/ConfigVars.defs.h

@@ -16,6 +16,6 @@ ANKI_CONFIG_VAR_F32(SceneReflectionProbeEffectiveDistance, 256.0f, 1.0f, MAX_F32
 ANKI_CONFIG_VAR_F32(SceneReflectionProbeShadowEffectiveDistance, 32.0f, 1.0f, MAX_F32,
 					"How far to render shadows for reflection probes")
 
-ANKI_CONFIG_VAR_BOOL(SceneRayTracedShadows, false, "Enable or not ray traced shadows. Ignored if RT is not supported")
+ANKI_CONFIG_VAR_BOOL(SceneRayTracedShadows, true, "Enable or not ray traced shadows. Ignored if RT is not supported")
 ANKI_CONFIG_VAR_F32(SceneRayTracingExtendedFrustumDistance, 100.0f, 10.0f, 10000.0f,
 					"Every object that its distance from the camera is bellow that value will take part in ray tracing")

+ 12 - 6
AnKi/Shaders/IndirectDiffuse.glsl

@@ -31,7 +31,7 @@ layout(set = 0, binding = 6) uniform texture2D u_depthRt;
 layout(set = 0, binding = 7) ANKI_RP uniform texture2D u_lightBufferRt;
 layout(set = 0, binding = 8) ANKI_RP uniform texture2D u_historyTex;
 layout(set = 0, binding = 9) uniform texture2D u_motionVectorsTex;
-layout(set = 0, binding = 10) uniform texture2D u_motionVectorsRejectionTex;
+layout(set = 0, binding = 10) uniform texture2D u_historyLengthTex;
 
 #if defined(ANKI_COMPUTE_SHADER)
 const UVec2 WORKGROUP_SIZE = UVec2(8, 8);
@@ -219,14 +219,20 @@ void main()
 	// Blend color with history
 	{
 		const Vec2 historyUv = uv + textureLod(u_motionVectorsTex, u_linearAnyClampSampler, uv, 0.0).xy;
-		const F32 historyRejectionFactor = textureLod(u_motionVectorsRejectionTex, u_linearAnyClampSampler, uv, 0.0).x;
+		const F32 historyLength = textureLod(u_historyLengthTex, u_linearAnyClampSampler, uv, 0.0).x;
 
-		const F32 lowestBlendFactor = 0.1;
-		const F32 blendFactor = mix(lowestBlendFactor, 1.0, historyRejectionFactor);
+		const F32 lowestBlendFactor = 0.05;
+		const F32 maxHistoryLength = 16.0;
+		const F32 stableFrames = 4.0;
+		const F32 lerp = min(1.0, (historyLength * maxHistoryLength - 1.0) / stableFrames);
+		const F32 blendFactor = mix(1.0, lowestBlendFactor, lerp);
 
 		// Blend with history
-		const ANKI_RP Vec3 history = textureLod(u_historyTex, u_linearAnyClampSampler, historyUv, 0.0).rgb;
-		outColor = mix(history, outColor, blendFactor);
+		if(blendFactor < 1.0)
+		{
+			const ANKI_RP Vec3 history = textureLod(u_historyTex, u_linearAnyClampSampler, historyUv, 0.0).rgb;
+			outColor = mix(history, outColor, blendFactor);
+		}
 	}
 
 	// Store color

+ 108 - 63
AnKi/Shaders/MotionVectors.glsl

@@ -6,37 +6,116 @@
 // Calculates the motion vectors that will be used to sample from the previous frame
 
 ANKI_SPECIALIZATION_CONSTANT_UVEC2(FB_SIZE, 0u);
-const F32 MAX_REJECTION_DISTANCE = 2.0; // In meters
-#define VARIANCE_CLIPPING 0
-const F32 VARIANCE_CLIPPING_GAMMA = 2.0;
+const F32 MAX_REJECTION_DISTANCE = 0.1; // In meters
+const F32 MAX_HISTORY_LENGTH = 16.0;
 
 #include <AnKi/Shaders/Functions.glsl>
 
-layout(set = 0, binding = 0) uniform sampler u_linearClampSampler;
+layout(set = 0, binding = 0) uniform sampler u_linearAnyClampSampler;
 layout(set = 0, binding = 1) uniform texture2D u_currentDepthTex;
 layout(set = 0, binding = 2) uniform texture2D u_historyDepthTex;
 layout(set = 0, binding = 3) uniform texture2D u_velocityTex;
+layout(set = 0, binding = 4) uniform texture2D u_historyLengthTex;
+
+struct Uniforms
+{
+	Mat4 m_reprojectionMat;
+	Mat4 m_viewProjectionInvMat;
+	Mat4 m_prevViewProjectionInvMat;
+};
+
+layout(set = 0, binding = 5, std140, row_major) uniform b_unis
+{
+	Uniforms u_unis;
+};
 
 #if defined(ANKI_COMPUTE_SHADER)
-layout(set = 0, binding = 4) uniform writeonly image2D u_motionVectorsImage;
-layout(set = 0, binding = 5) uniform writeonly image2D u_rejectionFactorImage;
+layout(set = 0, binding = 6) uniform writeonly image2D u_motionVectorsImage;
+layout(set = 0, binding = 7) uniform writeonly image2D u_historyLengthImage;
 
 const UVec2 WORKGROUP_SIZE = UVec2(8, 8);
 layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
 #else
 layout(location = 0) in Vec2 in_uv;
 layout(location = 0) out Vec2 out_motionVectors;
-layout(location = 1) out F32 out_rejectionFactor;
+layout(location = 1) out F32 out_historyLength;
 #endif
 
-layout(push_constant, std140, row_major) uniform b_pc
+Vec3 clipToWorld(Vec4 clip, Mat4 clipToWorldMat)
 {
-	Mat4 u_reprojectionMat;
-	Mat4 u_prevViewProjectionInvMat;
-};
+	const Vec4 v4 = clipToWorldMat * clip;
+	return v4.xyz / v4.w;
+}
+
+/// Average the some depth values and unproject.
+Vec3 getAverageWorldPosition(texture2D tex, Vec2 uv, Mat4 clipToWorldMat)
+{
+	const Vec2 halfTexel = (1.0 / Vec2(FB_SIZE)) / 2.0;
+
+	Vec4 depths = textureGather(sampler2D(tex, u_linearAnyClampSampler), uv + halfTexel, 0);
+	depths += textureGather(sampler2D(tex, u_linearAnyClampSampler), uv - halfTexel, 0);
+
+	const F32 avgDepth = (depths.x + depths.y + depths.z + depths.w) / 8.0;
+
+	return clipToWorld(Vec4(UV_TO_NDC(uv), avgDepth, 1.0), clipToWorldMat);
+}
+
+/// Get the depths of some neighbour texels, unproject and find the AABB in world space that encloses them.
+void getMinMaxWorldPositions(texture2D tex, Vec2 uv, Mat4 clipToWorldMat, out Vec3 aabbMin, out Vec3 aabbMax)
+{
+	const Vec2 halfTexel = (1.0 / Vec2(FB_SIZE)) / 2.0;
+
+	const Vec4 depths1 = textureGather(sampler2D(tex, u_linearAnyClampSampler), uv + halfTexel, 0);
+	const Vec4 depths2 = textureGather(sampler2D(tex, u_linearAnyClampSampler), uv - halfTexel, 0);
+
+	const Vec4 minDepths4 = min(depths1, depths2);
+	const Vec4 maxDepths4 = max(depths1, depths2);
+
+	const Vec2 minDepths2 = min(minDepths4.xy, minDepths4.zw);
+	const Vec2 maxDepths2 = max(maxDepths4.xy, maxDepths4.zw);
+
+	const F32 minDepth = min(minDepths2.x, minDepths2.y);
+	const F32 maxDepth = max(maxDepths2.x, maxDepths2.y);
+
+	const Vec3 a = clipToWorld(Vec4(UV_TO_NDC(uv), minDepth, 1.0), clipToWorldMat);
+	const Vec3 b = clipToWorld(Vec4(UV_TO_NDC(uv), maxDepth, 1.0), clipToWorldMat);
+
+	aabbMin = min(a, b);
+	aabbMax = max(a, b);
+}
+
+F32 computeRejectionFactor(Vec2 uv, Vec2 historyUv)
+{
+	Vec3 boxMin;
+	Vec3 boxMax;
+	getMinMaxWorldPositions(u_currentDepthTex, uv, u_unis.m_viewProjectionInvMat, boxMin, boxMax);
+
+#if 0
+	const F32 historyDepth = textureLod(u_historyDepthTex, u_linearAnyClampSampler, historyUv, 0.0).r;
+	const Vec3 historyWorldPos = clipToWorld(Vec4(UV_TO_NDC(historyUv), historyDepth, 1.0), u_unis.m_prevViewProjectionInvMat);
+#else
+	// Average gives more rejection so less ghosting
+	const Vec3 historyWorldPos =
+		getAverageWorldPosition(u_historyDepthTex, historyUv, u_unis.m_prevViewProjectionInvMat);
+#endif
+	const Vec3 clampedHistoryWorldPos = clamp(historyWorldPos, boxMin, boxMax);
+
+	// This factor shows when new pixels appeared by checking depth differences
+	const Vec3 delta = clampedHistoryWorldPos - historyWorldPos;
+	const F32 distSquared = dot(delta, delta);
+	const F32 disocclusionFactor = min(1.0, distSquared / (MAX_REJECTION_DISTANCE * MAX_REJECTION_DISTANCE));
+	F32 rejection = disocclusionFactor;
+
+	// New pixels might appeared, add them to the disocclusion
+	const F32 minUv = min(historyUv.x, historyUv.y);
+	const F32 maxUv = max(historyUv.x, historyUv.y);
+	if(minUv <= 0.0 || maxUv >= 1.0)
+	{
+		rejection = 1.0;
+	}
 
-#define readDepth(texture_, uv, offsetX, offsetY) \
-	textureLodOffset(sampler2D(texture_, u_linearClampSampler), uv, 0.0, IVec2(offsetX, offsetY)).r
+	return rejection;
+}
 
 void main()
 {
@@ -50,34 +129,9 @@ void main()
 #else
 	const Vec2 uv = in_uv;
 #endif
-	const F32 depth = readDepth(u_currentDepthTex, uv, 0, 0);
-
-	//
-	// Compute rejection factor
-	//
-	F32 rejection = 0.0;
-
-	// Clamp history to neghbours of current pixel
-	const F32 near0 = readDepth(u_currentDepthTex, uv, 1, 1);
-	const F32 near1 = readDepth(u_currentDepthTex, uv, -1, 1);
-	const F32 near2 = readDepth(u_currentDepthTex, uv, 1, -1);
-	const F32 near3 = readDepth(u_currentDepthTex, uv, -1, -1);
+	const F32 depth = textureLod(u_currentDepthTex, u_linearAnyClampSampler, uv, 0.0).r;
 
-#if VARIANCE_CLIPPING
-	const F32 m1 = depth + near0 + near1 + near2 + near3;
-	const F32 m2 = depth * depth + near0 * near0 + near1 * near1 + near2 * near2 + near3 * near3;
-
-	const F32 mu = m1 / 5.0;
-	const F32 sigma = sqrt(m2 / 5.0 - mu * mu);
-
-	const F32 boxMin = mu - VARIANCE_CLIPPING_GAMMA * sigma;
-	const F32 boxMax = mu + VARIANCE_CLIPPING_GAMMA * sigma;
-#else
-	const F32 boxMin = min(depth, min(near0, min(near1, min(near2, near3))));
-	const F32 boxMax = max(depth, max(near0, max(near1, max(near2, near3))));
-#endif
-
-	const Vec2 velocity = textureLod(u_velocityTex, u_linearClampSampler, uv, 0.0).rg;
+	const Vec2 velocity = textureLod(u_velocityTex, u_linearAnyClampSampler, uv, 0.0).rg;
 
 	Vec2 historyUv;
 	if(velocity.x != 1.0)
@@ -86,40 +140,31 @@ void main()
 	}
 	else
 	{
-		const Vec4 v4 = u_reprojectionMat * Vec4(UV_TO_NDC(uv), depth, 1.0);
+		const Vec4 v4 = u_unis.m_reprojectionMat * Vec4(UV_TO_NDC(uv), depth, 1.0);
 		historyUv = NDC_TO_UV(v4.xy / v4.w);
 	}
 
-	const F32 historyDepth = readDepth(u_historyDepthTex, historyUv, 0, 0);
-	const F32 clampedHistoryDepth = clamp(historyDepth, boxMin, boxMax);
-
-	// This factor shows when new pixels appeared by checking depth differences
-	const Vec4 historyViewSpace4 = u_prevViewProjectionInvMat * Vec4(UV_TO_NDC(historyUv), historyDepth, 1.0);
-	const Vec3 historyViewSpace = historyViewSpace4.xyz / historyViewSpace4.w;
-
-	const Vec4 clampedHistoryViewSpace4 =
-		u_prevViewProjectionInvMat * Vec4(UV_TO_NDC(historyUv), clampedHistoryDepth, 1.0);
-	const Vec3 clampedHistoryViewSpace = clampedHistoryViewSpace4.xyz / clampedHistoryViewSpace4.w;
+	const F32 rejection = computeRejectionFactor(uv, historyUv);
 
-	const Vec3 delta = clampedHistoryViewSpace - historyViewSpace;
-	const F32 distSquared = dot(delta, delta);
-	const F32 disocclusionFactor = min(1.0, distSquared / (MAX_REJECTION_DISTANCE * MAX_REJECTION_DISTANCE));
-	rejection = max(rejection, disocclusionFactor);
-
-	// New pixels might appeared, add them to the disocclusion
-	const F32 minUv = min(historyUv.x, historyUv.y);
-	const F32 maxUv = max(historyUv.x, historyUv.y);
-	if(minUv <= 0.0 || maxUv >= 1.0)
+	// Compute history length
+	F32 historyLength;
+	if(rejection >= 0.5)
 	{
-		rejection = 1.0;
+		// Rejection factor too high, reset the temporal history
+		historyLength = 1.0 / MAX_HISTORY_LENGTH;
+	}
+	else
+	{
+		historyLength = textureLod(u_historyLengthTex, u_linearAnyClampSampler, historyUv, 0.0).r;
+		historyLength += 1.0 / MAX_HISTORY_LENGTH;
 	}
 
 	// Write out
 #if defined(ANKI_COMPUTE_SHADER)
 	imageStore(u_motionVectorsImage, IVec2(gl_GlobalInvocationID.xy), Vec4(historyUv - uv, 0.0, 0.0));
-	imageStore(u_rejectionFactorImage, IVec2(gl_GlobalInvocationID.xy), Vec4(rejection, 0.0, 0.0, 0.0));
+	imageStore(u_historyLengthImage, IVec2(gl_GlobalInvocationID.xy), Vec4(historyLength, 0.0, 0.0, 0.0));
 #else
 	out_motionVectors = historyUv - uv;
-	out_rejectionFactor = rejection;
+	out_historyLength = historyLength;
 #endif
 }

+ 1 - 1
AnKi/Shaders/RtShadows.glsl

@@ -8,7 +8,7 @@
 #include <AnKi/Shaders/Include/RtShadows.h>
 #include <AnKi/Shaders/PackFunctions.glsl>
 
-const F32 RT_SHADOWS_MAX_HISTORY_LENGTH = 31.0;
+const F32 RT_SHADOWS_MAX_HISTORY_LENGTH = 16.0;
 
 UVec4 packRtShadows(F32 shadowFactors[MAX_RT_SHADOW_LAYERS])
 {

+ 8 - 31
AnKi/Shaders/RtShadowsRayGen.ankiprog

@@ -28,14 +28,12 @@ layout(set = 0, binding = 8) uniform sampler u_linearAnyClampSampler;
 layout(set = 0, binding = 9) uniform sampler u_nearestAnyClampSampler;
 layout(set = 0, binding = 10) uniform texture2D u_depthRt;
 layout(set = 0, binding = 11) uniform texture2D u_motionVectorsRt;
-layout(set = 0, binding = 12) uniform texture2D u_motionVectorsRejectionRt;
+layout(set = 0, binding = 12) uniform texture2D u_historyLengthTex;
 layout(set = 0, binding = 13) uniform texture2D u_normalRt;
 layout(set = 0, binding = 14) uniform accelerationStructureEXT u_tlas;
-layout(set = 0, binding = 15) uniform texture2D u_prevHistoryLengthTex;
-layout(set = 0, binding = 16) uniform image2D u_historyLengthImage;
-layout(set = 0, binding = 17) uniform texture2D u_prevMomentsTex;
-layout(set = 0, binding = 18) uniform image2D u_momentsImage;
-layout(set = 0, binding = 19) uniform texture2D u_blueNoiseTex;
+layout(set = 0, binding = 15) uniform texture2D u_prevMomentsTex;
+layout(set = 0, binding = 16) uniform image2D u_momentsImage;
+layout(set = 0, binding = 17) uniform texture2D u_blueNoiseTex;
 
 ANKI_BINDLESS_SET(1); // Used by the hit shaders
 
@@ -75,11 +73,6 @@ void main()
 	{
 		imageStore(u_shadowsImage, IVec2(gl_LaunchIDEXT.xy), UVec4(0));
 		imageStore(u_momentsImage, IVec2(gl_LaunchIDEXT.xy), Vec4(0.0));
-
-		// Set to max history length because this pixel won't need any processing from further compute stages
-		imageStore(u_historyLengthImage, IVec2(gl_LaunchIDEXT.xy),
-				   Vec4(RT_SHADOWS_MAX_HISTORY_LENGTH / RT_SHADOWS_MAX_HISTORY_LENGTH, 0.0, 0.0, 0.0));
-
 		return;
 	}
 
@@ -178,25 +171,9 @@ void main()
 		}
 	}
 
-	// Compute history length
+	// Get history length
 	const Vec2 historyUv = uv + textureLod(u_motionVectorsRt, u_linearAnyClampSampler, uv, 0.0).xy;
-	const F32 historyRejectionFactor = textureLod(u_motionVectorsRejectionRt, u_linearAnyClampSampler, uv, 0.0).x;
-	F32 historyLength;
-	if(historyRejectionFactor >= 0.5)
-	{
-		// Rejection factor too high, reset the temporal history for all layers
-		historyLength = 1.0 / RT_SHADOWS_MAX_HISTORY_LENGTH;
-	}
-	else
-	{
-		// Sample seems stable, increment its temporal history
-
-		historyLength = textureLod(u_prevHistoryLengthTex, u_linearAnyClampSampler, historyUv, 0.0).r;
-		historyLength += 1.0 / RT_SHADOWS_MAX_HISTORY_LENGTH;
-	}
-
-	// Store history length
-	imageStore(u_historyLengthImage, IVec2(gl_LaunchIDEXT.xy), Vec4(historyLength));
+	const F32 historyLength = textureLod(u_historyLengthTex, u_linearAnyClampSampler, uv, 0.0).x;
 
 	// Compute blend fractor. Use nearest sampler because it's an integer texture
 	const F32 lowestBlendFactor = 0.1;
@@ -228,8 +205,8 @@ void main()
 
 	// Blend the moments
 	const Vec2 prevMoments = textureLod(u_prevMomentsTex, u_linearAnyClampSampler, historyUv, 0.0).xy;
-	F32 momentsBlendFactor = 0.2;
-	momentsBlendFactor = mix(momentsBlendFactor, 1.0, historyRejectionFactor);
+	const F32 lowestMomentsBlendFactor = 0.2;
+	const F32 momentsBlendFactor = mix(1.0, lowestMomentsBlendFactor, lerp);
 	moments = mix(prevMoments, moments, momentsBlendFactor);
 
 	// Store the moments

+ 3 - 2
Samples/Common/SampleApp.cpp

@@ -91,8 +91,9 @@ Error SampleApp::userMainLoop(Bool& quit, Second elapsedTime)
 
 	if(in.getKey(KeyCode::L) == 1)
 	{
-		renderer.setCurrentDebugRenderTarget(
-			(renderer.getCurrentDebugRenderTarget() == "MotionVectorsRejection") ? "" : "MotionVectorsRejection");
+		renderer.setCurrentDebugRenderTarget((renderer.getCurrentDebugRenderTarget() == "MotionVectorsHistoryLength")
+												 ? ""
+												 : "MotionVectorsHistoryLength");
 	}
 
 	if(in.getKey(KeyCode::H) == 1)

+ 3 - 2
Sandbox/Main.cpp

@@ -247,8 +247,9 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 
 	if(in.getKey(KeyCode::J) == 1)
 	{
-		renderer.setCurrentDebugRenderTarget(
-			(renderer.getCurrentDebugRenderTarget() == "GBuffer_albedo") ? "" : "GBuffer_albedo");
+		renderer.setCurrentDebugRenderTarget((renderer.getCurrentDebugRenderTarget() == "MotionVectorsHistoryLength")
+												 ? ""
+												 : "MotionVectorsHistoryLength");
 	}
 
 	if(in.getEvent(InputEvent::WINDOW_CLOSED))