소스 검색

Add a raster path to a few passes

Panagiotis Christopoulos Charitos 4 년 전
부모
커밋
50fabfa370

+ 60 - 11
AnKi/Renderer/MotionVectors.cpp

@@ -7,6 +7,7 @@
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Renderer/GBuffer.h>
 #include <AnKi/Renderer/RenderQueue.h>
+#include <AnKi/Core/ConfigSet.h>
 
 namespace anki {
 
@@ -15,9 +16,22 @@ MotionVectors::~MotionVectors()
 }
 
 Error MotionVectors::init()
+{
+	const Error err = initInternal();
+	if(err)
+	{
+		ANKI_R_LOGE("Failed to initialize motion vectors");
+	}
+	return err;
+}
+
+Error MotionVectors::initInternal()
 {
 	// Prog
-	ANKI_CHECK(getResourceManager().loadResource("Shaders/MotionVectors.ankiprog", m_prog));
+	ANKI_CHECK(getResourceManager().loadResource((getConfig().getRPreferCompute())
+													 ? "Shaders/MotionVectorsCompute.ankiprog"
+													 : "Shaders/MotionVectorsRaster.ankiprog",
+												 m_prog));
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	variantInitInfo.addConstant("FB_SIZE", UVec2(m_r->getInternalResolution().x(), m_r->getInternalResolution().y()));
 	const ShaderProgramResourceVariant* variant;
@@ -33,6 +47,9 @@ Error MotionVectors::init()
 		m_r->getInternalResolution().x(), m_r->getInternalResolution().y(), Format::R8_UNORM, "Motion vectors rej");
 	m_rejectionFactorRtDescr.bake();
 
+	m_fbDescr.m_colorAttachmentCount = 2;
+	m_fbDescr.bake();
+
 	return Error::NONE;
 }
 
@@ -43,17 +60,36 @@ void MotionVectors::populateRenderGraph(RenderingContext& ctx)
 	m_runCtx.m_motionVectorsRtHandle = rgraph.newRenderTarget(m_motionVectorsRtDescr);
 	m_runCtx.m_rejectionFactorRtHandle = rgraph.newRenderTarget(m_rejectionFactorRtDescr);
 
-	ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("Motion vectors");
+	RenderPassDescriptionBase* ppass;
+	TextureUsageBit readUsage;
+	TextureUsageBit writeUsage;
+	if(getConfig().getRPreferCompute())
+	{
+		ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("Motion vectors");
+
+		readUsage = TextureUsageBit::SAMPLED_COMPUTE;
+		writeUsage = TextureUsageBit::IMAGE_COMPUTE_WRITE;
+		ppass = &pass;
+	}
+	else
+	{
+		GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("Motion vectors");
+		pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_motionVectorsRtHandle, m_runCtx.m_rejectionFactorRtHandle}, {});
+
+		readUsage = TextureUsageBit::SAMPLED_FRAGMENT;
+		writeUsage = TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
+		ppass = &pass;
+	}
 
-	pass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) -> void {
+	ppass->setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) -> void {
 		run(ctx, rgraphCtx);
 	});
 
-	pass.newDependency({m_runCtx.m_motionVectorsRtHandle, TextureUsageBit::IMAGE_COMPUTE_WRITE});
-	pass.newDependency({m_runCtx.m_rejectionFactorRtHandle, TextureUsageBit::IMAGE_COMPUTE_WRITE});
-	pass.newDependency({m_r->getGBuffer().getColorRt(3), TextureUsageBit::SAMPLED_COMPUTE});
-	pass.newDependency({m_r->getGBuffer().getDepthRt(), TextureUsageBit::SAMPLED_COMPUTE});
-	pass.newDependency({m_r->getGBuffer().getPreviousFrameDepthRt(), TextureUsageBit::SAMPLED_COMPUTE});
+	ppass->newDependency(RenderPassDependency(m_runCtx.m_motionVectorsRtHandle, writeUsage));
+	ppass->newDependency(RenderPassDependency(m_runCtx.m_rejectionFactorRtHandle, writeUsage));
+	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));
 }
 
 void MotionVectors::run(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx)
@@ -67,8 +103,12 @@ void MotionVectors::run(const RenderingContext& ctx, RenderPassWorkContext& rgra
 	rgraphCtx.bindTexture(0, 2, m_r->getGBuffer().getPreviousFrameDepthRt(),
 						  TextureSubresourceInfo(DepthStencilAspectBit::DEPTH));
 	rgraphCtx.bindColorTexture(0, 3, m_r->getGBuffer().getColorRt(3));
-	rgraphCtx.bindImage(0, 4, m_runCtx.m_motionVectorsRtHandle, TextureSubresourceInfo());
-	rgraphCtx.bindImage(0, 5, m_runCtx.m_rejectionFactorRtHandle, TextureSubresourceInfo());
+
+	if(getConfig().getRPreferCompute())
+	{
+		rgraphCtx.bindImage(0, 4, m_runCtx.m_motionVectorsRtHandle, TextureSubresourceInfo());
+		rgraphCtx.bindImage(0, 5, m_runCtx.m_rejectionFactorRtHandle, TextureSubresourceInfo());
+	}
 
 	class PC
 	{
@@ -81,7 +121,16 @@ void MotionVectors::run(const RenderingContext& ctx, RenderPassWorkContext& rgra
 	pc.m_prevViewProjectionInvMat = ctx.m_prevMatrices.m_invertedProjectionJitter;
 	cmdb->setPushConstants(&pc, sizeof(pc));
 
-	dispatchPPCompute(cmdb, 8, 8, m_r->getInternalResolution().x(), m_r->getInternalResolution().y());
+	if(getConfig().getRPreferCompute())
+	{
+		dispatchPPCompute(cmdb, 8, 8, m_r->getInternalResolution().x(), m_r->getInternalResolution().y());
+	}
+	else
+	{
+		cmdb->setViewport(0, 0, m_r->getInternalResolution().x(), m_r->getInternalResolution().y());
+
+		cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 3);
+	}
 }
 
 } // end namespace anki

+ 3 - 0
AnKi/Renderer/MotionVectors.h

@@ -59,6 +59,7 @@ private:
 	ShaderProgramPtr m_grProg;
 	RenderTargetDescription m_motionVectorsRtDescr;
 	RenderTargetDescription m_rejectionFactorRtDescr;
+	FramebufferDescription m_fbDescr;
 
 	class
 	{
@@ -68,6 +69,8 @@ private:
 	} m_runCtx;
 
 	void run(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx);
+
+	ANKI_USE_RESULT Error initInternal();
 };
 /// @}
 

+ 75 - 19
AnKi/Renderer/ShadowMapping.cpp

@@ -92,17 +92,19 @@ Error ShadowMapping::initScratch()
 
 Error ShadowMapping::initAtlas()
 {
+	const Bool preferCompute = getConfig().getRPreferCompute();
+
 	// Init RT
 	{
 		m_atlas.m_tileResolution = getConfig().getRShadowMappingTileResolution();
 		m_atlas.m_tileCountBothAxis = getConfig().getRShadowMappingTileCountPerRowOrColumn();
 
 		// RT
+		TextureUsageBit usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_COMPUTE;
+		usage |= (preferCompute) ? TextureUsageBit::IMAGE_COMPUTE_WRITE : TextureUsageBit::ALL_FRAMEBUFFER_ATTACHMENT;
 		TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(
 			m_atlas.m_tileResolution * m_atlas.m_tileCountBothAxis,
-			m_atlas.m_tileResolution * m_atlas.m_tileCountBothAxis, SHADOW_COLOR_PIXEL_FORMAT,
-			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::IMAGE_COMPUTE_WRITE | TextureUsageBit::SAMPLED_COMPUTE,
-			"SM atlas");
+			m_atlas.m_tileResolution * m_atlas.m_tileCountBothAxis, SHADOW_COLOR_PIXEL_FORMAT, usage, "SM atlas");
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 		ClearValue clearVal;
 		clearVal.m_colorf[0] = 1.0f;
@@ -115,18 +117,27 @@ Error ShadowMapping::initAtlas()
 
 	// Programs and shaders
 	{
-		ANKI_CHECK(getResourceManager().loadResource("Shaders/ExponentialShadowmappingResolve.ankiprog",
-													 m_atlas.m_resolveProg));
+		ANKI_CHECK(getResourceManager().loadResource(
+			(preferCompute) ? "Shaders/EvsmCompute.ankiprog" : "Shaders/EvsmRaster.ankiprog", m_atlas.m_resolveProg));
 
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_atlas.m_resolveProg);
 		variantInitInfo.addConstant("INPUT_TEXTURE_SIZE", UVec2(m_scratch.m_tileCountX * m_scratch.m_tileResolution,
 																m_scratch.m_tileCountY * m_scratch.m_tileResolution));
 
+		if(!preferCompute)
+		{
+			variantInitInfo.addConstant("FB_SIZE", UVec2(m_atlas.m_tileCountBothAxis * m_atlas.m_tileResolution));
+		}
+
 		const ShaderProgramResourceVariant* variant;
 		m_atlas.m_resolveProg->getOrCreateVariant(variantInitInfo, variant);
 		m_atlas.m_resolveGrProg = variant->getProgram();
 	}
 
+	m_atlas.m_fbDescr.m_colorAttachmentCount = 1;
+	m_atlas.m_fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::LOAD;
+	m_atlas.m_fbDescr.bake();
+
 	return Error::NONE;
 }
 
@@ -169,13 +180,23 @@ void ShadowMapping::runAtlas(RenderPassWorkContext& rgraphCtx)
 	// Continue
 	cmdb->bindSampler(0, 1, m_r->getSamplers().m_trilinearClamp);
 	rgraphCtx.bindTexture(0, 2, m_scratch.m_rt, TextureSubresourceInfo(DepthStencilAspectBit::DEPTH));
-	rgraphCtx.bindImage(0, 3, m_atlas.m_rt);
 
-	constexpr U32 workgroupSize = 8;
-	ANKI_ASSERT(m_atlas.m_tileResolution >= workgroupSize && (m_atlas.m_tileResolution % workgroupSize) == 0);
+	if(getConfig().getRPreferCompute())
+	{
+		rgraphCtx.bindImage(0, 3, m_atlas.m_rt);
+
+		constexpr U32 workgroupSize = 8;
+		ANKI_ASSERT(m_atlas.m_tileResolution >= workgroupSize && (m_atlas.m_tileResolution % workgroupSize) == 0);
 
-	cmdb->dispatchCompute(m_atlas.m_tileResolution / workgroupSize, m_atlas.m_tileResolution / workgroupSize,
-						  m_atlas.m_resolveWorkItems.getSize());
+		cmdb->dispatchCompute(m_atlas.m_tileResolution / workgroupSize, m_atlas.m_tileResolution / workgroupSize,
+							  m_atlas.m_resolveWorkItems.getSize());
+	}
+	else
+	{
+		cmdb->setViewport(0, 0, m_atlas.m_tex->getWidth(), m_atlas.m_tex->getHeight());
+
+		cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 6, m_atlas.m_resolveWorkItems.getSize());
+	}
 }
 
 void ShadowMapping::runShadowMapping(RenderPassWorkContext& rgraphCtx)
@@ -245,22 +266,57 @@ void ShadowMapping::populateRenderGraph(RenderingContext& ctx)
 
 		// Atlas pass
 		{
-			ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("SM atlas");
+			if(ANKI_LIKELY(m_atlas.m_rtImportedOnce))
+			{
+				m_atlas.m_rt = rgraph.importRenderTarget(m_atlas.m_tex);
+			}
+			else
+			{
+				m_atlas.m_rt = rgraph.importRenderTarget(m_atlas.m_tex, TextureUsageBit::SAMPLED_FRAGMENT);
+				m_atlas.m_rtImportedOnce = true;
+			}
 
-			m_atlas.m_rt = rgraph.importRenderTarget(m_atlas.m_tex, TextureUsageBit::SAMPLED_FRAGMENT);
-			pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
-				runAtlas(rgraphCtx);
-			});
+			if(getConfig().getRPreferCompute())
+			{
+				ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("SM atlas");
 
-			pass.newDependency({m_scratch.m_rt, TextureUsageBit::SAMPLED_COMPUTE,
-								TextureSubresourceInfo(DepthStencilAspectBit::DEPTH)});
-			pass.newDependency({m_atlas.m_rt, TextureUsageBit::IMAGE_COMPUTE_WRITE});
+				pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
+					runAtlas(rgraphCtx);
+				});
+
+				pass.newDependency(RenderPassDependency(m_scratch.m_rt, TextureUsageBit::SAMPLED_COMPUTE,
+														TextureSubresourceInfo(DepthStencilAspectBit::DEPTH)));
+				pass.newDependency(RenderPassDependency(m_atlas.m_rt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
+			}
+			else
+			{
+				GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("SM atlas");
+				pass.setFramebufferInfo(m_atlas.m_fbDescr, {m_atlas.m_rt}, {});
+
+				pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
+					runAtlas(rgraphCtx);
+				});
+
+				pass.newDependency(RenderPassDependency(m_scratch.m_rt, TextureUsageBit::SAMPLED_FRAGMENT,
+														TextureSubresourceInfo(DepthStencilAspectBit::DEPTH)));
+				pass.newDependency(
+					RenderPassDependency(m_atlas.m_rt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ
+														   | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
+			}
 		}
 	}
 	else
 	{
 		// No need for shadowmapping passes, just import the atlas
-		m_atlas.m_rt = rgraph.importRenderTarget(m_atlas.m_tex, TextureUsageBit::SAMPLED_FRAGMENT);
+		if(ANKI_LIKELY(m_atlas.m_rtImportedOnce))
+		{
+			m_atlas.m_rt = rgraph.importRenderTarget(m_atlas.m_tex);
+		}
+		else
+		{
+			m_atlas.m_rt = rgraph.importRenderTarget(m_atlas.m_tex, TextureUsageBit::SAMPLED_FRAGMENT);
+			m_atlas.m_rtImportedOnce = true;
+		}
 	}
 }
 

+ 3 - 0
AnKi/Renderer/ShadowMapping.h

@@ -49,6 +49,7 @@ private:
 
 		TexturePtr m_tex; ///<  Size (m_tileResolution*m_tileCountBothAxis)^2
 		RenderTargetHandle m_rt;
+		Bool m_rtImportedOnce = false;
 
 		U32 m_tileResolution = 0; ///< Tile resolution.
 		U32 m_tileCountBothAxis = 0;
@@ -56,6 +57,8 @@ private:
 		ShaderProgramResourcePtr m_resolveProg;
 		ShaderProgramPtr m_resolveGrProg;
 
+		FramebufferDescription m_fbDescr;
+
 		WeakArray<ResolveWorkItem> m_resolveWorkItems;
 	} m_atlas;
 

+ 68 - 22
AnKi/Renderer/TemporalAA.cpp

@@ -9,6 +9,7 @@
 #include <AnKi/Renderer/LightShading.h>
 #include <AnKi/Renderer/Tonemapping.h>
 #include <AnKi/Renderer/MotionVectors.h>
+#include <AnKi/Core/ConfigSet.h>
 
 namespace anki {
 
@@ -34,17 +35,23 @@ Error TemporalAA::init()
 
 Error TemporalAA::initInternal()
 {
-	ANKI_CHECK(m_r->getResourceManager().loadResource("Shaders/TemporalAAResolve.ankiprog", m_prog));
+	ANKI_CHECK(m_r->getResourceManager().loadResource(
+		(getConfig().getRPreferCompute()) ? "Shaders/TemporalAACompute.ankiprog" : "Shaders/TemporalAARaster.ankiprog",
+		m_prog));
 
 	{
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 		variantInitInfo.addConstant("VARIANCE_CLIPPING_GAMMA", 2.7f);
 		variantInitInfo.addConstant("BLEND_FACTOR", 1.0f / 16.0f);
-		variantInitInfo.addConstant("FB_SIZE",
-									UVec2(m_r->getInternalResolution().x(), m_r->getInternalResolution().y()));
 		variantInitInfo.addMutation("VARIANCE_CLIPPING", 1);
 		variantInitInfo.addMutation("YCBCR", 0);
 
+		if(getConfig().getRPreferCompute())
+		{
+			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();
@@ -52,11 +59,13 @@ Error TemporalAA::initInternal()
 
 	for(U i = 0; i < 2; ++i)
 	{
-		TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(
-			m_r->getInternalResolution().x(), m_r->getInternalResolution().y(),
-			LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
-			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_COMPUTE | TextureUsageBit::IMAGE_COMPUTE_WRITE,
-			"TemporalAA");
+		TextureUsageBit usage = TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_COMPUTE;
+		usage |= (getConfig().getRPreferCompute()) ? TextureUsageBit::IMAGE_COMPUTE_WRITE
+												   : TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE;
+
+		TextureInitInfo texinit =
+			m_r->create2DRenderTargetInitInfo(m_r->getInternalResolution().x(), m_r->getInternalResolution().y(),
+											  LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT, usage, "TemporalAA");
 
 		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 
@@ -68,6 +77,9 @@ Error TemporalAA::initInternal()
 											 Format::R8G8B8A8_UNORM, "TemporalAA Tonemapped");
 	m_tonemappedRtDescr.bake();
 
+	m_fbDescr.m_colorAttachmentCount = 2;
+	m_fbDescr.bake();
+
 	return Error::NONE;
 }
 
@@ -77,6 +89,7 @@ void TemporalAA::populateRenderGraph(RenderingContext& ctx)
 
 	const U32 historyRtIdx = (m_r->getFrameCount() + 1) & 1;
 	const U32 renderRtIdx = !historyRtIdx;
+	const Bool preferCompute = getConfig().getRPreferCompute();
 
 	// Import RTs
 	if(ANKI_LIKELY(m_rtTexturesImportedOnce[historyRtIdx]))
@@ -93,9 +106,40 @@ void TemporalAA::populateRenderGraph(RenderingContext& ctx)
 	m_runCtx.m_tonemappedRt = rgraph.newRenderTarget(m_tonemappedRtDescr);
 
 	// Create pass
-	ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("TemporalAA");
+	TextureUsageBit readUsage;
+	RenderPassDescriptionBase* prpass;
+	if(preferCompute)
+	{
+		ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("TemporalAA");
+
+		pass.newDependency(RenderPassDependency(m_runCtx.m_renderRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
+		pass.newDependency(RenderPassDependency(m_runCtx.m_tonemappedRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
+
+		readUsage = TextureUsageBit::SAMPLED_COMPUTE;
+
+		prpass = &pass;
+	}
+	else
+	{
+		GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass("TemporalAA");
+		pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_renderRt, m_runCtx.m_tonemappedRt}, {});
+
+		pass.newDependency(RenderPassDependency(m_runCtx.m_renderRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
+		pass.newDependency(
+			RenderPassDependency(m_runCtx.m_tonemappedRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
+
+		readUsage = TextureUsageBit::SAMPLED_FRAGMENT;
+
+		prpass = &pass;
+	}
 
-	pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
+	prpass->newDependency(RenderPassDependency(m_r->getGBuffer().getDepthRt(), readUsage,
+											   TextureSubresourceInfo(DepthStencilAspectBit::DEPTH)));
+	prpass->newDependency(RenderPassDependency(m_r->getLightShading().getRt(), readUsage));
+	prpass->newDependency(RenderPassDependency(m_runCtx.m_historyRt, readUsage));
+	prpass->newDependency(RenderPassDependency(m_r->getMotionVectors().getMotionVectorsRt(), readUsage));
+
+	prpass->setWork([this](RenderPassWorkContext& rgraphCtx) {
 		CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
 		cmdb->bindShaderProgram(m_grProg);
@@ -106,20 +150,22 @@ void TemporalAA::populateRenderGraph(RenderingContext& ctx)
 		rgraphCtx.bindColorTexture(0, 2, m_r->getLightShading().getRt());
 		rgraphCtx.bindColorTexture(0, 3, m_runCtx.m_historyRt);
 		rgraphCtx.bindColorTexture(0, 4, m_r->getMotionVectors().getMotionVectorsRt());
-		rgraphCtx.bindImage(0, 5, m_runCtx.m_renderRt, TextureSubresourceInfo());
-		rgraphCtx.bindImage(0, 6, m_runCtx.m_tonemappedRt, TextureSubresourceInfo());
-		rgraphCtx.bindUniformBuffer(0, 7, m_r->getTonemapping().getAverageLuminanceBuffer());
+		rgraphCtx.bindUniformBuffer(0, 5, m_r->getTonemapping().getAverageLuminanceBuffer());
 
-		dispatchPPCompute(cmdb, 8, 8, m_r->getInternalResolution().x(), m_r->getInternalResolution().y());
-	});
+		if(getConfig().getRPreferCompute())
+		{
+			rgraphCtx.bindImage(0, 6, m_runCtx.m_renderRt, TextureSubresourceInfo());
+			rgraphCtx.bindImage(0, 7, m_runCtx.m_tonemappedRt, TextureSubresourceInfo());
 
-	pass.newDependency({m_runCtx.m_renderRt, TextureUsageBit::IMAGE_COMPUTE_WRITE});
-	pass.newDependency({m_runCtx.m_tonemappedRt, TextureUsageBit::IMAGE_COMPUTE_WRITE});
-	pass.newDependency({m_r->getGBuffer().getDepthRt(), TextureUsageBit::SAMPLED_COMPUTE,
-						TextureSubresourceInfo(DepthStencilAspectBit::DEPTH)});
-	pass.newDependency({m_r->getLightShading().getRt(), TextureUsageBit::SAMPLED_COMPUTE});
-	pass.newDependency({m_runCtx.m_historyRt, TextureUsageBit::SAMPLED_COMPUTE});
-	pass.newDependency({m_r->getMotionVectors().getMotionVectorsRt(), TextureUsageBit::SAMPLED_COMPUTE});
+			dispatchPPCompute(cmdb, 8, 8, m_r->getInternalResolution().x(), m_r->getInternalResolution().y());
+		}
+		else
+		{
+			cmdb->setViewport(0, 0, m_r->getInternalResolution().x(), m_r->getInternalResolution().y());
+
+			cmdb->drawArrays(PrimitiveTopology::TRIANGLES, 3);
+		}
+	});
 }
 
 } // end namespace anki

+ 1 - 0
AnKi/Renderer/TemporalAA.h

@@ -42,6 +42,7 @@ private:
 	ShaderProgramPtr m_grProg;
 
 	RenderTargetDescription m_tonemappedRtDescr;
+	FramebufferDescription m_fbDescr;
 
 	class
 	{

+ 53 - 13
AnKi/Shaders/ExponentialShadowmappingResolve.ankiprog → AnKi/Shaders/Evsm.glsl

@@ -4,26 +4,55 @@
 // http://www.anki3d.org/LICENSE
 
 ANKI_SPECIALIZATION_CONSTANT_UVEC2(INPUT_TEXTURE_SIZE, 0u);
+ANKI_SPECIALIZATION_CONSTANT_UVEC2(FB_SIZE, 2u);
 
-#pragma anki start comp
-#include <AnKi/Shaders/GaussianBlurCommon.glsl>
-#include <AnKi/Shaders/LightFunctions.glsl>
 #include <AnKi/Shaders/Include/ShadowMappingTypes.h>
 
-layout(local_size_x = 8, local_size_y = 8) in;
-
-const F32 OFFSET = 1.25;
-
 layout(set = 0, binding = 0, std430) readonly buffer b_unis
 {
 	ShadowMappingUniforms u_uniforms[];
 };
 
+#if defined(ANKI_VERTEX_SHADER)
+#	include <AnKi/Shaders/Common.glsl>
+
+layout(location = 0) out Vec2 out_uv;
+layout(location = 1) flat out I32 out_instanceIndex;
+
+void main()
+{
+	const ShadowMappingUniforms uni = u_uniforms[gl_InstanceIndex];
+
+	const Vec2 uv = Vec2(((gl_VertexID + 2) / 3) % 2, ((gl_VertexID + 1) / 3) % 2);
+
+	out_uv = uv * uni.m_uvScale + uni.m_uvTranslation;
+
+	const Vec2 pos = UV_TO_NDC((Vec2(uni.m_viewportXY) + uni.m_viewportZW * uv) / Vec2(FB_SIZE));
+	gl_Position = Vec4(pos, 0.0, 1.0);
+
+	out_instanceIndex = gl_InstanceIndex;
+}
+
+#else // !defined(ANKI_VERTEX_SHADER)
+
+#	include <AnKi/Shaders/GaussianBlurCommon.glsl>
+#	include <AnKi/Shaders/LightFunctions.glsl>
+
+const F32 OFFSET = 1.25;
+
 layout(set = 0, binding = 1) uniform sampler u_linearAnyClampSampler;
 layout(set = 0, binding = 2) uniform texture2D u_inputTex;
 
+#	if defined(ANKI_COMPUTE_SHADER)
 layout(set = 0, binding = 3) uniform writeonly image2D u_outImg;
 
+layout(local_size_x = 8, local_size_y = 8) in;
+#	else
+layout(location = 0) in Vec2 in_uv;
+layout(location = 1) flat in I32 in_instanceIndex;
+layout(location = 0) out Vec4 out_moments;
+#	endif
+
 Vec4 computeMoments(Vec2 uv)
 {
 	const F32 d = textureLod(u_inputTex, u_linearAnyClampSampler, uv, 0.0).r;
@@ -33,11 +62,16 @@ Vec4 computeMoments(Vec2 uv)
 
 void main()
 {
+#	if defined(ANKI_COMPUTE_SHADER)
 	const ShadowMappingUniforms uni = u_uniforms[gl_GlobalInvocationID.z];
 
-	// Compute the read UV
-	Vec2 uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / uni.m_viewportZW;
+	Vec2 uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / uni.m_viewportZW; // in [0, 1]
 	uv = uv * uni.m_uvScale + uni.m_uvTranslation;
+#	else
+	const ShadowMappingUniforms uni = u_uniforms[in_instanceIndex];
+
+	Vec2 uv = in_uv;
+#	endif
 
 	// Compute the UV limits. We can't sample beyond those
 	const Vec2 TEXEL_SIZE = 1.0 / Vec2(INPUT_TEXTURE_SIZE);
@@ -69,11 +103,17 @@ void main()
 	}
 
 	// Write the results
-#if ANKI_EVSM4
+#	if ANKI_EVSM4
 	const Vec4 outColor = moments;
-#else
+#	else
 	const Vec4 outColor = Vec4(moments.xy, 0.0, 0.0);
-#endif
+#	endif
+
+#	if defined(ANKI_COMPUTE_SHADER)
 	imageStore(u_outImg, IVec2(gl_GlobalInvocationID.xy) + uni.m_viewportXY, outColor);
+#	else
+	out_moments = outColor;
+#	endif
 }
-#pragma anki end
+
+#endif // !defined(ANKI_VERTEX_SHADER)

+ 8 - 0
AnKi/Shaders/EvsmCompute.ankiprog

@@ -0,0 +1,8 @@
+// Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma anki start comp
+#include <AnKi/Shaders/Evsm.glsl>
+#pragma anki end

+ 12 - 0
AnKi/Shaders/EvsmRaster.ankiprog

@@ -0,0 +1,12 @@
+// Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma anki start vert
+#include <AnKi/Shaders/Evsm.glsl>
+#pragma anki end
+
+#pragma anki start frag
+#include <AnKi/Shaders/Evsm.glsl>
+#pragma anki end

+ 21 - 12
AnKi/Shaders/MotionVectors.ankiprog → AnKi/Shaders/MotionVectors.glsl

@@ -10,20 +10,25 @@ const F32 MAX_REJECTION_DISTANCE = 2.0; // In meters
 #define VARIANCE_CLIPPING 0
 const F32 VARIANCE_CLIPPING_GAMMA = 2.0;
 
-#pragma anki start comp
-
 #include <AnKi/Shaders/Functions.glsl>
 
-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(set = 0, binding = 0) uniform sampler u_linearClampSampler;
 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;
+
+#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;
 
+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;
+#endif
+
 layout(push_constant, std140, row_major) uniform b_pc
 {
 	Mat4 u_reprojectionMat;
@@ -35,15 +40,16 @@ layout(push_constant, std140, row_major) uniform b_pc
 
 void main()
 {
-	if((FB_SIZE.x % WORKGROUP_SIZE.x) != 0u || (FB_SIZE.y % WORKGROUP_SIZE.y) != 0u) // This check is free
+#if defined(ANKI_COMPUTE_SHADER)
+	if(skipOutOfBoundsInvocations(WORKGROUP_SIZE, FB_SIZE))
 	{
-		if(gl_GlobalInvocationID.x >= FB_SIZE.x || gl_GlobalInvocationID.y >= FB_SIZE.y)
-		{
-			return;
-		}
+		return;
 	}
 
 	const Vec2 uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(FB_SIZE);
+#else
+	const Vec2 uv = in_uv;
+#endif
 	const F32 depth = readDepth(u_currentDepthTex, uv, 0, 0);
 
 	//
@@ -109,8 +115,11 @@ void main()
 	}
 
 	// 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));
+#else
+	out_motionVectors = historyUv - uv;
+	out_rejectionFactor = rejection;
+#endif
 }
-
-#pragma anki end

+ 8 - 0
AnKi/Shaders/MotionVectorsCompute.ankiprog

@@ -0,0 +1,8 @@
+// Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma anki start comp
+#include <AnKi/Shaders/MotionVectors.glsl>
+#pragma anki end

+ 12 - 0
AnKi/Shaders/MotionVectorsRaster.ankiprog

@@ -0,0 +1,12 @@
+// Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma anki start vert
+#include <AnKi/Shaders/QuadVert.glsl>
+#pragma anki end
+
+#pragma anki start frag
+#include <AnKi/Shaders/MotionVectors.glsl>
+#pragma anki end

+ 0 - 5
AnKi/Shaders/QuadVert.glsl

@@ -5,11 +5,6 @@
 
 #include <AnKi/Shaders/Common.glsl>
 
-out gl_PerVertex
-{
-	Vec4 gl_Position;
-};
-
 layout(location = 0) out Vec2 out_uv;
 
 void main()

+ 24 - 10
AnKi/Shaders/TemporalAAResolve.ankiprog → AnKi/Shaders/TemporalAA.glsl

@@ -10,26 +10,32 @@ ANKI_SPECIALIZATION_CONSTANT_F32(VARIANCE_CLIPPING_GAMMA, 0u);
 ANKI_SPECIALIZATION_CONSTANT_F32(BLEND_FACTOR, 1u);
 ANKI_SPECIALIZATION_CONSTANT_UVEC2(FB_SIZE, 2u);
 
-#pragma anki start comp
 #include <AnKi/Shaders/Functions.glsl>
 #include <AnKi/Shaders/PackFunctions.glsl>
 #include <AnKi/Shaders/TonemappingFunctions.glsl>
 
-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(set = 0, binding = 0) uniform sampler u_linearAnyClampSampler;
 layout(set = 0, binding = 1) uniform texture2D u_depthRt;
 layout(set = 0, binding = 2) uniform texture2D u_inputRt;
 layout(set = 0, binding = 3) uniform texture2D u_historyRt;
 layout(set = 0, binding = 4) uniform texture2D u_motionVectorsTex;
-layout(set = 0, binding = 5) writeonly uniform image2D u_outImg;
-layout(set = 0, binding = 6) writeonly uniform image2D u_tonemappedImg;
 
 const U32 TONEMAPPING_SET = 0u;
-const U32 TONEMAPPING_BINDING = 7u;
+const U32 TONEMAPPING_BINDING = 5u;
 #include <AnKi/Shaders/TonemappingResources.glsl>
 
+#if defined(ANKI_COMPUTE_SHADER)
+layout(set = 0, binding = 6) writeonly uniform image2D u_outImg;
+layout(set = 0, binding = 7) writeonly uniform image2D u_tonemappedImg;
+
+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 Vec3 out_color;
+layout(location = 1) out Vec3 out_tonemappedColor;
+#endif
+
 #if YCBCR
 #	define sample(s, uv) rgbToYCbCr(textureLod(s, u_linearAnyClampSampler, uv, 0.0).rgb)
 #	define sampleOffset(s, uv, x, y) \
@@ -41,12 +47,17 @@ const U32 TONEMAPPING_BINDING = 7u;
 
 void main()
 {
+#if defined(ANKI_COMPUTE_SHADER)
 	if(skipOutOfBoundsInvocations(WORKGROUP_SIZE, FB_SIZE))
 	{
 		return;
 	}
 
 	const Vec2 uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(FB_SIZE);
+#else
+	const Vec2 uv = in_uv;
+#endif
+
 	const F32 depth = textureLod(u_depthRt, u_linearAnyClampSampler, uv, 0.0).r;
 
 	// Get prev uv coords
@@ -99,9 +110,12 @@ void main()
 #if YCBCR
 	outColor = yCbCrToRgb(outColor);
 #endif
-	imageStore(u_outImg, IVec2(gl_GlobalInvocationID.xy), Vec4(outColor, 0.0));
 
+#if defined(ANKI_COMPUTE_SHADER)
+	imageStore(u_outImg, IVec2(gl_GlobalInvocationID.xy), Vec4(outColor, 0.0));
 	imageStore(u_tonemappedImg, IVec2(gl_GlobalInvocationID.xy), Vec4(tonemap(outColor, u_exposureThreshold0), 0.0));
+#else
+	out_color = outColor;
+	out_tonemappedColor = tonemap(outColor, u_exposureThreshold0);
+#endif
 }
-
-#pragma anki end

+ 8 - 0
AnKi/Shaders/TemporalAACompute.ankiprog

@@ -0,0 +1,8 @@
+// Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma anki start comp
+#include <AnKi/Shaders/TemporalAA.glsl>
+#pragma anki end

+ 12 - 0
AnKi/Shaders/TemporalAARaster.ankiprog

@@ -0,0 +1,12 @@
+// Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma anki start vert
+#include <AnKi/Shaders/QuadVert.glsl>
+#pragma anki end
+
+#pragma anki start frag
+#include <AnKi/Shaders/TemporalAA.glsl>
+#pragma anki end