Browse Source

Add bilateral upscaling

Panagiotis Christopoulos Charitos 4 years ago
parent
commit
8084d26e57

+ 1 - 3
AnKi/Renderer/DepthDownscale.cpp

@@ -32,9 +32,7 @@ Error DepthDownscale::initInternal(const ConfigSet&)
 
 	// Create RT descr
 	TextureInitInfo texInit = m_r->create2DRenderTargetInitInfo(
-		width, height, Format::R32_SFLOAT,
-		TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_COMPUTE | TextureUsageBit::IMAGE_COMPUTE_WRITE,
-		"HiZ");
+		width, height, Format::R32_SFLOAT, TextureUsageBit::ALL_SAMPLED | TextureUsageBit::IMAGE_COMPUTE_WRITE, "HiZ");
 	texInit.m_mipmapCount = U8(m_mipCount);
 	texInit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
 	m_hizTex = m_r->createAndClearRenderTarget(texInit);

+ 50 - 6
AnKi/Renderer/RtShadows.cpp

@@ -30,7 +30,7 @@ Error RtShadows::init(const ConfigSet& cfg)
 		ANKI_R_LOGE("Failed to initialize ray traced shadows");
 	}
 
-	return Error::NONE;
+	return err;
 }
 
 Error RtShadows::initInternal(const ConfigSet& cfg)
@@ -103,6 +103,17 @@ Error RtShadows::initInternal(const ConfigSet& cfg)
 		m_svgfAtrousLastPassGrProg = variant->getProgram();
 	}
 
+	// Upscale program
+	{
+		ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsUpscale.ankiprog", m_upscaleProg));
+		ShaderProgramResourceVariantInitInfo variantInitInfo(m_upscaleProg);
+		variantInitInfo.addConstant("OUT_IMAGE_SIZE", UVec2(m_r->getWidth(), m_r->getHeight()));
+
+		const ShaderProgramResourceVariant* variant;
+		m_upscaleProg->getOrCreateVariant(variantInitInfo, variant);
+		m_upscaleGrProg = variant->getProgram();
+	}
+
 	// Debug program
 	ANKI_CHECK(getResourceManager().loadResource("Shaders/RtShadowsVisualizeRenderTarget.ankiprog",
 												 m_visualizeRenderTargetsProg));
@@ -110,7 +121,7 @@ Error RtShadows::initInternal(const ConfigSet& cfg)
 	// Shadow RT
 	{
 		TextureInitInfo texinit =
-			m_r->create2DRenderTargetInitInfo(m_r->getWidth() / 2, m_r->getHeight() / 2, Format::R32G32_UINT,
+			m_r->create2DRenderTargetInitInfo(m_r->getWidth(), m_r->getHeight(), Format::R32G32_UINT,
 											  TextureUsageBit::ALL_SAMPLED | TextureUsageBit::IMAGE_TRACE_RAYS_WRITE
 												  | TextureUsageBit::IMAGE_COMPUTE_WRITE,
 											  "RtShadows");
@@ -290,7 +301,8 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 		rpass.newDependency(RenderPassDependency(m_runCtx.m_currentMomentsRt, TextureUsageBit::SAMPLED_COMPUTE));
 		rpass.newDependency(RenderPassDependency(m_runCtx.m_currentHistoryLengthRt, TextureUsageBit::SAMPLED_COMPUTE));
 
-		rpass.newDependency(RenderPassDependency(m_runCtx.m_historyAndFinalRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
+		rpass.newDependency(
+			RenderPassDependency(m_runCtx.m_intermediateShadowsRts[0], TextureUsageBit::IMAGE_COMPUTE_WRITE));
 	}
 
 	// Variance calculation pass
@@ -355,6 +367,23 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 		}
 	}
 
+	// Upscale
+	{
+		ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("RtShadows Upscale");
+		rpass.setWork(
+			[](RenderPassWorkContext& rgraphCtx) {
+				static_cast<RtShadows*>(rgraphCtx.m_userData)->runUpscale(rgraphCtx);
+			},
+			this, 0);
+
+		rpass.newDependency(
+			RenderPassDependency(m_runCtx.m_intermediateShadowsRts[0], TextureUsageBit::SAMPLED_COMPUTE));
+		rpass.newDependency(RenderPassDependency(m_r->getGBuffer().getDepthRt(), TextureUsageBit::SAMPLED_COMPUTE));
+		rpass.newDependency(depthDependency);
+
+		rpass.newDependency(RenderPassDependency(m_runCtx.m_historyAndFinalRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
+	}
+
 	// Find out the lights that will take part in RT pass
 	{
 		RenderQueue& rqueue = *m_runCtx.m_ctx->m_renderQueue;
@@ -484,9 +513,7 @@ void RtShadows::runDenoise(RenderPassWorkContext& rgraphCtx)
 	rgraphCtx.bindColorTexture(0, 5, m_runCtx.m_currentMomentsRt);
 	rgraphCtx.bindColorTexture(0, 6, m_runCtx.m_currentHistoryLengthRt);
 
-	rgraphCtx.bindImage(0, 7,
-						(m_runCtx.m_denoiseOrientation == 0) ? m_runCtx.m_intermediateShadowsRts[1]
-															 : m_runCtx.m_historyAndFinalRt);
+	rgraphCtx.bindImage(0, 7, m_runCtx.m_intermediateShadowsRts[!m_runCtx.m_denoiseOrientation]);
 
 	RtShadowsDenoiseUniforms unis;
 	unis.invViewProjMat = m_runCtx.m_ctx->m_matrices.m_invertedViewProjectionJitter;
@@ -567,6 +594,23 @@ void RtShadows::runSvgfAtrous(RenderPassWorkContext& rgraphCtx)
 	++m_runCtx.m_atrousPassIdx;
 }
 
+void RtShadows::runUpscale(RenderPassWorkContext& rgraphCtx)
+{
+	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
+
+	cmdb->bindShaderProgram(m_upscaleGrProg);
+
+	cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);
+	cmdb->bindSampler(0, 1, m_r->getSamplers().m_trilinearClamp);
+
+	rgraphCtx.bindColorTexture(0, 2, m_runCtx.m_intermediateShadowsRts[0]);
+	rgraphCtx.bindImage(0, 3, m_runCtx.m_historyAndFinalRt);
+	rgraphCtx.bindColorTexture(0, 4, m_r->getDepthDownscale().getHiZRt());
+	rgraphCtx.bindTexture(0, 5, m_r->getGBuffer().getDepthRt(), TextureSubresourceInfo(DepthStencilAspectBit::DEPTH));
+
+	dispatchPPCompute(cmdb, 8, 8, m_r->getWidth(), m_r->getHeight());
+}
+
 void RtShadows::buildSbt()
 {
 	// Get some things

+ 4 - 0
AnKi/Renderer/RtShadows.h

@@ -82,6 +82,9 @@ public:
 	ShaderProgramPtr m_svgfAtrousGrProg;
 	ShaderProgramPtr m_svgfAtrousLastPassGrProg;
 
+	ShaderProgramResourcePtr m_upscaleProg;
+	ShaderProgramPtr m_upscaleGrProg;
+
 	ShaderProgramResourcePtr m_visualizeRenderTargetsProg;
 	/// @}
 
@@ -125,6 +128,7 @@ public:
 	void runDenoise(RenderPassWorkContext& rgraphCtx);
 	void runSvgfVariance(RenderPassWorkContext& rgraphCtx);
 	void runSvgfAtrous(RenderPassWorkContext& rgraphCtx);
+	void runUpscale(RenderPassWorkContext& rgraphCtx);
 
 	void buildSbt();
 

+ 14 - 1
AnKi/Shaders/Functions.glsl

@@ -562,4 +562,17 @@ F32 gaussianWeight(F32 s, F32 x)
 	F32 p = 1.0 / (s * sqrt(2.0 * PI));
 	p *= exp((x * x) / (-2.0 * s * s));
 	return p;
-}
+}
+
+Vec4 bilinearFiltering(texture2D tex, sampler nearestSampler, Vec2 uv, F32 lod, Vec2 textureSize)
+{
+	const Vec2 texelSize = 1.0 / textureSize;
+	const Vec2 unnormTexCoord = (uv * textureSize) - 0.5;
+	const Vec2 f = fract(unnormTexCoord);
+	const Vec2 snapTexCoord = (floor(unnormTexCoord) + 0.5) / textureSize;
+	const Vec4 s1 = textureLod(tex, nearestSampler, uv, lod);
+	const Vec4 s2 = textureLod(tex, nearestSampler, uv + Vec2(texelSize.x, 0.0), lod);
+	const Vec4 s3 = textureLod(tex, nearestSampler, uv + Vec2(0.0, texelSize.y), lod);
+	const Vec4 s4 = textureLod(tex, nearestSampler, uv + texelSize, lod);
+	return mix(mix(s1, s2, f.x), mix(s3, s4, f.x), f.y);
+}

+ 1 - 1
AnKi/Shaders/RtShadowsDenoise.ankiprog

@@ -114,7 +114,7 @@ void main()
 	sampleCount = sampleCount / 2;
 
 	// Sample
-	F32 weight = 1.0;
+	F32 weight = 1.0; // TODO fix that
 
 	for(I32 i = -I32(sampleCount); i < I32(sampleCount); ++i)
 	{

+ 43 - 5
AnKi/Shaders/RtShadowsUpscale.ankiprog

@@ -3,10 +3,12 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#pragma anki mutator QUALITY 0 1
-
 #pragma anki start comp
 
+#include <AnKi/Shaders/RtShadows.glsl>
+#include <AnKi/Shaders/Functions.glsl>
+#include <AnKi/Shaders/BilateralFilter.glsl>
+
 ANKI_SPECIALIZATION_CONSTANT_UVEC2(OUT_IMAGE_SIZE, 0, UVec2(1));
 
 const UVec2 WORKGROUP_SIZE = UVec2(8u, 8u);
@@ -26,9 +28,45 @@ void main()
 		return;
 	}
 
-#if QUALITY == 0
-#else
-#endif
+	const Vec2 uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(OUT_IMAGE_SIZE);
+
+	// Reference
+	const F32 depthCenter = textureLod(u_fullDepthTex, u_linearAnyClampSampler, uv, 0.0).x;
+
+	F32 sumShadowLayers[MAX_RT_SHADOW_LAYERS];
+	zeroRtShadowLayers(sumShadowLayers);
+
+	// Do a bilateral upscale
+	const Vec2 texelSize = 1.0 / Vec2(OUT_IMAGE_SIZE / 2);
+	const I32 radius = 1;
+	F32 sumWeight = EPSILON;
+	for(I32 x = -radius; x <= radius; ++x)
+	{
+		for(I32 y = -radius; y <= radius; ++y)
+		{
+			const Vec2 sampleUv = uv + Vec2(x, y) * texelSize;
+			const F32 depthTap = textureLod(u_quarterDepthTex, u_linearAnyClampSampler, sampleUv, 0.0).x;
+
+			const F32 w = calculateBilateralWeightDepth(depthCenter, depthTap, 1.0);
+
+			F32 shadowLayers[MAX_RT_SHADOW_LAYERS];
+			unpackRtShadows(textureLod(u_quarterShadowsTex, u_nearestAnyClampSampler, sampleUv, 0.0), shadowLayers);
+
+			for(U32 i = 0; i < MAX_RT_SHADOW_LAYERS; ++i)
+			{
+				sumShadowLayers[i] += shadowLayers[i] * w;
+			}
+
+			sumWeight += w;
+		}
+	}
+
+	for(U32 i = 0; i < MAX_RT_SHADOW_LAYERS; ++i)
+	{
+		sumShadowLayers[i] /= sumWeight;
+	}
+
+	imageStore(u_fullShadowsImage, IVec2(gl_GlobalInvocationID.xy), packRtShadows(sumShadowLayers));
 }
 
 #pragma anki end