Browse Source

Add more code in RT clipmaps

Panagiotis Christopoulos Charitos 9 months ago
parent
commit
8702c6c8d3

+ 86 - 5
AnKi/Renderer/IndirectDiffuseClipmaps.cpp

@@ -3,19 +3,100 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#include <AnKi/Renderer/IndirectDiffuseProbes2.h>
+#include <AnKi/Renderer/IndirectDiffuseClipmaps.h>
 #include <AnKi/Renderer/Renderer.h>
-#include <AnKi/Renderer/PrimaryNonRenderableVisibility.h>
+#include <AnKi/Renderer/GBuffer.h>
 #include <AnKi/Util/Tracer.h>
-#include <AnKi/Scene/Components/GlobalIlluminationProbeComponent.h>
 
 namespace anki {
 
-void IndirectDiffuseProbes2::populateRenderGraph(RenderingContext& ctx)
+Error IndirectDiffuseClipmaps::init()
+{
+	m_tmpRtDesc = getRenderer().create2DRenderTargetDescription(getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y(),
+																Format::kR8G8B8A8_Unorm, "Test");
+	m_tmpRtDesc.bake();
+
+	const Bool supports3Comp = GrManager::getSingleton().getDeviceCapabilities().m_unalignedBbpTextureFormats;
+	TextureInitInfo volumeInit = getRenderer().create2DRenderTargetInitInfo(
+		g_indirectDiffuseClipmap0ProbesPerDimCVar, g_indirectDiffuseClipmap0ProbesPerDimCVar,
+		(supports3Comp) ? Format::kR16G16B16_Sfloat : Format::kR16G16B16A16_Sfloat, TextureUsageBit::kAllShaderResource, "IndirectDiffuseClipmap #1");
+	volumeInit.m_depth = g_indirectDiffuseClipmap0ProbesPerDimCVar;
+	volumeInit.m_type = TextureType::k3D;
+	m_clipmapLevelTextures[0] = getRenderer().createAndClearRenderTarget(volumeInit, TextureUsageBit::kSrvCompute);
+
+	ANKI_CHECK(loadShaderProgram("ShaderBinaries/IndirectDiffuseClipmaps.ankiprogbin", {}, m_tmpProg, m_tmpGrProg, "Test"));
+	ANKI_CHECK(loadShaderProgram("ShaderBinaries/IndirectDiffuseClipmaps.ankiprogbin", {}, m_tmpProg, m_tmpGrProg2, "InitTex"));
+
+	return Error::kNone;
+}
+
+void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 {
 	ANKI_TRACE_SCOPED_EVENT(IndirectDiffuse);
 
-	m_runCtx = {};
+	RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
+
+	RenderTargetHandle volumeRt;
+	if(!m_clipmapsImportedOnce)
+	{
+		volumeRt = rgraph.importRenderTarget(m_clipmapLevelTextures[0].get(), TextureUsageBit::kSrvCompute);
+	}
+	else
+	{
+		m_clipmapsImportedOnce = true;
+		volumeRt = rgraph.importRenderTarget(m_clipmapLevelTextures[0].get());
+	}
+
+	m_runCtx.m_tmpRt = rgraph.newRenderTarget(m_tmpRtDesc);
+
+	{
+		NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("IndirectDiffuseClipmaps clear");
+
+		pass.newTextureDependency(volumeRt, TextureUsageBit::kUavCompute);
+
+		pass.setWork([this, volumeRt, &ctx](RenderPassWorkContext& rgraphCtx) {
+			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
+
+			cmdb.bindShaderProgram(m_tmpGrProg2.get());
+
+			const Vec4 consts(g_indirectDiffuseClipmap0SizeCVar);
+			cmdb.setFastConstants(&consts, sizeof(consts));
+
+			rgraphCtx.bindUav(0, 0, volumeRt);
+
+			cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
+
+			const U32 probeCountPerDim = m_clipmapLevelTextures[0]->getWidth();
+			dispatchPPCompute(cmdb, 4, 4, 4, probeCountPerDim, probeCountPerDim, probeCountPerDim);
+		});
+	}
+
+	{
+		NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("IndirectDiffuseClipmaps test");
+
+		pass.newTextureDependency(volumeRt, TextureUsageBit::kSrvCompute);
+		pass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
+		pass.newTextureDependency(m_runCtx.m_tmpRt, TextureUsageBit::kUavCompute);
+
+		pass.setWork([this, volumeRt, &ctx](RenderPassWorkContext& rgraphCtx) {
+			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
+
+			cmdb.bindShaderProgram(m_tmpGrProg.get());
+
+			const Vec4 consts(g_indirectDiffuseClipmap0SizeCVar);
+			cmdb.setFastConstants(&consts, sizeof(consts));
+
+			rgraphCtx.bindSrv(0, 0, volumeRt);
+			rgraphCtx.bindSrv(1, 0, getRenderer().getGBuffer().getDepthRt());
+			rgraphCtx.bindUav(0, 0, m_runCtx.m_tmpRt);
+
+			cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
+
+			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
+
+			dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
+		});
+	}
 }
 
 } // end namespace anki

+ 30 - 4
AnKi/Renderer/IndirectDiffuseClipmaps.h

@@ -14,22 +14,48 @@ namespace anki {
 /// @addtogroup renderer
 /// @{
 
-inline NumericCVar<F32> g_indirectDiffuseClipmap0MetersCVar("R", "IndirectDiffuseClipmap0Meters", 20.0, 10.0, 50.0, "The size of the 1st clipmap");
-inline NumericCVar<U32> g_indirectDiffuseClipmap0CellsPerCubicMeterCVar("R", "IndirectDiffuseClipmap0CellsPerCubicMeter", 1, 1, 10 * 3,
-																		"Cell count per cubic meter");
+inline BoolCVar g_rtIndirectDiffuseClipmapsCVar("R", "RtIndirectDiffuseClipmaps", false);
+inline NumericCVar<U32> g_indirectDiffuseClipmap0ProbesPerDimCVar("R", "IndirectDiffuseClipmap0ProbesPerDim", 40, 10, 50,
+																  "The cell count of each dimension of 1st clipmap");
+inline NumericCVar<F32> g_indirectDiffuseClipmap0SizeCVar("R", "IndirectDiffuseClipmap0Size", 20.0, 10.0, 100.0, "The clipmap size in meters");
 
 /// Ambient global illumination passes.
-class IndirectDiffuseProbes2 : public RendererObject
+class IndirectDiffuseClipmaps : public RendererObject
 {
 public:
+	IndirectDiffuseClipmaps()
+	{
+		registerDebugRenderTarget("IndirectDiffuseClipmapsTest");
+	}
+
 	Error init();
 
 	void populateRenderGraph(RenderingContext& ctx);
 
+	void getDebugRenderTarget([[maybe_unused]] CString rtName, Array<RenderTargetHandle, kMaxDebugRenderTargets>& handles,
+							  [[maybe_unused]] ShaderProgramPtr& optionalShaderProgram) const override
+	{
+		handles[0] = m_runCtx.m_tmpRt;
+	}
+
 private:
 	static constexpr U32 kClipmapLevelCount = 3;
 
 	Array<TexturePtr, kClipmapLevelCount> m_clipmapLevelTextures;
+
+	ShaderProgramResourcePtr m_tmpProg;
+	ShaderProgramPtr m_tmpGrProg;
+	ShaderProgramPtr m_tmpGrProg2;
+
+	RenderTargetDesc m_tmpRtDesc;
+
+	Bool m_clipmapsImportedOnce = false;
+
+	class
+	{
+	public:
+		RenderTargetHandle m_tmpRt;
+	} m_runCtx;
 };
 /// @}
 

+ 5 - 0
AnKi/Renderer/Renderer.cpp

@@ -49,6 +49,7 @@
 #include <AnKi/Renderer/RtMaterialFetchDbg.h>
 #include <AnKi/Renderer/Reflections.h>
 #include <AnKi/Renderer/IndirectDiffuse.h>
+#include <AnKi/Renderer/IndirectDiffuseClipmaps.h>
 #include <AnKi/Renderer/Utils/Drawer.h>
 #include <AnKi/Renderer/Utils/GpuVisibility.h>
 #include <AnKi/Renderer/Utils/MipmapGenerator.h>
@@ -291,6 +292,10 @@ Error Renderer::populateRenderGraph(RenderingContext& ctx)
 	m_clusterBinning2->populateRenderGraph(ctx);
 	m_generatedSky->populateRenderGraph(ctx);
 	m_indirectDiffuseProbes->populateRenderGraph(ctx);
+	if(m_indirectDiffuseClipmaps)
+	{
+		m_indirectDiffuseClipmaps->populateRenderGraph(ctx);
+	}
 	m_probeReflections->populateRenderGraph(ctx);
 	m_volumetricLightingAccumulation->populateRenderGraph(ctx);
 	m_motionVectors->populateRenderGraph(ctx);

+ 4 - 1
AnKi/Renderer/RendererObject.def.h

@@ -22,11 +22,14 @@ ANKI_RENDERER_OBJECT_DEF(TemporalAA, temporalAA, 1)
 ANKI_RENDERER_OBJECT_DEF(UiStage, uiStage, 1)
 ANKI_RENDERER_OBJECT_DEF(VolumetricLightingAccumulation, volumetricLightingAccumulation, 1)
 ANKI_RENDERER_OBJECT_DEF(IndirectDiffuseProbes, indirectDiffuseProbes, 1)
+ANKI_RENDERER_OBJECT_DEF(IndirectDiffuseClipmaps, indirectDiffuseClipmaps,
+						 GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled&& g_rtIndirectDiffuseClipmapsCVar)
 ANKI_RENDERER_OBJECT_DEF(ShadowmapsResolve, shadowmapsResolve, 1)
 ANKI_RENDERER_OBJECT_DEF(RtShadows, rtShadows, GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled&& g_rayTracedShadowsCVar)
 ANKI_RENDERER_OBJECT_DEF(AccelerationStructureBuilder, accelerationStructureBuilder,
 						 GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled
-							 && (g_rayTracedShadowsCVar || g_rtMaterialFetchDbgCVar || g_rtReflectionsCVar || g_rtIndirectDiffuseCVar))
+							 && (g_rayTracedShadowsCVar || g_rtMaterialFetchDbgCVar || g_rtReflectionsCVar || g_rtIndirectDiffuseCVar
+								 || g_rtIndirectDiffuseClipmapsCVar))
 ANKI_RENDERER_OBJECT_DEF(MotionVectors, motionVectors, 1)
 ANKI_RENDERER_OBJECT_DEF(TemporalUpscaler, temporalUpscaler, 1)
 ANKI_RENDERER_OBJECT_DEF(VrsSriGeneration, vrsSriGeneration, 1)

+ 123 - 0
AnKi/Shaders/IndirectDiffuseClipmaps.ankiprog

@@ -0,0 +1,123 @@
+// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma anki 16bit
+
+#pragma anki technique InitTex comp
+#pragma anki technique Test comp
+
+#include <AnKi/Shaders/Include/GpuSceneTypes.h>
+#include <AnKi/Shaders/Functions.hlsl>
+#include <AnKi/Shaders/SH.hlsl>
+#include <AnKi/Shaders/Include/MiscRendererTypes.h>
+
+struct Clipmap
+{
+	F32 m_size;
+	F32 m_padding0;
+	F32 m_padding1;
+	F32 m_padding2;
+};
+
+ANKI_FAST_CONSTANTS(Clipmap, g_clipmap)
+
+Vec3 worldPosToVolumeUvw(Vec3 worldPos, F32 clipmapSize)
+{
+	const Vec3 uvw = frac(worldPos / clipmapSize);
+	return uvw;
+}
+
+UVec3 worldPosToVolumeTexel(Vec3 worldPos, F32 clipmapSize, F32 probeCountPerDim)
+{
+	const Vec3 uvw = worldPosToVolumeUvw(worldPos, clipmapSize);
+	return uvw * probeCountPerDim;
+}
+
+void computeClipmapBounds(Vec3 cameraPos, F32 clipmapSize, out Vec3 aabbMin, out Vec3 aabbMax)
+{
+	aabbMin = round(cameraPos) - clipmapSize * 0.5;
+	aabbMax = round(cameraPos) + clipmapSize * 0.5;
+}
+
+#if NOT_ZERO(ANKI_TECHNIQUE_InitTex)
+RWTexture3D<Vec4> g_volume : register(u0);
+
+ConstantBuffer<GlobalRendererConstants> g_globalConstants : register(b0);
+
+[NumThreads(4, 4, 4)] void main(UVec3 svDispatchThreadId : SV_DispatchThreadID)
+{
+	F32 probeCountPerDim, unused0, unused1;
+	g_volume.GetDimensions(probeCountPerDim, unused0, unused1);
+
+	Vec3 clipmapAabbMin, clipmapAabbMax;
+	computeClipmapBounds(g_globalConstants.m_cameraPosition, g_clipmap.m_size, clipmapAabbMin, clipmapAabbMax);
+
+	const Vec3 prevCameraPos = g_globalConstants.m_previousMatrices.m_cameraTransform.getTranslationPart();
+	Vec3 prevClipmapAabbMin, prevClipmapAabbMax;
+	computeClipmapBounds(prevCameraPos, g_clipmap.m_size, prevClipmapAabbMin, prevClipmapAabbMax);
+
+	const F32 probeSize = g_clipmap.m_size / probeCountPerDim;
+	const Vec3 cellWorldPos = svDispatchThreadId * probeSize + probeSize * 0.5 + clipmapAabbMin;
+
+	const UVec3 probeTexelCoord = worldPosToVolumeTexel(cellWorldPos, g_clipmap.m_size, probeCountPerDim);
+
+	if(any(probeTexelCoord >= probeCountPerDim))
+	{
+		return;
+	}
+
+	Vec3 color;
+	Vec3 prev = g_volume[probeTexelCoord].xyz;
+	if(any(cellWorldPos < prevClipmapAabbMin) || any(cellWorldPos > prevClipmapAabbMax))
+	{
+		color = abs(frac(g_globalConstants.m_frame * cellWorldPos)) + 0.1;
+	}
+	else
+	{
+		color = prev;
+	}
+
+	g_volume[probeTexelCoord] = Vec4(color, 1.0);
+}
+#endif
+
+#if NOT_ZERO(ANKI_TECHNIQUE_Test)
+Texture3D<Vec4> g_volume : register(t0);
+Texture2D<Vec4> g_depthTex : register(t1);
+
+RWTexture2D<Vec4> g_outTex : register(u0);
+
+ConstantBuffer<GlobalRendererConstants> g_globalConstants : register(b0);
+
+SamplerState g_linearAnyRepeatSampler : register(s0);
+
+[NumThreads(8, 8, 1)] void main(UVec2 svDispatchThreadId : SV_DispatchThreadID)
+{
+	UVec2 viewportSize;
+	g_outTex.GetDimensions(viewportSize.x, viewportSize.y);
+
+	if(any(svDispatchThreadId >= viewportSize))
+	{
+		return;
+	}
+
+	const F32 depth = g_depthTex[svDispatchThreadId].r;
+	const Vec2 ndc = uvToNdc(Vec2(svDispatchThreadId) / Vec2(viewportSize));
+	const Vec4 worldPos4 = mul(g_globalConstants.m_matrices.m_invertedViewProjectionJitter, Vec4(ndc, depth, 1.0));
+	const Vec3 worldPos = worldPos4.xyz / worldPos4.w;
+
+	Vec3 uvw = worldPosToVolumeUvw(worldPos, g_clipmap.m_size);
+	// const Vec3 color = g_volume.SampleLevel(g_linearAnyRepeatSampler, uvw, 0.0);
+	const Vec3 color = g_volume[uvw * 40.0];
+
+	Vec3 clipMin, clipMax;
+	computeClipmapBounds(g_globalConstants.m_cameraPosition, g_clipmap.m_size, clipMin, clipMax);
+
+	if(any(worldPos > clipMax) || any(worldPos < clipMin))
+		g_outTex[svDispatchThreadId] = 0.0;
+	else
+		g_outTex[svDispatchThreadId] = Vec4(color, 1.0);
+}
+#endif

+ 6 - 0
AnKi/Shaders/Intellisense.hlsl

@@ -244,6 +244,12 @@ T round(T x);
 template<typename T>
 T ceil(T x);
 
+template<typename T>
+T frac(T x);
+
+template<typename T>
+T lerp(T x, T y, float t);
+
 // Atomics
 
 template<typename T>

+ 43 - 0
AnKi/Shaders/SH.hlsl

@@ -0,0 +1,43 @@
+// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+// Spherical Harmonics utilities
+
+#pragma once
+
+#include <AnKi/Shaders/Common.hlsl>
+
+constexpr U32 kSHL1CoefficientCount = (1 + 1) * (1 + 1);
+constexpr F32 kSHBasisL0 = 1.0 / (2.0 * sqrt(kPi));
+constexpr F32 kSHBasisL1 = sqrt(3.0) / (2.0 * sqrt(kPi));
+
+/// 2 bands, 4 coefficients per color component.
+template<typename T>
+struct SHL1
+{
+	vector<T, 3> m_c[kSHL1CoefficientCount];
+};
+
+template<typename T>
+SHL1<T> appendSH(SHL1<T> inputSH, vector<T, 3> direction, vector<T, 3> value, U32 sampleCount)
+{
+	SHL1<T> res;
+
+	// L0
+	res.m_c[0] = T(kSHBasisL0) * value;
+
+	// L1
+	res.m_c[1] = T(kSHBasisL1) * direction.y * value;
+	res.m_c[2] = T(kSHBasisL1) * direction.z * value;
+	res.m_c[3] = T(kSHBasisL1) * direction.x * value;
+
+	const T weight = T(1) / T(sampleCount);
+	[unroll] for(U32 i = 0; i < kSHL1CoefficientCount; ++i)
+	{
+		inputSH.m_c[i] += res.m_c[i] * weight;
+	}
+
+	return inputSH;
+}

+ 2 - 1
Samples/Common/SampleApp.cpp

@@ -63,7 +63,8 @@ Error SampleApp::userMainLoop(Bool& quit, Second elapsedTime)
 
 	if(in.getKey(KeyCode::kY) == 1)
 	{
-		renderer.setCurrentDebugRenderTarget((renderer.getCurrentDebugRenderTarget() == "GBufferAlbedo") ? "" : "GBufferAlbedo");
+		renderer.setCurrentDebugRenderTarget(
+			(renderer.getCurrentDebugRenderTarget() == "IndirectDiffuseClipmapsTest") ? "" : "IndirectDiffuseClipmapsTest");
 		// g_shadowMappingPcssCVar = !g_shadowMappingPcssCVar;
 	}