Browse Source

Refactor history rejection/length

Panagiotis Christopoulos Charitos 3 years ago
parent
commit
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->getDepthDownscale().getHiZRt(), readUsage, hizSubresource));
 		prpass->newDependency(RenderPassDependency(m_r->getDownscaleBlur().getRt(), readUsage));
 		prpass->newDependency(RenderPassDependency(m_r->getDownscaleBlur().getRt(), readUsage));
 		prpass->newDependency(RenderPassDependency(m_r->getMotionVectors().getMotionVectorsRt(), 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->newDependency(RenderPassDependency(m_runCtx.m_mainRtHandles[READ], readUsage));
 
 
 		prpass->setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
 		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, 7, m_r->getDownscaleBlur().getRt());
 			rgraphCtx.bindColorTexture(0, 8, m_runCtx.m_mainRtHandles[READ]);
 			rgraphCtx.bindColorTexture(0, 8, m_runCtx.m_mainRtHandles[READ]);
 			rgraphCtx.bindColorTexture(0, 9, m_r->getMotionVectors().getMotionVectorsRt());
 			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())
 			if(getConfig().getRPreferCompute())
 			{
 			{

+ 58 - 26
AnKi/Renderer/MotionVectors.cpp

@@ -35,23 +35,33 @@ Error MotionVectors::initInternal()
 													 : "Shaders/MotionVectorsRaster.ankiprog",
 													 : "Shaders/MotionVectorsRaster.ankiprog",
 												 m_prog));
 												 m_prog));
 	ShaderProgramResourceVariantInitInfo variantInitInfo(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;
 	const ShaderProgramResourceVariant* variant;
 	m_prog->getOrCreateVariant(variantInitInfo, variant);
 	m_prog->getOrCreateVariant(variantInitInfo, variant);
 	m_grProg = variant->getProgram();
 	m_grProg = variant->getProgram();
 
 
 	// RTs
 	// RTs
 	m_motionVectorsRtDescr = m_r->create2DRenderTargetDescription(
 	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_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.m_colorAttachmentCount = 2;
 	m_fbDescr.bake();
 	m_fbDescr.bake();
@@ -64,14 +74,32 @@ void MotionVectors::populateRenderGraph(RenderingContext& ctx)
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
 
 
 	m_runCtx.m_motionVectorsRtHandle = rgraph.newRenderTarget(m_motionVectorsRtDescr);
 	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;
 	RenderPassDescriptionBase* ppass;
 	TextureUsageBit readUsage;
 	TextureUsageBit readUsage;
 	TextureUsageBit writeUsage;
 	TextureUsageBit writeUsage;
 	if(getConfig().getRPreferCompute())
 	if(getConfig().getRPreferCompute())
 	{
 	{
-		ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("Motion vectors");
+		ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("MotionVectors");
 
 
 		readUsage = TextureUsageBit::SAMPLED_COMPUTE;
 		readUsage = TextureUsageBit::SAMPLED_COMPUTE;
 		writeUsage = TextureUsageBit::IMAGE_COMPUTE_WRITE;
 		writeUsage = TextureUsageBit::IMAGE_COMPUTE_WRITE;
@@ -79,8 +107,8 @@ void MotionVectors::populateRenderGraph(RenderingContext& ctx)
 	}
 	}
 	else
 	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;
 		readUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		writeUsage = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
 		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_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().getColorRt(3), readUsage));
 	ppass->newDependency(RenderPassDependency(m_r->getGBuffer().getDepthRt(), readUsage));
 	ppass->newDependency(RenderPassDependency(m_r->getGBuffer().getDepthRt(), readUsage));
 	ppass->newDependency(RenderPassDependency(m_r->getGBuffer().getPreviousFrameDepthRt(), 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->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, 1, m_r->getGBuffer().getDepthRt(), TextureSubresourceInfo(DepthStencilAspectBit::DEPTH));
 	rgraphCtx.bindTexture(0, 2, m_r->getGBuffer().getPreviousFrameDepthRt(),
 	rgraphCtx.bindTexture(0, 2, m_r->getGBuffer().getPreviousFrameDepthRt(),
 						  TextureSubresourceInfo(DepthStencilAspectBit::DEPTH));
 						  TextureSubresourceInfo(DepthStencilAspectBit::DEPTH));
 	rgraphCtx.bindColorTexture(0, 3, m_r->getGBuffer().getColorRt(3));
 	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:
 	public:
 		Mat4 m_reprojectionMat;
 		Mat4 m_reprojectionMat;
+		Mat4 m_viewProjectionInvMat;
 		Mat4 m_prevViewProjectionInvMat;
 		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())
 	if(getConfig().getRPreferCompute())
 	{
 	{

+ 10 - 7
AnKi/Renderer/MotionVectors.h

@@ -21,7 +21,7 @@ public:
 		: RendererObject(renderer)
 		: RendererObject(renderer)
 	{
 	{
 		registerDebugRenderTarget("MotionVectors");
 		registerDebugRenderTarget("MotionVectors");
-		registerDebugRenderTarget("MotionVectorsRejection");
+		registerDebugRenderTarget("MotionVectorsHistoryLength");
 	}
 	}
 
 
 	~MotionVectors();
 	~MotionVectors();
@@ -35,9 +35,9 @@ public:
 		return m_runCtx.m_motionVectorsRtHandle;
 		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,
 	void getDebugRenderTarget(CString rtName, RenderTargetHandle& handle,
@@ -49,8 +49,8 @@ public:
 		}
 		}
 		else
 		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;
 	ShaderProgramResourcePtr m_prog;
 	ShaderProgramPtr m_grProg;
 	ShaderProgramPtr m_grProg;
 	RenderTargetDescription m_motionVectorsRtDescr;
 	RenderTargetDescription m_motionVectorsRtDescr;
-	RenderTargetDescription m_rejectionFactorRtDescr;
 	FramebufferDescription m_fbDescr;
 	FramebufferDescription m_fbDescr;
 
 
+	Array<TexturePtr, 2> m_historyLengthTextures;
+	Bool m_historyLengthTexturesImportedOnce = false;
+
 	class
 	class
 	{
 	{
 	public:
 	public:
 		RenderTargetHandle m_motionVectorsRtHandle;
 		RenderTargetHandle m_motionVectorsRtHandle;
-		RenderTargetHandle m_rejectionFactorRtHandle;
+		RenderTargetHandle m_historyLengthReadRtHandle;
+		RenderTargetHandle m_historyLengthWriteRtHandle;
 	} m_runCtx;
 	} m_runCtx;
 
 
 	void run(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx);
 	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);
 		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
 	// Variance RT
 	if(m_useSvgf)
 	if(m_useSvgf)
 	{
 	{
@@ -216,16 +202,12 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 			m_runCtx.m_prevMomentsRt =
 			m_runCtx.m_prevMomentsRt =
 				rgraph.importRenderTarget(m_momentsRts[prevRtIdx], TextureUsageBit::SAMPLED_FRAGMENT);
 				rgraph.importRenderTarget(m_momentsRts[prevRtIdx], TextureUsageBit::SAMPLED_FRAGMENT);
 
 
-			m_runCtx.m_prevHistoryLengthRt =
-				rgraph.importRenderTarget(m_historyLengthRts[prevRtIdx], TextureUsageBit::SAMPLED_FRAGMENT);
-
 			m_rtsImportedOnce = true;
 			m_rtsImportedOnce = true;
 		}
 		}
 		else
 		else
 		{
 		{
 			m_runCtx.m_historyRt = rgraph.importRenderTarget(m_historyRt);
 			m_runCtx.m_historyRt = rgraph.importRenderTarget(m_historyRt);
 			m_runCtx.m_prevMomentsRt = rgraph.importRenderTarget(m_momentsRts[prevRtIdx]);
 			m_runCtx.m_prevMomentsRt = rgraph.importRenderTarget(m_momentsRts[prevRtIdx]);
-			m_runCtx.m_prevHistoryLengthRt = rgraph.importRenderTarget(m_historyLengthRts[prevRtIdx]);
 		}
 		}
 
 
 		if((getPassCountWithoutUpscaling() % 2) == 1)
 		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_currentMomentsRt = rgraph.importRenderTarget(m_momentsRts[!prevRtIdx], TextureUsageBit::NONE);
-		m_runCtx.m_currentHistoryLengthRt =
-			rgraph.importRenderTarget(m_historyLengthRts[!prevRtIdx], TextureUsageBit::NONE);
 
 
 		if(m_useSvgf)
 		if(m_useSvgf)
 		{
 		{
@@ -277,16 +257,12 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 		rpass.newDependency(
 		rpass.newDependency(
 			RenderPassDependency(m_r->getMotionVectors().getMotionVectorsRt(), TextureUsageBit::SAMPLED_TRACE_RAYS));
 			RenderPassDependency(m_r->getMotionVectors().getMotionVectorsRt(), TextureUsageBit::SAMPLED_TRACE_RAYS));
 		rpass.newDependency(
 		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_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_prevMomentsRt, TextureUsageBit::SAMPLED_TRACE_RAYS));
 		rpass.newDependency(RenderPassDependency(m_runCtx.m_currentMomentsRt, TextureUsageBit::IMAGE_TRACE_RAYS_WRITE));
 		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,
 		rpass.newDependency(RenderPassDependency(ctx.m_clusteredShading.m_clustersBufferHandle,
 												 BufferUsageBit::STORAGE_TRACE_RAYS_READ));
 												 BufferUsageBit::STORAGE_TRACE_RAYS_READ));
 	}
 	}
@@ -304,7 +280,8 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 		rpass.newDependency(depthDependency);
 		rpass.newDependency(depthDependency);
 		rpass.newDependency(RenderPassDependency(m_r->getGBuffer().getColorRt(2), TextureUsageBit::SAMPLED_COMPUTE));
 		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_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(
 		rpass.newDependency(
 			RenderPassDependency(m_runCtx.m_intermediateShadowsRts[1], TextureUsageBit::IMAGE_COMPUTE_WRITE));
 			RenderPassDependency(m_runCtx.m_intermediateShadowsRts[1], TextureUsageBit::IMAGE_COMPUTE_WRITE));
@@ -323,7 +300,8 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 		rpass.newDependency(depthDependency);
 		rpass.newDependency(depthDependency);
 		rpass.newDependency(RenderPassDependency(m_r->getGBuffer().getColorRt(2), TextureUsageBit::SAMPLED_COMPUTE));
 		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_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));
 		rpass.newDependency(RenderPassDependency(m_runCtx.m_historyRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
 	}
 	}
@@ -339,7 +317,8 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 		rpass.newDependency(
 		rpass.newDependency(
 			RenderPassDependency(m_runCtx.m_intermediateShadowsRts[0], TextureUsageBit::SAMPLED_COMPUTE));
 			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_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(depthDependency);
 		rpass.newDependency(RenderPassDependency(m_r->getGBuffer().getColorRt(2), TextureUsageBit::SAMPLED_COMPUTE));
 		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);
 	cmdb->bindSampler(0, 9, m_r->getSamplers().m_nearestNearestClamp);
 	rgraphCtx.bindTexture(0, 10, m_r->getDepthDownscale().getHiZRt(), HIZ_HALF_DEPTH);
 	rgraphCtx.bindTexture(0, 10, m_r->getDepthDownscale().getHiZRt(), HIZ_HALF_DEPTH);
 	rgraphCtx.bindColorTexture(0, 11, m_r->getMotionVectors().getMotionVectorsRt());
 	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.bindColorTexture(0, 13, m_r->getGBuffer().getColorRt(2));
 	rgraphCtx.bindAccelerationStructure(0, 14, m_r->getAccelerationStructureBuilder().getAccelerationStructureHandle());
 	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);
 	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.bindTexture(0, 3, m_r->getDepthDownscale().getHiZRt(), HIZ_HALF_DEPTH);
 	rgraphCtx.bindColorTexture(0, 4, m_r->getGBuffer().getColorRt(2));
 	rgraphCtx.bindColorTexture(0, 4, m_r->getGBuffer().getColorRt(2));
 	rgraphCtx.bindColorTexture(0, 5, m_runCtx.m_currentMomentsRt);
 	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(
 	rgraphCtx.bindImage(
 		0, 7, (m_runCtx.m_denoiseOrientation == 0) ? m_runCtx.m_intermediateShadowsRts[1] : m_runCtx.m_historyRt);
 		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, 2, m_runCtx.m_intermediateShadowsRts[0]);
 	rgraphCtx.bindColorTexture(0, 3, m_runCtx.m_currentMomentsRt);
 	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.bindTexture(0, 5, m_r->getDepthDownscale().getHiZRt(), HIZ_HALF_DEPTH);
 
 
 	rgraphCtx.bindImage(0, 6, m_runCtx.m_intermediateShadowsRts[1]);
 	rgraphCtx.bindImage(0, 6, m_runCtx.m_intermediateShadowsRts[1]);

+ 0 - 4
AnKi/Renderer/RtShadows.h

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

+ 3 - 1
AnKi/Scene/CameraNode.cpp

@@ -7,6 +7,7 @@
 #include <AnKi/Scene/Components/FrustumComponent.h>
 #include <AnKi/Scene/Components/FrustumComponent.h>
 #include <AnKi/Scene/Components/MoveComponent.h>
 #include <AnKi/Scene/Components/MoveComponent.h>
 #include <AnKi/Scene/Components/SpatialComponent.h>
 #include <AnKi/Scene/Components/SpatialComponent.h>
+#include <AnKi/Scene/SceneGraph.h>
 #include <AnKi/Core/ConfigSet.h>
 #include <AnKi/Core/ConfigSet.h>
 
 
 namespace anki {
 namespace anki {
@@ -74,7 +75,8 @@ void CameraNode::initCommon(FrustumType frustumType)
 	frc->setLodDistance(1, getConfig().getLod1MaxDistance());
 	frc->setLodDistance(1, getConfig().getLod1MaxDistance());
 
 
 	// Extended frustum for RT
 	// Extended frustum for RT
-	if(getConfig().getSceneRayTracedShadows())
+	if(getSceneGraph().getGrManager().getDeviceCapabilities().m_rayTracingEnabled
+	   && getConfig().getSceneRayTracedShadows())
 	{
 	{
 		FrustumComponent* rtFrustumComponent = newComponent<FrustumComponent>();
 		FrustumComponent* rtFrustumComponent = newComponent<FrustumComponent>();
 		rtFrustumComponent->setFrustumType(FrustumType::ORTHOGRAPHIC);
 		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,
 ANKI_CONFIG_VAR_F32(SceneReflectionProbeShadowEffectiveDistance, 32.0f, 1.0f, MAX_F32,
 					"How far to render shadows for reflection probes")
 					"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,
 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")
 					"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 = 7) ANKI_RP uniform texture2D u_lightBufferRt;
 layout(set = 0, binding = 8) ANKI_RP uniform texture2D u_historyTex;
 layout(set = 0, binding = 8) ANKI_RP uniform texture2D u_historyTex;
 layout(set = 0, binding = 9) uniform texture2D u_motionVectorsTex;
 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)
 #if defined(ANKI_COMPUTE_SHADER)
 const UVec2 WORKGROUP_SIZE = UVec2(8, 8);
 const UVec2 WORKGROUP_SIZE = UVec2(8, 8);
@@ -219,14 +219,20 @@ void main()
 	// Blend color with history
 	// Blend color with history
 	{
 	{
 		const Vec2 historyUv = uv + textureLod(u_motionVectorsTex, u_linearAnyClampSampler, uv, 0.0).xy;
 		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
 		// 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
 	// 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
 // Calculates the motion vectors that will be used to sample from the previous frame
 
 
 ANKI_SPECIALIZATION_CONSTANT_UVEC2(FB_SIZE, 0u);
 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>
 #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 = 1) uniform texture2D u_currentDepthTex;
 layout(set = 0, binding = 2) uniform texture2D u_historyDepthTex;
 layout(set = 0, binding = 2) uniform texture2D u_historyDepthTex;
 layout(set = 0, binding = 3) uniform texture2D u_velocityTex;
 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)
 #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);
 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;
 layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
 #else
 #else
 layout(location = 0) in Vec2 in_uv;
 layout(location = 0) in Vec2 in_uv;
 layout(location = 0) out Vec2 out_motionVectors;
 layout(location = 0) out Vec2 out_motionVectors;
-layout(location = 1) out F32 out_rejectionFactor;
+layout(location = 1) out F32 out_historyLength;
 #endif
 #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()
 void main()
 {
 {
@@ -50,34 +129,9 @@ void main()
 #else
 #else
 	const Vec2 uv = in_uv;
 	const Vec2 uv = in_uv;
 #endif
 #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;
 	Vec2 historyUv;
 	if(velocity.x != 1.0)
 	if(velocity.x != 1.0)
@@ -86,40 +140,31 @@ void main()
 	}
 	}
 	else
 	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);
 		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
 	// Write out
 #if defined(ANKI_COMPUTE_SHADER)
 #if defined(ANKI_COMPUTE_SHADER)
 	imageStore(u_motionVectorsImage, IVec2(gl_GlobalInvocationID.xy), Vec4(historyUv - uv, 0.0, 0.0));
 	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
 #else
 	out_motionVectors = historyUv - uv;
 	out_motionVectors = historyUv - uv;
-	out_rejectionFactor = rejection;
+	out_historyLength = historyLength;
 #endif
 #endif
 }
 }

+ 1 - 1
AnKi/Shaders/RtShadows.glsl

@@ -8,7 +8,7 @@
 #include <AnKi/Shaders/Include/RtShadows.h>
 #include <AnKi/Shaders/Include/RtShadows.h>
 #include <AnKi/Shaders/PackFunctions.glsl>
 #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])
 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 = 9) uniform sampler u_nearestAnyClampSampler;
 layout(set = 0, binding = 10) uniform texture2D u_depthRt;
 layout(set = 0, binding = 10) uniform texture2D u_depthRt;
 layout(set = 0, binding = 11) uniform texture2D u_motionVectorsRt;
 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 = 13) uniform texture2D u_normalRt;
 layout(set = 0, binding = 14) uniform accelerationStructureEXT u_tlas;
 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
 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_shadowsImage, IVec2(gl_LaunchIDEXT.xy), UVec4(0));
 		imageStore(u_momentsImage, IVec2(gl_LaunchIDEXT.xy), Vec4(0.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;
 		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 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
 	// Compute blend fractor. Use nearest sampler because it's an integer texture
 	const F32 lowestBlendFactor = 0.1;
 	const F32 lowestBlendFactor = 0.1;
@@ -228,8 +205,8 @@ void main()
 
 
 	// Blend the moments
 	// Blend the moments
 	const Vec2 prevMoments = textureLod(u_prevMomentsTex, u_linearAnyClampSampler, historyUv, 0.0).xy;
 	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);
 	moments = mix(prevMoments, moments, momentsBlendFactor);
 
 
 	// Store the moments
 	// 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)
 	if(in.getKey(KeyCode::L) == 1)
 	{
 	{
-		renderer.setCurrentDebugRenderTarget(
-			(renderer.getCurrentDebugRenderTarget() == "MotionVectorsRejection") ? "" : "MotionVectorsRejection");
+		renderer.setCurrentDebugRenderTarget((renderer.getCurrentDebugRenderTarget() == "MotionVectorsHistoryLength")
+												 ? ""
+												 : "MotionVectorsHistoryLength");
 	}
 	}
 
 
 	if(in.getKey(KeyCode::H) == 1)
 	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)
 	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))
 	if(in.getEvent(InputEvent::WINDOW_CLOSED))