Browse Source

Add lod bias and sharpening to FSR

Panagiotis Christopoulos Charitos 4 years ago
parent
commit
174eaf7fd9

+ 4 - 3
AnKi/Gr/Sampler.h

@@ -17,8 +17,9 @@ namespace anki
 class alignas(4) SamplerInitInfo : public GrBaseInitInfo
 {
 public:
-	F32 m_minLod = -1000.0;
-	F32 m_maxLod = 1000.0;
+	F32 m_minLod = -1000.0f;
+	F32 m_maxLod = 1000.0f;
+	F32 m_lodBias = 0.0f;
 	SamplingFilter m_minMagFilter = SamplingFilter::NEAREST;
 	SamplingFilter m_mipmapFilter = SamplingFilter::BASE;
 	CompareOperation m_compareOperation = CompareOperation::ALWAYS;
@@ -39,7 +40,7 @@ public:
 		const U8* last = reinterpret_cast<const U8*>(&m_addressing) + sizeof(m_addressing);
 		const U32 size = U32(last - first);
 		ANKI_ASSERT(size
-					== sizeof(F32) * 2 + sizeof(SamplingFilter) * 2 + sizeof(CompareOperation) + sizeof(I8)
+					== sizeof(F32) * 3 + sizeof(SamplingFilter) * 2 + sizeof(CompareOperation) + sizeof(I8)
 						   + sizeof(SamplingAddressing));
 		return anki::computeHash(first, size);
 	}

+ 1 - 1
AnKi/Gr/Vulkan/SamplerFactory.cpp

@@ -62,7 +62,7 @@ Error MicroSampler::init(const SamplerInitInfo& inf)
 		ANKI_ASSERT(0);
 	}
 
-	ci.mipLodBias = 0.0;
+	ci.mipLodBias = inf.m_lodBias;
 
 	if(inf.m_anisotropyLevel > 0)
 	{

+ 1 - 0
AnKi/Renderer/ConfigDefs.h

@@ -57,3 +57,4 @@ ANKI_CONFIG_OPTION(r_rtShadowsSvgfAtrousPassCount, 3, 1, 20)
 ANKI_CONFIG_OPTION(r_rtShadowsRaysPerPixel, 1, 1, 8)
 
 ANKI_CONFIG_OPTION(r_fsr, 1, 0, 1)
+ANKI_CONFIG_OPTION(r_sharpen, 1, 0, 1)

+ 1 - 1
AnKi/Renderer/ForwardShading.cpp

@@ -55,7 +55,7 @@ void ForwardShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgr
 		// Start drawing
 		m_r->getSceneDrawer().drawRange(Pass::FS, ctx.m_matrices.m_view, ctx.m_matrices.m_viewProjectionJitter,
 										ctx.m_prevMatrices.m_viewProjectionJitter, cmdb,
-										m_r->getSamplers().m_trilinearRepeatAniso,
+										m_r->getSamplers().m_trilinearRepeatAnisoResolutionScalingBias,
 										ctx.m_renderQueue->m_forwardShadingRenderables.getBegin() + start,
 										ctx.m_renderQueue->m_forwardShadingRenderables.getBegin() + end);
 

+ 2 - 2
AnKi/Renderer/GBuffer.cpp

@@ -116,7 +116,7 @@ void GBuffer::runInThread(const RenderingContext& ctx, RenderPassWorkContext& rg
 		ANKI_ASSERT(earlyZStart < earlyZEnd && earlyZEnd <= I32(earlyZCount));
 		m_r->getSceneDrawer().drawRange(Pass::EZ, ctx.m_matrices.m_view, ctx.m_matrices.m_viewProjectionJitter,
 										ctx.m_matrices.m_jitter * ctx.m_prevMatrices.m_viewProjection, cmdb,
-										m_r->getSamplers().m_trilinearRepeatAniso,
+										m_r->getSamplers().m_trilinearRepeatAnisoResolutionScalingBias,
 										ctx.m_renderQueue->m_earlyZRenderables.getBegin() + earlyZStart,
 										ctx.m_renderQueue->m_earlyZRenderables.getBegin() + earlyZEnd);
 
@@ -138,7 +138,7 @@ void GBuffer::runInThread(const RenderingContext& ctx, RenderPassWorkContext& rg
 		ANKI_ASSERT(colorStart < colorEnd && colorEnd <= I32(ctx.m_renderQueue->m_renderables.getSize()));
 		m_r->getSceneDrawer().drawRange(Pass::GB, ctx.m_matrices.m_view, ctx.m_matrices.m_viewProjectionJitter,
 										ctx.m_matrices.m_jitter * ctx.m_prevMatrices.m_viewProjection, cmdb,
-										m_r->getSamplers().m_trilinearRepeatAniso,
+										m_r->getSamplers().m_trilinearRepeatAnisoResolutionScalingBias,
 										ctx.m_renderQueue->m_renderables.getBegin() + colorStart,
 										ctx.m_renderQueue->m_renderables.getBegin() + colorEnd);
 	}

+ 4 - 0
AnKi/Renderer/Renderer.cpp

@@ -239,6 +239,10 @@ Error Renderer::initInternal(const ConfigSet& config)
 
 		sinit.m_anisotropyLevel = U8(config.getNumberU32("r_textureAnisotropy"));
 		m_samplers.m_trilinearRepeatAniso = m_gr->newSampler(sinit);
+
+		const F32 scalingMipBias = log2(F32(m_internalResolution.x()) / F32(m_postProcessResolution.x()));
+		sinit.m_lodBias = scalingMipBias;
+		m_samplers.m_trilinearRepeatAnisoResolutionScalingBias = m_gr->newSampler(sinit);
 	}
 
 	initJitteredMats();

+ 1 - 0
AnKi/Renderer/Renderer.h

@@ -33,6 +33,7 @@ public:
 	SamplerPtr m_trilinearClamp;
 	SamplerPtr m_trilinearRepeat;
 	SamplerPtr m_trilinearRepeatAniso;
+	SamplerPtr m_trilinearRepeatAnisoResolutionScalingBias;
 };
 
 /// Offscreen renderer.

+ 92 - 17
AnKi/Renderer/Scale.cpp

@@ -29,8 +29,9 @@ Scale::~Scale()
 
 Error Scale::init(const ConfigSet& cfg)
 {
-	const Bool needsScale = m_r->getPostProcessResolution() != m_r->getInternalResolution();
-	if(!needsScale)
+	const Bool needsScaling = m_r->getPostProcessResolution() != m_r->getInternalResolution();
+	const Bool needsSharpening = cfg.getBool("r_sharpen");
+	if(!needsScaling && !needsSharpening)
 	{
 		return Error::NONE;
 	}
@@ -40,11 +41,33 @@ Error Scale::init(const ConfigSet& cfg)
 	m_fsr = cfg.getBool("r_fsr");
 
 	// Program
-	ANKI_CHECK(
-		getResourceManager().loadResource((m_fsr) ? "Shaders/Fsr.ankiprog" : "Shaders/BlitCompute.ankiprog", m_prog));
-	const ShaderProgramResourceVariant* variant;
-	m_prog->getOrCreateVariant(variant);
-	m_grProg = variant->getProgram();
+	if(needsScaling)
+	{
+		ANKI_CHECK(getResourceManager().loadResource((m_fsr) ? "Shaders/Fsr.ankiprog" : "Shaders/BlitCompute.ankiprog",
+													 m_scaleProg));
+		const ShaderProgramResourceVariant* variant;
+		if(m_fsr)
+		{
+			ShaderProgramResourceVariantInitInfo variantInitInfo(m_scaleProg);
+			variantInitInfo.addMutation("SHARPEN", 0);
+			m_scaleProg->getOrCreateVariant(variantInitInfo, variant);
+		}
+		else
+		{
+			m_scaleProg->getOrCreateVariant(variant);
+		}
+		m_scaleGrProg = variant->getProgram();
+	}
+
+	if(needsSharpening)
+	{
+		ANKI_CHECK(getResourceManager().loadResource("Shaders/Fsr.ankiprog", m_sharpenProg));
+		ShaderProgramResourceVariantInitInfo variantInitInfo(m_sharpenProg);
+		variantInitInfo.addMutation("SHARPEN", 1);
+		const ShaderProgramResourceVariant* variant;
+		m_sharpenProg->getOrCreateVariant(variantInitInfo, variant);
+		m_sharpenGrProg = variant->getProgram();
+	}
 
 	// The RT desc
 	m_rtDesc =
@@ -57,40 +80,62 @@ Error Scale::init(const ConfigSet& cfg)
 
 void Scale::populateRenderGraph(RenderingContext& ctx)
 {
-	const Bool needsScale = m_grProg.isCreated();
-	if(!needsScale)
+	if(!doScaling() && !doSharpening())
 	{
-		m_runCtx.m_upscaledRt = m_r->getTemporalAA().getTonemappedRt();
+		m_runCtx.m_scaledRt = m_r->getTemporalAA().getTonemappedRt();
+		m_runCtx.m_sharpenedRt = m_r->getTemporalAA().getTonemappedRt();
+		return;
 	}
-	else
+
+	if(doScaling())
 	{
 		RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
 
-		m_runCtx.m_upscaledRt = rgraph.newRenderTarget(m_rtDesc);
+		m_runCtx.m_scaledRt = rgraph.newRenderTarget(m_rtDesc);
 
 		ComputeRenderPassDescription& pass = ctx.m_renderGraphDescr.newComputeRenderPass("Scale");
 		pass.newDependency(
 			RenderPassDependency(m_r->getTemporalAA().getTonemappedRt(), TextureUsageBit::SAMPLED_COMPUTE));
-		pass.newDependency(RenderPassDependency(m_runCtx.m_upscaledRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
+		pass.newDependency(RenderPassDependency(m_runCtx.m_scaledRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
+
+		pass.setWork(
+			[](RenderPassWorkContext& rgraphCtx) {
+				Scale* const self = static_cast<Scale*>(rgraphCtx.m_userData);
+				self->runScaling(rgraphCtx);
+			},
+			this, 0);
+	}
+
+	if(doSharpening())
+	{
+		RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
+
+		m_runCtx.m_sharpenedRt = rgraph.newRenderTarget(m_rtDesc);
+
+		ComputeRenderPassDescription& pass = ctx.m_renderGraphDescr.newComputeRenderPass("Sharpen");
+		pass.newDependency(
+			RenderPassDependency((!doScaling()) ? m_r->getTemporalAA().getTonemappedRt() : m_runCtx.m_scaledRt,
+								 TextureUsageBit::SAMPLED_COMPUTE));
+		pass.newDependency(RenderPassDependency(m_runCtx.m_sharpenedRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
 
 		pass.setWork(
 			[](RenderPassWorkContext& rgraphCtx) {
 				Scale* const self = static_cast<Scale*>(rgraphCtx.m_userData);
-				self->run(rgraphCtx);
+				self->runSharpening(rgraphCtx);
 			},
 			this, 0);
 	}
 }
 
-void Scale::run(RenderPassWorkContext& rgraphCtx)
+void Scale::runScaling(RenderPassWorkContext& rgraphCtx)
 {
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
-	cmdb->bindShaderProgram(m_grProg);
+	cmdb->bindShaderProgram(m_scaleGrProg);
 
 	cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
 	rgraphCtx.bindColorTexture(0, 1, m_r->getTemporalAA().getTonemappedRt());
-	rgraphCtx.bindImage(0, 2, m_runCtx.m_upscaledRt);
+	rgraphCtx.bindImage(0, 2, m_runCtx.m_scaledRt);
 
 	if(m_fsr)
 	{
@@ -131,4 +176,34 @@ void Scale::run(RenderPassWorkContext& rgraphCtx)
 	dispatchPPCompute(cmdb, 8, 8, m_r->getPostProcessResolution().x(), m_r->getPostProcessResolution().y());
 }
 
+void Scale::runSharpening(RenderPassWorkContext& rgraphCtx)
+{
+	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
+
+	cmdb->bindShaderProgram(m_sharpenGrProg);
+
+	cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
+	rgraphCtx.bindColorTexture(0, 1, (!doScaling()) ? m_r->getTemporalAA().getTonemappedRt() : m_runCtx.m_scaledRt);
+	rgraphCtx.bindImage(0, 2, m_runCtx.m_sharpenedRt);
+
+	class
+	{
+	public:
+		UVec4 m_fsrConsts0;
+		UVec4 m_fsrConsts1;
+		UVec4 m_fsrConsts2;
+		UVec4 m_fsrConsts3;
+		UVec2 m_viewportSize;
+		UVec2 m_padding;
+	} pc;
+
+	FsrRcasCon(&pc.m_fsrConsts0[0], 0.2f);
+
+	pc.m_viewportSize = m_r->getPostProcessResolution();
+
+	cmdb->setPushConstants(&pc, sizeof(pc));
+
+	dispatchPPCompute(cmdb, 8, 8, m_r->getPostProcessResolution().x(), m_r->getPostProcessResolution().y());
+}
+
 } // end namespace anki

+ 19 - 5
AnKi/Renderer/Scale.h

@@ -30,12 +30,14 @@ public:
 
 	RenderTargetHandle getRt() const
 	{
-		return m_runCtx.m_upscaledRt;
+		return (doSharpening()) ? m_runCtx.m_sharpenedRt : m_runCtx.m_scaledRt;
 	}
 
 private:
-	ShaderProgramResourcePtr m_prog;
-	ShaderProgramPtr m_grProg;
+	ShaderProgramResourcePtr m_scaleProg;
+	ShaderProgramPtr m_scaleGrProg;
+	ShaderProgramResourcePtr m_sharpenProg;
+	ShaderProgramPtr m_sharpenGrProg;
 
 	RenderTargetDescription m_rtDesc;
 
@@ -44,10 +46,22 @@ private:
 	class
 	{
 	public:
-		RenderTargetHandle m_upscaledRt;
+		RenderTargetHandle m_scaledRt;
+		RenderTargetHandle m_sharpenedRt;
 	} m_runCtx;
 
-	void run(RenderPassWorkContext& rgraphCtx);
+	void runScaling(RenderPassWorkContext& rgraphCtx);
+	void runSharpening(RenderPassWorkContext& rgraphCtx);
+
+	Bool doSharpening() const
+	{
+		return m_sharpenProg.isCreated();
+	}
+
+	Bool doScaling() const
+	{
+		return m_scaleProg.isCreated();
+	}
 };
 /// @}
 

+ 22 - 1
AnKi/Shaders/Fsr.ankiprog

@@ -3,6 +3,8 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
+#pragma anki mutator SHARPEN 0 1
+
 #pragma anki start comp
 
 #include <AnKi/Shaders/Functions.glsl>
@@ -26,7 +28,21 @@ layout(push_constant, std430) uniform b_pc
 #define A_GLSL 1
 #define A_HALF 1
 #include <ThirdParty/Fsr/ffx_a.h>
-#define FSR_EASU_H 1
+
+#if SHARPEN
+#	define FSR_RCAS_H 1
+
+AH4 FsrRcasLoadH(ASW2 p)
+{
+	return AH4(texelFetch(sampler2D(u_tex, u_linearAnyClampSampler), ASU2(p), 0));
+}
+
+void FsrRcasInputH(inout AH1 r, inout AH1 g, inout AH1 b)
+{
+}
+
+#else // !SHARPEN
+#	define FSR_EASU_H 1
 
 AH4 FsrEasuRH(AF2 p)
 {
@@ -42,6 +58,7 @@ AH4 FsrEasuBH(AF2 p)
 {
 	return AH4(textureGather(sampler2D(u_tex, u_linearAnyClampSampler), p, 2));
 }
+#endif
 
 #include <ThirdParty/Fsr/ffx_fsr1.h>
 // FSR end
@@ -56,7 +73,11 @@ void main()
 	}
 
 	HVec3 color;
+#if SHARPEN
+	FsrRcasH(color.r, color.g, color.b, gl_GlobalInvocationID.xy, u_fsrConsts0);
+#else
 	FsrEasuH(color, gl_GlobalInvocationID.xy, u_fsrConsts0, u_fsrConsts1, u_fsrConsts2, u_fsrConsts3);
+#endif
 
 	imageStore(u_outImg, IVec2(gl_GlobalInvocationID.xy), Vec4(color, 0.0));
 }