Browse Source

Change the values stored in the HZB buffer

Panagiotis Christopoulos Charitos 2 years ago
parent
commit
483d3b0d2d

+ 6 - 1
AnKi/Renderer/Hzb.cpp

@@ -103,7 +103,12 @@ void Hzb::populateRenderGraph(RenderingContext& ctx)
 			TextureSubresourceInfo firstMipSubresource;
 			rctx.bindImage(0, 0, m_runCtx.m_hzbRt, firstMipSubresource);
 
-			UVec4 clearColor(0u);
+			// See the comments in the class on what this -0 means
+			const F32 negativeZero = -0.0f;
+			U32 negativeZerou;
+			memcpy(&negativeZerou, &negativeZero, sizeof(U32));
+			ANKI_ASSERT(negativeZerou > 0);
+			UVec4 clearColor(negativeZerou);
 			cmdb.setPushConstants(&clearColor, sizeof(clearColor));
 
 			dispatchPPCompute(cmdb, 8, 8, m_hzbRtDescr.m_width, m_hzbRtDescr.m_height);

+ 6 - 0
AnKi/Renderer/Hzb.h

@@ -13,6 +13,12 @@ namespace anki {
 /// @{
 
 /// Hierarchical depth generator.
+///
+/// The HZB is cleared with -0.0. Then the reprojection may replace the -0.0 of some texels with something in the range of [0.0, 1.0] where 0.0 is the
+/// far and 1.0 the near. So after reprojection we have -0.0 for untouched, 1.0 for near and 0.0 for far. We do this because reprojection will use
+/// atomic min on integers and -0.0 > 1.0 > 0.0 if seen as U32. Downscaling also uses min becase we want the farthest value. When testing against the
+/// HZB we only need to bring depth back to normal which is 0.0 for near and 1.0 for far. So it's a plain 1.0-x. So far becomes 1.0, near is 0.0 and
+/// untouched becomes 1.0 which transaltes to far and it's what we want.
 class Hzb : public RendererObject
 {
 public:

+ 1 - 1
AnKi/Shaders/GpuVisibility.ankiprog

@@ -113,7 +113,7 @@
 	depths[2] = asfloat(g_hzbTex.SampleLevel(g_nearestAnyClampSampler, Vec2(minUv.x, maxUv.y), mip));
 	depths[3] = asfloat(g_hzbTex.SampleLevel(g_nearestAnyClampSampler, Vec2(maxUv.x, minUv.y), mip));
 
-	const F32 maxDepth = max(depths[0], max(depths[1], max(depths[2], depths[3])));
+	const F32 maxDepth = 1.0 - min(depths[0], min(depths[1], min(depths[2], depths[3])));
 
 	if(aabbMinDepth > maxDepth)
 	{

+ 2 - 2
AnKi/Shaders/HzbGenPyramid.ankiprog

@@ -79,8 +79,8 @@ void SpdStoreIntermediate(AU1 x, AU1 y, AF4 value)
 
 AF4 SpdReduce4(AF4 v0, AF4 v1, AF4 v2, AF4 v3)
 {
-	const F32 maxDepth = max(v0.x, max(v1.x, max(v2.x, v3.x)));
-	return AF4(maxDepth, 0.0, 0.0, 0.0);
+	const F32 minValue = min(v0.x, min(v1.x, min(v2.x, v3.x)));
+	return AF4(minValue, 0.0, 0.0, 0.0);
 }
 
 #include <ThirdParty/FidelityFX/ffx_spd.h>

+ 2 - 1
AnKi/Shaders/HzbReprojection.ankiprog

@@ -44,7 +44,8 @@
 	Vec2 texCoordsf = newUv * hzbTexSize;
 	if(all(texCoordsf >= Vec2(0.0f, 0.0f)) && all(texCoordsf < hzbTexSize))
 	{
-		InterlockedMax(g_hzbUavTex[IVec2(texCoordsf)], asuint(depth));
+		// See the C++ code what that 1-depth means
+		InterlockedMin(g_hzbUavTex[IVec2(texCoordsf)], asuint(1.0 - depth));
 	}
 
 	// Now do the same for the shadow cascades