فهرست منبع

Add clipmaps to volumetric lighting

Panagiotis Christopoulos Charitos 6 ماه پیش
والد
کامیت
02fa230807

+ 7 - 0
AnKi/Gr/Vulkan/VkGrManager.cpp

@@ -1622,6 +1622,13 @@ VkBool32 GrManagerImpl::debugReportCallbackEXT(VkDebugUtilsMessageSeverityFlagBi
 	}
 #endif
 
+	if(pCallbackData->messageIdNumber == 20145586 || pCallbackData->messageIdNumber == 979140054)
+	{
+		// Mismatch of the format of the storage image (or the storage texel buffer) in SPIR-V and the actual VkImage. Ignore it because DXC puts
+		// almost random shit as formats
+		return false;
+	}
+
 	if(pCallbackData->messageIdNumber == 1944932341 || pCallbackData->messageIdNumber == 1303270965)
 	{
 		// Not sure why I'm getting that

+ 6 - 6
AnKi/Renderer/Dbg.cpp

@@ -130,7 +130,7 @@ void Dbg::drawNonRenderable(GpuSceneNonRenderableObjectType type, U32 objCount,
 	consts.m_camTrf = ctx.m_matrices.m_cameraTransform;
 	cmdb.setFastConstants(&consts, sizeof(consts));
 
-	cmdb.bindSrv(1, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(type));
+	cmdb.bindSrv(1, 0, getClusterBinning().getPackedObjectsBuffer(type));
 	cmdb.bindSrv(2, 0, getRenderer().getPrimaryNonRenderableVisibility().getVisibleIndicesBuffer(type));
 
 	cmdb.bindSampler(1, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
@@ -156,7 +156,7 @@ void Dbg::run(RenderPassWorkContext& rgraphCtx, const RenderingContext& ctx)
 	cmdb.setLineWidth(2.0f);
 
 	cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
-	rgraphCtx.bindSrv(0, 0, getRenderer().getGBuffer().getDepthRt());
+	rgraphCtx.bindSrv(0, 0, getGBuffer().getDepthRt());
 
 	// GBuffer renderables
 	if(g_dbgSceneCVar)
@@ -189,7 +189,7 @@ void Dbg::run(RenderPassWorkContext& rgraphCtx, const RenderingContext& ctx)
 
 		BufferView indicesBuff;
 		BufferHandle dep;
-		getRenderer().getGBuffer().getVisibleAabbsBuffer(indicesBuff, dep);
+		getGBuffer().getVisibleAabbsBuffer(indicesBuff, dep);
 		cmdb.bindSrv(2, 0, indicesBuff);
 
 		cmdb.drawIndexed(PrimitiveTopology::kLines, 12 * 2, allAabbCount);
@@ -313,19 +313,19 @@ void Dbg::populateRenderGraph(RenderingContext& ctx)
 
 	GraphicsRenderPassTargetDesc colorRti(m_runCtx.m_rt);
 	colorRti.m_loadOperation = RenderTargetLoadOperation::kClear;
-	GraphicsRenderPassTargetDesc depthRti(getRenderer().getGBuffer().getDepthRt());
+	GraphicsRenderPassTargetDesc depthRti(getGBuffer().getDepthRt());
 	depthRti.m_loadOperation = RenderTargetLoadOperation::kLoad;
 	depthRti.m_subresource.m_depthStencilAspect = DepthStencilAspectBit::kDepth;
 	pass.setRenderpassInfo({colorRti}, &depthRti);
 
 	pass.newTextureDependency(m_runCtx.m_rt, TextureUsageBit::kRtvDsvWrite);
-	pass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvPixel | TextureUsageBit::kRtvDsvRead);
+	pass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvPixel | TextureUsageBit::kRtvDsvRead);
 
 	if(g_dbgSceneCVar)
 	{
 		BufferView indicesBuff;
 		BufferHandle dep;
-		getRenderer().getGBuffer().getVisibleAabbsBuffer(indicesBuff, dep);
+		getGBuffer().getVisibleAabbsBuffer(indicesBuff, dep);
 		pass.newBufferDependency(dep, BufferUsageBit::kSrvGeometry);
 
 		if(GpuSceneArrays::RenderableBoundingVolumeForward::getSingleton().getElementCount())

+ 4 - 4
AnKi/Renderer/DepthDownscale.cpp

@@ -89,7 +89,7 @@ void DepthDownscale::populateRenderGraph(RenderingContext& ctx)
 
 		NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("Depth downscale");
 
-		pass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
+		pass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
 
 		pass.newTextureDependency(m_runCtx.m_rt, TextureUsageBit::kUavCompute);
 
@@ -131,7 +131,7 @@ void DepthDownscale::populateRenderGraph(RenderingContext& ctx)
 			cmdb.bindUav(0, 0, BufferView(m_counterBuffer.get(), 0, sizeof(U32)));
 
 			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindSrv(0, 0, getRenderer().getGBuffer().getDepthRt());
+			rgraphCtx.bindSrv(0, 0, getGBuffer().getDepthRt());
 
 			cmdb.dispatchCompute(dispatchThreadGroupCountXY[0], dispatchThreadGroupCountXY[1], 1);
 		});
@@ -151,7 +151,7 @@ void DepthDownscale::populateRenderGraph(RenderingContext& ctx)
 
 			if(mip == 0)
 			{
-				pass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvPixel);
+				pass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvPixel);
 			}
 			else
 			{
@@ -170,7 +170,7 @@ void DepthDownscale::populateRenderGraph(RenderingContext& ctx)
 
 				if(mip == 0)
 				{
-					rgraphCtx.bindSrv(0, 0, getRenderer().getGBuffer().getDepthRt());
+					rgraphCtx.bindSrv(0, 0, getGBuffer().getDepthRt());
 				}
 				else
 				{

+ 7 - 8
AnKi/Renderer/ForwardShading.cpp

@@ -37,7 +37,7 @@ void ForwardShading::populateRenderGraph(RenderingContext& ctx)
 	visIn.m_lodDistances = lodDistances;
 	visIn.m_rgraph = &rgraph;
 	visIn.m_gatherAabbIndices = g_dbgSceneCVar;
-	RenderTargetHandle hzb = getRenderer().getGBuffer().getHzbRt();
+	RenderTargetHandle hzb = getGBuffer().getHzbRt();
 	visIn.m_hzbRt = &hzb;
 	visIn.m_viewportSize = getRenderer().getInternalResolution();
 
@@ -60,20 +60,19 @@ void ForwardShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgr
 		cmdb.bindSampler(ANKI_MATERIAL_REGISTER_LINEAR_CLAMP_SAMPLER, 0, getRenderer().getSamplers().m_trilinearClamp.get());
 		cmdb.bindSampler(ANKI_MATERIAL_REGISTER_SHADOW_SAMPLER, 0, getRenderer().getSamplers().m_trilinearClampShadow.get());
 
-		rgraphCtx.bindSrv(ANKI_MATERIAL_REGISTER_SCENE_DEPTH, 0, getRenderer().getDepthDownscale().getRt(),
-						  DepthDownscale::kQuarterInternalResolution);
+		rgraphCtx.bindSrv(ANKI_MATERIAL_REGISTER_SCENE_DEPTH, 0, getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
 		rgraphCtx.bindSrv(ANKI_MATERIAL_REGISTER_LIGHT_VOLUME, 0, getRenderer().getVolumetricLightingAccumulation().getRt());
 
 		cmdb.bindConstantBuffer(ANKI_MATERIAL_REGISTER_CLUSTER_SHADING_CONSTANTS, 0, ctx.m_globalRenderingConstantsBuffer);
 
 		cmdb.bindSrv(ANKI_MATERIAL_REGISTER_CLUSTER_SHADING_POINT_LIGHTS, 0,
-					 getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
+					 getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
 		cmdb.bindSrv(ANKI_MATERIAL_REGISTER_CLUSTER_SHADING_SPOT_LIGHTS, 0,
-					 getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
+					 getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
 
-		rgraphCtx.bindSrv(ANKI_MATERIAL_REGISTER_SHADOW_ATLAS, 0, getRenderer().getShadowMapping().getShadowmapRt());
+		rgraphCtx.bindSrv(ANKI_MATERIAL_REGISTER_SHADOW_ATLAS, 0, getShadowMapping().getShadowmapRt());
 
-		cmdb.bindSrv(ANKI_MATERIAL_REGISTER_CLUSTERS, 0, getRenderer().getClusterBinning().getClustersBuffer());
+		cmdb.bindSrv(ANKI_MATERIAL_REGISTER_CLUSTERS, 0, getClusterBinning().getClustersBuffer());
 
 		// Draw
 		RenderableDrawerArguments args;
@@ -99,7 +98,7 @@ void ForwardShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgr
 
 void ForwardShading::setDependencies(GraphicsRenderPass& pass)
 {
-	pass.newTextureDependency(getRenderer().getDepthDownscale().getRt(), TextureUsageBit::kSrvPixel, DepthDownscale::kQuarterInternalResolution);
+	pass.newTextureDependency(getDepthDownscale().getRt(), TextureUsageBit::kSrvPixel, DepthDownscale::kQuarterInternalResolution);
 	pass.newTextureDependency(getRenderer().getVolumetricLightingAccumulation().getRt(), TextureUsageBit::kSrvPixel);
 
 	if(getRenderer().getLensFlare().getIndirectDrawBuffer().isValid())

+ 11 - 11
AnKi/Renderer/GBufferPost.cpp

@@ -30,23 +30,23 @@ void GBufferPost::populateRenderGraph(RenderingContext& ctx)
 
 	NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("GBuffPost");
 
-	rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(0), TextureUsageBit::kUavCompute);
-	rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(1), TextureUsageBit::kUavCompute);
-	rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kUavCompute);
-	rpass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
+	rpass.newTextureDependency(getGBuffer().getColorRt(0), TextureUsageBit::kUavCompute);
+	rpass.newTextureDependency(getGBuffer().getColorRt(1), TextureUsageBit::kUavCompute);
+	rpass.newTextureDependency(getGBuffer().getColorRt(2), TextureUsageBit::kUavCompute);
+	rpass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
 
-	rpass.newBufferDependency(getRenderer().getClusterBinning().getDependency(), BufferUsageBit::kSrvCompute);
+	rpass.newBufferDependency(getClusterBinning().getDependency(), BufferUsageBit::kSrvCompute);
 
 	rpass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
 		CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
-		rgraphCtx.bindUav(0, 0, getRenderer().getGBuffer().getColorRt(0));
-		rgraphCtx.bindUav(1, 0, getRenderer().getGBuffer().getColorRt(1));
-		rgraphCtx.bindUav(2, 0, getRenderer().getGBuffer().getColorRt(2));
+		rgraphCtx.bindUav(0, 0, getGBuffer().getColorRt(0));
+		rgraphCtx.bindUav(1, 0, getGBuffer().getColorRt(1));
+		rgraphCtx.bindUav(2, 0, getGBuffer().getColorRt(2));
 
-		rgraphCtx.bindSrv(0, 0, getRenderer().getGBuffer().getDepthRt());
-		cmdb.bindSrv(1, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kDecal));
-		cmdb.bindSrv(2, 0, getRenderer().getClusterBinning().getClustersBuffer());
+		rgraphCtx.bindSrv(0, 0, getGBuffer().getDepthRt());
+		cmdb.bindSrv(1, 0, getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kDecal));
+		cmdb.bindSrv(2, 0, getClusterBinning().getClustersBuffer());
 
 		cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
 

+ 8 - 8
AnKi/Renderer/IndirectDiffuse.cpp

@@ -124,14 +124,14 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 
 		rpass.newBufferDependency(sbtHandle, BufferUsageBit::kShaderBindingTable);
 		rpass.newTextureDependency(transientRt1, TextureUsageBit::kUavTraceRays);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvTraceRays);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(1), TextureUsageBit::kSrvTraceRays);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSrvTraceRays);
+		rpass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvTraceRays);
+		rpass.newTextureDependency(getGBuffer().getColorRt(1), TextureUsageBit::kSrvTraceRays);
+		rpass.newTextureDependency(getGBuffer().getColorRt(2), TextureUsageBit::kSrvTraceRays);
 		if(getRenderer().getGeneratedSky().isEnabled())
 		{
 			rpass.newTextureDependency(getRenderer().getGeneratedSky().getEnvironmentMapRt(), TextureUsageBit::kSrvTraceRays);
 		}
-		rpass.newTextureDependency(getRenderer().getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvTraceRays);
+		rpass.newTextureDependency(getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvTraceRays);
 		rpass.newAccelerationStructureDependency(getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle(),
 												 AccelerationStructureUsageBit::kTraceRaysSrv);
 
@@ -158,9 +158,9 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 			cmdb.bindConstantBuffer(0, 2, ctx.m_globalRenderingConstantsBuffer);
 
 			rgraphCtx.bindSrv(0, 2, getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle());
-			rgraphCtx.bindSrv(1, 2, getRenderer().getGBuffer().getDepthRt());
-			rgraphCtx.bindSrv(2, 2, getRenderer().getGBuffer().getColorRt(1));
-			rgraphCtx.bindSrv(3, 2, getRenderer().getGBuffer().getColorRt(2));
+			rgraphCtx.bindSrv(1, 2, getGBuffer().getDepthRt());
+			rgraphCtx.bindSrv(2, 2, getGBuffer().getColorRt(1));
+			rgraphCtx.bindSrv(3, 2, getGBuffer().getColorRt(2));
 
 			const LightComponent* dirLight = SceneGraph::getSingleton().getDirectionalLight();
 			const SkyboxComponent* sky = SceneGraph::getSingleton().getSkybox();
@@ -181,7 +181,7 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 
 			cmdb.bindSrv(5, 2, GpuSceneArrays::GlobalIlluminationProbe::getSingleton().getBufferView());
 			cmdb.bindSrv(6, 2, BufferView(getDummyGpuResources().m_buffer.get()));
-			rgraphCtx.bindSrv(7, 2, getRenderer().getShadowMapping().getShadowmapRt());
+			rgraphCtx.bindSrv(7, 2, getShadowMapping().getShadowmapRt());
 
 			rgraphCtx.bindUav(0, 2, transientRt1);
 			cmdb.bindUav(1, 2, TextureView(getDummyGpuResources().m_texture2DUav.get(), TextureSubresourceDesc::all()));

+ 88 - 62
AnKi/Renderer/IndirectDiffuseClipmaps.cpp

@@ -64,12 +64,14 @@ Error IndirectDiffuseClipmaps::init()
 
 	for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
 	{
-		m_probeValidityRtDescs[i] =
-			getRenderer().create2DRenderTargetDescription(m_clipmapInfo[i].m_probeCounts.x(), m_clipmapInfo[i].m_probeCounts.z(), Format::kR8_Unorm,
-														  generateTempPassName("IndirectDiffuseClipmap: Probe validity #%u", i));
-		m_probeValidityRtDescs[i].m_depth = m_clipmapInfo[i].m_probeCounts.y();
-		m_probeValidityRtDescs[i].m_type = TextureType::k3D;
-		m_probeValidityRtDescs[i].bake();
+		TextureInitInfo init = getRenderer().create2DRenderTargetInitInfo(m_clipmapInfo[i].m_probeCounts.x(), m_clipmapInfo[i].m_probeCounts.z(),
+																		  Format::kR8_Unorm, TextureUsageBit::kUavCompute | TextureUsageBit::kAllSrv,
+																		  generateTempPassName("IndirectDiffuseClipmap: Probe validity #%u", i));
+
+		init.m_depth = m_clipmapInfo[i].m_probeCounts.y();
+		init.m_type = TextureType::k3D;
+
+		m_probeValidityVolumes[i] = getRenderer().createAndClearRenderTarget(init, TextureUsageBit::kSrvCompute);
 	}
 
 	// Create the lighting result texture
@@ -114,6 +116,16 @@ Error IndirectDiffuseClipmaps::init()
 		m_distanceMomentsVolumes[clipmap] = getRenderer().createAndClearRenderTarget(volumeInit, TextureUsageBit::kSrvCompute);
 	}
 
+	for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
+	{
+		m_avgLightColorRtDescs[clipmap] = getRenderer().create2DRenderTargetDescription(
+			m_clipmapInfo[0].m_probeCounts.x(), m_clipmapInfo[0].m_probeCounts.z(), Format::kB10G11R11_Ufloat_Pack32,
+			generateTempPassName("IndirectDiffuseClipmap: Avg light #%u", clipmap));
+		m_avgLightColorRtDescs[clipmap].m_depth = m_clipmapInfo[0].m_probeCounts.y();
+		m_avgLightColorRtDescs[clipmap].m_type = TextureType::k3D;
+		m_avgLightColorRtDescs[clipmap].bake();
+	}
+
 	const Array<SubMutation, 4> mutation = {{{"GPU_WAVE_SIZE", MutatorValue(GrManager::getSingleton().getDeviceCapabilities().m_maxWaveSize)},
 											 {"RADIANCE_OCTAHEDRON_MAP_SIZE", MutatorValue(g_indirectDiffuseClipmapRadianceOctMapSize)},
 											 {"IRRADIANCE_OCTAHEDRON_MAP_SIZE", MutatorValue(g_indirectDiffuseClipmapIrradianceOctMapSize)},
@@ -179,33 +191,33 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 	RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
 
 	const RenderTargetHandle rtResultHandle = rgraph.newRenderTarget(m_rtResultRtDesc);
-	m_runCtx.m_appliedGiRt = rgraph.newRenderTarget(m_appliedGiRtDesc);
-
-	Array<RenderTargetHandle, kIndirectDiffuseClipmapCount> radianceVolumes;
-	Array<RenderTargetHandle, kIndirectDiffuseClipmapCount> irradianceVolumes;
-	Array<RenderTargetHandle, kIndirectDiffuseClipmapCount> distanceMomentsVolumes;
+	m_runCtx.m_handles.m_appliedIrradiance = rgraph.newRenderTarget(m_appliedGiRtDesc);
+
+	RenderTargetHandle& appliedGiRt = m_runCtx.m_handles.m_appliedIrradiance;
+	Array<RenderTargetHandle, kIndirectDiffuseClipmapCount>& radianceVolumes = m_runCtx.m_handles.m_radianceVolumes;
+	Array<RenderTargetHandle, kIndirectDiffuseClipmapCount>& irradianceVolumes = m_runCtx.m_handles.m_irradianceVolumes;
+	Array<RenderTargetHandle, kIndirectDiffuseClipmapCount>& distanceMomentsVolumes = m_runCtx.m_handles.m_distanceMomentsVolumes;
+	Array<RenderTargetHandle, kIndirectDiffuseClipmapCount>& probeValidityVolumes = m_runCtx.m_handles.m_probeValidityVolumes;
+	Array<RenderTargetHandle, kIndirectDiffuseClipmapCount>& avgIrradianceVolumes = m_runCtx.m_handles.m_avgIrradianceVolumes;
 	for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
 	{
-		if(m_texturesImportedOnce)
+		if(m_texturesImportedOnce) [[likely]]
 		{
 			radianceVolumes[i] = rgraph.importRenderTarget(m_radianceVolumes[i].get());
 			irradianceVolumes[i] = rgraph.importRenderTarget(m_irradianceVolumes[i].get());
 			distanceMomentsVolumes[i] = rgraph.importRenderTarget(m_distanceMomentsVolumes[i].get());
+			probeValidityVolumes[i] = rgraph.importRenderTarget(m_probeValidityVolumes[i].get());
 		}
 		else
 		{
 			radianceVolumes[i] = rgraph.importRenderTarget(m_radianceVolumes[i].get(), TextureUsageBit::kSrvCompute);
 			irradianceVolumes[i] = rgraph.importRenderTarget(m_irradianceVolumes[i].get(), TextureUsageBit::kSrvCompute);
 			distanceMomentsVolumes[i] = rgraph.importRenderTarget(m_distanceMomentsVolumes[i].get(), TextureUsageBit::kSrvCompute);
+			probeValidityVolumes[i] = rgraph.importRenderTarget(m_probeValidityVolumes[i].get(), TextureUsageBit::kSrvCompute);
 		}
-	}
 
-	Array<RenderTargetHandle, kIndirectDiffuseClipmapCount> probeValidityVolumes;
-	for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
-	{
-		probeValidityVolumes[i] = rgraph.newRenderTarget(m_probeValidityRtDescs[i]);
+		avgIrradianceVolumes[i] = rgraph.newRenderTarget(m_avgLightColorRtDescs[i]);
 	}
-	m_runCtx.m_probeValidityRts = probeValidityVolumes;
 
 	// SBT build
 	BufferHandle sbtHandle;
@@ -223,7 +235,7 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 		{
 			pass.newTextureDependency(getRenderer().getGeneratedSky().getEnvironmentMapRt(), TextureUsageBit::kSrvTraceRays);
 		}
-		pass.newTextureDependency(getRenderer().getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvTraceRays);
+		pass.newTextureDependency(getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvTraceRays);
 		pass.newAccelerationStructureDependency(getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle(),
 												AccelerationStructureUsageBit::kTraceRaysSrv);
 
@@ -274,7 +286,7 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 				rgraphCtx.bindSrv(srv++, 2, getRenderer().getGeneratedSky().getEnvironmentMapRt());
 			}
 
-			rgraphCtx.bindSrv(srv++, 2, getRenderer().getShadowMapping().getShadowmapRt());
+			rgraphCtx.bindSrv(srv++, 2, getShadowMapping().getShadowmapRt());
 
 			cmdb.bindSrv(srv++, 2, BufferView(getDummyGpuResources().m_buffer.get(), 0, sizeof(U32)));
 			cmdb.bindSrv(srv++, 2, BufferView(getDummyGpuResources().m_buffer.get(), 0, sizeof(U32)));
@@ -364,9 +376,10 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 		{
 			pass.newTextureDependency(radianceVolumes[clipmap], TextureUsageBit::kSrvCompute);
 			pass.newTextureDependency(irradianceVolumes[clipmap], TextureUsageBit::kUavCompute);
+			pass.newTextureDependency(avgIrradianceVolumes[clipmap], TextureUsageBit::kUavCompute);
 		}
 
-		pass.setWork([this, &ctx, radianceVolumes, irradianceVolumes](RenderPassWorkContext& rgraphCtx) {
+		pass.setWork([this, &ctx, radianceVolumes, irradianceVolumes, avgIrradianceVolumes](RenderPassWorkContext& rgraphCtx) {
 			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
 			cmdb.bindShaderProgram(m_computeIrradianceGrProg.get());
@@ -375,10 +388,16 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 
 			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
 
+			U32 uav = 0;
 			for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
 			{
 				rgraphCtx.bindSrv(clipmap, 0, radianceVolumes[clipmap]);
-				rgraphCtx.bindUav(clipmap, 0, irradianceVolumes[clipmap]);
+				rgraphCtx.bindUav(uav++, 0, irradianceVolumes[clipmap]);
+			}
+
+			for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
+			{
+				rgraphCtx.bindUav(uav++, 0, avgIrradianceVolumes[clipmap]);
 			}
 
 			cmdb.dispatchCompute(m_clipmapInfo[0].m_probeCounts[0] * kIndirectDiffuseClipmapCount, m_clipmapInfo[0].m_probeCounts[1],
@@ -387,7 +406,7 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 	}
 
 	// Apply GI
-	if(1)
+	if(0)
 	{
 		patchShaderBindingTablePass("IndirectDiffuseClipmaps: Patch SBT", m_rtLibraryGrProg.get(), m_rayGenShaderGroupIndices[0],
 									m_missShaderGroupIdx, m_sbtRecordSize, rgraph, sbtHandle, sbtBuffer);
@@ -399,11 +418,11 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 		{
 			pass.newTextureDependency(getRenderer().getGeneratedSky().getEnvironmentMapRt(), TextureUsageBit::kSrvTraceRays);
 		}
-		pass.newTextureDependency(getRenderer().getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvTraceRays);
+		pass.newTextureDependency(getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvTraceRays);
 		pass.newAccelerationStructureDependency(getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle(),
 												AccelerationStructureUsageBit::kTraceRaysSrv);
-		pass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSrvTraceRays);
-		pass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvTraceRays);
+		pass.newTextureDependency(getGBuffer().getColorRt(2), TextureUsageBit::kSrvTraceRays);
+		pass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvTraceRays);
 
 		for(U32 clipmap = 0; clipmap < kIndirectDiffuseClipmapCount; ++clipmap)
 		{
@@ -412,7 +431,7 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 			pass.newTextureDependency(distanceMomentsVolumes[clipmap], TextureUsageBit::kSrvTraceRays);
 		}
 
-		pass.newTextureDependency(m_runCtx.m_appliedGiRt, TextureUsageBit::kUavTraceRays);
+		pass.newTextureDependency(appliedGiRt, TextureUsageBit::kUavTraceRays);
 
 		pass.setWork([this, &ctx, sbtBuffer, irradianceVolumes, probeValidityVolumes, distanceMomentsVolumes](RenderPassWorkContext& rgraphCtx) {
 			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
@@ -455,7 +474,7 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 				rgraphCtx.bindSrv(srv++, 2, getRenderer().getGeneratedSky().getEnvironmentMapRt());
 			}
 
-			rgraphCtx.bindSrv(srv++, 2, getRenderer().getShadowMapping().getShadowmapRt());
+			rgraphCtx.bindSrv(srv++, 2, getShadowMapping().getShadowmapRt());
 
 			cmdb.bindSrv(srv++, 2, BufferView(getDummyGpuResources().m_buffer.get(), 0, sizeof(U32)));
 			cmdb.bindSrv(srv++, 2, BufferView(getDummyGpuResources().m_buffer.get(), 0, sizeof(U32)));
@@ -473,15 +492,15 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 				rgraphCtx.bindSrv(srv++, 2, distanceMomentsVolumes[clipmap]);
 			}
 
-			rgraphCtx.bindSrv(srv++, 2, getRenderer().getGBuffer().getDepthRt());
+			rgraphCtx.bindSrv(srv++, 2, getGBuffer().getDepthRt());
 			cmdb.bindSrv(srv++, 2, TextureView(getDummyGpuResources().m_texture2DSrv.get(), TextureSubresourceDesc::all()));
-			rgraphCtx.bindSrv(srv++, 2, getRenderer().getGBuffer().getColorRt(2));
+			rgraphCtx.bindSrv(srv++, 2, getGBuffer().getColorRt(2));
 
 			cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearClamp.get());
 			cmdb.bindSampler(1, 2, getRenderer().getSamplers().m_trilinearClampShadow.get());
 			cmdb.bindSampler(2, 2, getRenderer().getSamplers().m_trilinearRepeat.get());
 
-			rgraphCtx.bindUav(0, 2, m_runCtx.m_appliedGiRt);
+			rgraphCtx.bindUav(0, 2, m_runCtx.m_handles.m_appliedIrradiance);
 			cmdb.bindUav(1, 2, TextureView(getDummyGpuResources().m_texture2DUav.get(), TextureSubresourceDesc::firstSurface()));
 
 			const Vec3 probeSizes = m_clipmapInfo[0].m_size / Vec3(m_clipmapInfo[0].m_probeCounts);
@@ -497,49 +516,56 @@ void IndirectDiffuseClipmaps::populateRenderGraph(RenderingContext& ctx)
 	{
 		NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("IndirectDiffuseClipmaps composite");
 
-		pass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
-		pass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
+		pass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
+		pass.newTextureDependency(getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
 		for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
 		{
 			pass.newTextureDependency(irradianceVolumes[i], TextureUsageBit::kSrvCompute);
 			pass.newTextureDependency(probeValidityVolumes[i], TextureUsageBit::kSrvCompute);
 			pass.newTextureDependency(distanceMomentsVolumes[i], TextureUsageBit::kSrvCompute);
+			pass.newTextureDependency(avgIrradianceVolumes[i], TextureUsageBit::kSrvCompute);
 		}
-		pass.newTextureDependency(m_runCtx.m_appliedGiRt, TextureUsageBit::kUavCompute);
+		pass.newTextureDependency(appliedGiRt, TextureUsageBit::kUavCompute);
 
-		pass.setWork([this, &ctx, irradianceVolumes, probeValidityVolumes, distanceMomentsVolumes](RenderPassWorkContext& rgraphCtx) {
-			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
+		pass.setWork(
+			[this, &ctx, irradianceVolumes, probeValidityVolumes, distanceMomentsVolumes, avgIrradianceVolumes](RenderPassWorkContext& rgraphCtx) {
+				CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
-			cmdb.bindShaderProgram(m_applyGiGrProg.get());
+				cmdb.bindShaderProgram(m_applyGiGrProg.get());
 
-			rgraphCtx.bindSrv(0, 0, getRenderer().getGBuffer().getDepthRt());
-			rgraphCtx.bindSrv(1, 0, getRenderer().getGBuffer().getColorRt(2));
-			cmdb.bindSrv(2, 0, TextureView(&m_blueNoiseImg->getTexture(), TextureSubresourceDesc::firstSurface()));
+				rgraphCtx.bindSrv(0, 0, getGBuffer().getDepthRt());
+				rgraphCtx.bindSrv(1, 0, getGBuffer().getColorRt(2));
+				cmdb.bindSrv(2, 0, TextureView(&m_blueNoiseImg->getTexture(), TextureSubresourceDesc::firstSurface()));
 
-			U32 srvReg = 3;
-			for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
-			{
-				rgraphCtx.bindSrv(srvReg++, 0, irradianceVolumes[i]);
-			}
+				U32 srvReg = 3;
+				for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
+				{
+					rgraphCtx.bindSrv(srvReg++, 0, irradianceVolumes[i]);
+				}
 
-			for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
-			{
-				rgraphCtx.bindSrv(srvReg++, 0, probeValidityVolumes[i]);
-			}
+				for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
+				{
+					rgraphCtx.bindSrv(srvReg++, 0, probeValidityVolumes[i]);
+				}
 
-			for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
-			{
-				rgraphCtx.bindSrv(srvReg++, 0, distanceMomentsVolumes[i]);
-			}
+				for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
+				{
+					rgraphCtx.bindSrv(srvReg++, 0, distanceMomentsVolumes[i]);
+				}
 
-			rgraphCtx.bindUav(0, 0, m_runCtx.m_appliedGiRt);
+				for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
+				{
+					rgraphCtx.bindSrv(srvReg++, 0, avgIrradianceVolumes[i]);
+				}
 
-			cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
+				rgraphCtx.bindUav(0, 0, m_runCtx.m_handles.m_appliedIrradiance);
 
-			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
+				cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
 
-			dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
-		});
+				cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
+
+				dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
+			});
 	}
 }
 
@@ -547,7 +573,7 @@ void IndirectDiffuseClipmaps::drawDebugProbes(const RenderingContext& ctx, Rende
 {
 	CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
-	const U32 clipmap = 0;
+	const U32 clipmap = 1;
 
 	cmdb.bindShaderProgram(m_visProbesGrProg.get());
 
@@ -556,9 +582,9 @@ void IndirectDiffuseClipmaps::drawDebugProbes(const RenderingContext& ctx, Rende
 
 	cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
 
-	Texture* visVolume = m_irradianceVolumes[clipmap].get();
-	cmdb.bindSrv(0, 0, TextureView(visVolume, TextureSubresourceDesc::all()));
-	rgraphCtx.bindSrv(1, 0, m_runCtx.m_probeValidityRts[clipmap]);
+	const RenderTargetHandle visVolume = m_runCtx.m_handles.m_irradianceVolumes[clipmap];
+	rgraphCtx.bindSrv(0, 0, visVolume);
+	rgraphCtx.bindSrv(1, 0, m_runCtx.m_handles.m_probeValidityVolumes[clipmap]);
 	cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
 
 	cmdb.draw(PrimitiveTopology::kTriangles, 36, m_clipmapInfo[clipmap].m_probeCountTotal);

+ 18 - 6
AnKi/Renderer/IndirectDiffuseClipmaps.h

@@ -57,6 +57,18 @@ inline NumericCVar<U32> g_indirectDiffuseClipmapRadianceOctMapSize(
 inline NumericCVar<U32> g_indirectDiffuseClipmapIrradianceOctMapSize("R", "IndirectDiffuseClipmapIrradianceOctMapSize", 5, 4, 20,
 																	 "Size of the octahedral for the irradiance");
 
+/// @memberof IndirectDiffuseClipmaps
+class IndirectDiffuseClipmapsRenderTargetHandles
+{
+public:
+	RenderTargetHandle m_appliedIrradiance;
+	Array<RenderTargetHandle, kIndirectDiffuseClipmapCount> m_radianceVolumes;
+	Array<RenderTargetHandle, kIndirectDiffuseClipmapCount> m_irradianceVolumes;
+	Array<RenderTargetHandle, kIndirectDiffuseClipmapCount> m_distanceMomentsVolumes;
+	Array<RenderTargetHandle, kIndirectDiffuseClipmapCount> m_probeValidityVolumes;
+	Array<RenderTargetHandle, kIndirectDiffuseClipmapCount> m_avgIrradianceVolumes;
+};
+
 /// Indirect diffuse based on clipmaps of probes.
 class IndirectDiffuseClipmaps : public RtMaterialFetchRendererObject
 {
@@ -73,7 +85,7 @@ public:
 	void getDebugRenderTarget([[maybe_unused]] CString rtName, Array<RenderTargetHandle, kMaxDebugRenderTargets>& handles,
 							  [[maybe_unused]] ShaderProgramPtr& optionalShaderProgram) const override
 	{
-		handles[0] = m_runCtx.m_appliedGiRt;
+		handles[0] = m_runCtx.m_handles.m_appliedIrradiance;
 	}
 
 	const Array<Clipmap, kIndirectDiffuseClipmapCount>& getClipmapsInfo() const
@@ -83,19 +95,20 @@ public:
 
 	void drawDebugProbes(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx) const;
 
-	RenderTargetHandle getRt() const
+	const IndirectDiffuseClipmapsRenderTargetHandles& getRts() const
 	{
-		return m_runCtx.m_appliedGiRt;
+		return m_runCtx.m_handles;
 	}
 
 private:
 	Array<TexturePtr, kIndirectDiffuseClipmapCount> m_radianceVolumes;
 	Array<TexturePtr, kIndirectDiffuseClipmapCount> m_irradianceVolumes;
 	Array<TexturePtr, kIndirectDiffuseClipmapCount> m_distanceMomentsVolumes;
+	Array<TexturePtr, kIndirectDiffuseClipmapCount> m_probeValidityVolumes;
 
 	RenderTargetDesc m_rtResultRtDesc;
-	Array<RenderTargetDesc, kIndirectDiffuseClipmapCount> m_probeValidityRtDescs;
 	RenderTargetDesc m_appliedGiRtDesc;
+	Array<RenderTargetDesc, kIndirectDiffuseClipmapCount> m_avgLightColorRtDescs;
 
 	Array<Clipmap, kIndirectDiffuseClipmapCount> m_clipmapInfo;
 
@@ -118,8 +131,7 @@ private:
 	class
 	{
 	public:
-		RenderTargetHandle m_appliedGiRt;
-		Array<RenderTargetHandle, kIndirectDiffuseClipmapCount> m_probeValidityRts;
+		IndirectDiffuseClipmapsRenderTargetHandles m_handles;
 	} m_runCtx;
 };
 /// @}

+ 2 - 2
AnKi/Renderer/LensFlare.cpp

@@ -55,7 +55,7 @@ void LensFlare::populateRenderGraph(RenderingContext& ctx)
 	NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("Lens flare indirect");
 
 	rpass.newBufferDependency(m_runCtx.m_indirectBuffHandle, BufferUsageBit::kUavCompute);
-	rpass.newTextureDependency(getRenderer().getDepthDownscale().getRt(), TextureUsageBit::kSrvCompute, DepthDownscale::kEighthInternalResolution);
+	rpass.newTextureDependency(getDepthDownscale().getRt(), TextureUsageBit::kSrvCompute, DepthDownscale::kEighthInternalResolution);
 
 	rpass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
 		ANKI_TRACE_SCOPED_EVENT(LensFlare);
@@ -79,7 +79,7 @@ void LensFlare::populateRenderGraph(RenderingContext& ctx)
 		rgraphCtx.bindUav(0, 0, m_runCtx.m_indirectBuffHandle);
 		// Bind neareset because you don't need high quality
 		cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
-		rgraphCtx.bindSrv(1, 0, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kEighthInternalResolution);
+		rgraphCtx.bindSrv(1, 0, getDepthDownscale().getRt(), DepthDownscale::kEighthInternalResolution);
 
 		cmdb.dispatchCompute(flareCount, 1, 1);
 	});

+ 25 - 25
AnKi/Renderer/LightShading.cpp

@@ -84,28 +84,28 @@ void LightShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgrap
 
 		// Bind all
 		cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
-		cmdb.bindSrv(0, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
-		cmdb.bindSrv(1, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
+		cmdb.bindSrv(0, 0, getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
+		cmdb.bindSrv(1, 0, getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
 		if(getRenderer().isIndirectDiffuseClipmapsEnabled())
 		{
-			rgraphCtx.bindSrv(2, 0, getRenderer().getIndirectDiffuseClipmaps().getRt());
+			rgraphCtx.bindSrv(2, 0, getIndirectDiffuseClipmaps().getRts().m_appliedIrradiance);
 		}
 		else
 		{
-			cmdb.bindSrv(2, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kGlobalIlluminationProbe));
+			cmdb.bindSrv(2, 0, getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kGlobalIlluminationProbe));
 		}
-		cmdb.bindSrv(3, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kReflectionProbe));
-		cmdb.bindSrv(4, 0, getRenderer().getClusterBinning().getClustersBuffer());
+		cmdb.bindSrv(3, 0, getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kReflectionProbe));
+		cmdb.bindSrv(4, 0, getClusterBinning().getClustersBuffer());
 
 		cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
 		cmdb.bindSampler(1, 0, getRenderer().getSamplers().m_trilinearClamp.get());
-		rgraphCtx.bindSrv(5, 0, getRenderer().getGBuffer().getColorRt(0));
-		rgraphCtx.bindSrv(6, 0, getRenderer().getGBuffer().getColorRt(1));
-		rgraphCtx.bindSrv(7, 0, getRenderer().getGBuffer().getColorRt(2));
-		rgraphCtx.bindSrv(8, 0, getRenderer().getGBuffer().getDepthRt());
-		rgraphCtx.bindSrv(9, 0, getRenderer().getShadowmapsResolve().getRt());
-		rgraphCtx.bindSrv(10, 0, getRenderer().getSsao().getRt());
-		rgraphCtx.bindSrv(11, 0, getRenderer().getReflections().getRt());
+		rgraphCtx.bindSrv(5, 0, getGBuffer().getColorRt(0));
+		rgraphCtx.bindSrv(6, 0, getGBuffer().getColorRt(1));
+		rgraphCtx.bindSrv(7, 0, getGBuffer().getColorRt(2));
+		rgraphCtx.bindSrv(8, 0, getGBuffer().getDepthRt());
+		rgraphCtx.bindSrv(9, 0, getShadowmapsResolve().getRt());
+		rgraphCtx.bindSrv(10, 0, getSsao().getRt());
+		rgraphCtx.bindSrv(11, 0, getReflections().getRt());
 		cmdb.bindSrv(12, 0, TextureView(&getRenderer().getProbeReflections().getIntegrationLut(), TextureSubresourceDesc::all()));
 
 		// Draw
@@ -181,7 +181,7 @@ void LightShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgrap
 		cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
 		cmdb.bindSampler(1, 0, getRenderer().getSamplers().m_trilinearClamp.get());
 
-		rgraphCtx.bindSrv(0, 0, getRenderer().getGBuffer().getDepthRt());
+		rgraphCtx.bindSrv(0, 0, getGBuffer().getDepthRt());
 		rgraphCtx.bindSrv(1, 0, getRenderer().getVolumetricFog().getRt());
 
 		class Consts
@@ -211,7 +211,7 @@ void LightShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgrap
 	// Debug stuff
 	if(g_visualizeGiProbesCVar && getRenderer().isIndirectDiffuseClipmapsEnabled())
 	{
-		getRenderer().getIndirectDiffuseClipmaps().drawDebugProbes(ctx, rgraphCtx);
+		getIndirectDiffuseClipmaps().drawDebugProbes(ctx, rgraphCtx);
 	}
 
 	// Forward shading last
@@ -255,7 +255,7 @@ void LightShading::populateRenderGraph(RenderingContext& ctx)
 	});
 
 	GraphicsRenderPassTargetDesc colorRt(m_runCtx.m_rt);
-	GraphicsRenderPassTargetDesc depthRt(getRenderer().getGBuffer().getDepthRt());
+	GraphicsRenderPassTargetDesc depthRt(getGBuffer().getDepthRt());
 	depthRt.m_loadOperation = RenderTargetLoadOperation::kLoad;
 	depthRt.m_subresource.m_depthStencilAspect = DepthStencilAspectBit::kDepth;
 	pass.setRenderpassInfo({colorRt}, &depthRt, (enableVrs) ? &sriRt : nullptr,
@@ -272,18 +272,18 @@ void LightShading::populateRenderGraph(RenderingContext& ctx)
 
 	// Light shading
 	pass.newTextureDependency(m_runCtx.m_rt, TextureUsageBit::kRtvDsvWrite);
-	pass.newTextureDependency(getRenderer().getGBuffer().getColorRt(0), readUsage);
-	pass.newTextureDependency(getRenderer().getGBuffer().getColorRt(1), readUsage);
-	pass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), readUsage);
-	pass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvPixel | TextureUsageBit::kRtvDsvRead);
-	pass.newTextureDependency(getRenderer().getShadowmapsResolve().getRt(), readUsage);
-	pass.newBufferDependency(getRenderer().getClusterBinning().getDependency(), BufferUsageBit::kSrvPixel);
-	pass.newTextureDependency(getRenderer().getSsao().getRt(), readUsage);
-	pass.newTextureDependency(getRenderer().getReflections().getRt(), readUsage);
+	pass.newTextureDependency(getGBuffer().getColorRt(0), readUsage);
+	pass.newTextureDependency(getGBuffer().getColorRt(1), readUsage);
+	pass.newTextureDependency(getGBuffer().getColorRt(2), readUsage);
+	pass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvPixel | TextureUsageBit::kRtvDsvRead);
+	pass.newTextureDependency(getShadowmapsResolve().getRt(), readUsage);
+	pass.newBufferDependency(getClusterBinning().getDependency(), BufferUsageBit::kSrvPixel);
+	pass.newTextureDependency(getSsao().getRt(), readUsage);
+	pass.newTextureDependency(getReflections().getRt(), readUsage);
 
 	if(getRenderer().isIndirectDiffuseClipmapsEnabled())
 	{
-		pass.newTextureDependency(getRenderer().getIndirectDiffuseClipmaps().getRt(), TextureUsageBit::kSrvPixel);
+		pass.newTextureDependency(getIndirectDiffuseClipmaps().getRts().m_appliedIrradiance, TextureUsageBit::kSrvPixel);
 	}
 
 	// Fog

+ 2 - 2
AnKi/Renderer/MotionBlur.cpp

@@ -124,7 +124,7 @@ void MotionBlur::populateRenderGraph(RenderingContext& ctx)
 		}
 
 		ppass->newTextureDependency(getRenderer().getTonemapping().getRt(), readUsage);
-		ppass->newTextureDependency(getRenderer().getGBuffer().getDepthRt(), readUsage);
+		ppass->newTextureDependency(getGBuffer().getDepthRt(), readUsage);
 		ppass->newTextureDependency(maxNeighbourVelRt, readUsage);
 		ppass->newTextureDependency(getRenderer().getMotionVectors().getMotionVectorsRt(), readUsage);
 		ppass->newTextureDependency(m_runCtx.m_rt, writeUsage);
@@ -136,7 +136,7 @@ void MotionBlur::populateRenderGraph(RenderingContext& ctx)
 			cmdb.bindShaderProgram(m_reconstructGrProg.get());
 
 			rgraphCtx.bindSrv(0, 0, getRenderer().getTonemapping().getRt());
-			rgraphCtx.bindSrv(1, 0, getRenderer().getGBuffer().getDepthRt());
+			rgraphCtx.bindSrv(1, 0, getGBuffer().getDepthRt());
 			rgraphCtx.bindSrv(2, 0, maxNeighbourVelRt);
 			rgraphCtx.bindSrv(3, 0, getRenderer().getMotionVectors().getMotionVectorsRt());
 

+ 5 - 5
AnKi/Renderer/MotionVectors.cpp

@@ -58,8 +58,8 @@ void MotionVectors::populateRenderGraph(RenderingContext& ctx)
 		cmdb.bindShaderProgram(m_grProg.get());
 
 		cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
-		rgraphCtx.bindSrv(0, 0, getRenderer().getGBuffer().getDepthRt());
-		rgraphCtx.bindSrv(1, 0, getRenderer().getGBuffer().getColorRt(3));
+		rgraphCtx.bindSrv(0, 0, getGBuffer().getDepthRt());
+		rgraphCtx.bindSrv(1, 0, getGBuffer().getColorRt(3));
 
 		class Constants
 		{
@@ -92,9 +92,9 @@ void MotionVectors::populateRenderGraph(RenderingContext& ctx)
 	});
 
 	ppass->newTextureDependency(m_runCtx.m_motionVectorsRtHandle, writeUsage);
-	ppass->newTextureDependency(getRenderer().getGBuffer().getColorRt(3), readUsage);
-	ppass->newTextureDependency(getRenderer().getGBuffer().getDepthRt(), readUsage);
-	ppass->newTextureDependency(getRenderer().getGBuffer().getPreviousFrameDepthRt(), readUsage);
+	ppass->newTextureDependency(getGBuffer().getColorRt(3), readUsage);
+	ppass->newTextureDependency(getGBuffer().getDepthRt(), readUsage);
+	ppass->newTextureDependency(getGBuffer().getPreviousFrameDepthRt(), readUsage);
 }
 
 } // end namespace anki

+ 1 - 1
AnKi/Renderer/PrimaryNonRenderableVisibility.cpp

@@ -96,7 +96,7 @@ void PrimaryNonRenderableVisibility::populateRenderGraph(RenderingContext& ctx)
 			in.m_passesName = passName;
 			in.m_objectType = type;
 			in.m_viewProjectionMat = ctx.m_matrices.m_viewProjection;
-			in.m_hzbRt = &getRenderer().getGBuffer().getHzbRt();
+			in.m_hzbRt = &getGBuffer().getHzbRt();
 			in.m_rgraph = &rgraph;
 
 			const GpuSceneNonRenderableObjectTypeWithFeedback feedbackType = toGpuSceneNonRenderableObjectTypeWithFeedback(type);

+ 40 - 40
AnKi/Renderer/Reflections.cpp

@@ -171,8 +171,8 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 		// Create the pass
 		NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("ReflTileClassification");
 
-		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(1), TextureUsageBit::kSrvCompute);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getGBuffer().getColorRt(1), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
 
 		rpass.newTextureDependency(classTileMapRt, TextureUsageBit::kUavCompute);
 		rpass.newBufferDependency(indirectArgsHandle, BufferUsageBit::kUavCompute);
@@ -183,8 +183,8 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 
 			cmdb.bindShaderProgram(m_tileClassificationGrProg.get());
 
-			rgraphCtx.bindSrv(0, 0, getRenderer().getGBuffer().getColorRt(1));
-			rgraphCtx.bindSrv(1, 0, getRenderer().getGBuffer().getDepthRt());
+			rgraphCtx.bindSrv(0, 0, getGBuffer().getColorRt(1));
+			rgraphCtx.bindSrv(1, 0, getGBuffer().getDepthRt());
 			rgraphCtx.bindUav(0, 0, classTileMapRt);
 			cmdb.bindUav(1, 0, BufferView(m_indirectArgsBuffer.get()));
 
@@ -204,14 +204,14 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 		// Create the pass
 		NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("SSR");
 
-		rpass.newTextureDependency(getRenderer().getDepthDownscale().getRt(), TextureUsageBit::kSrvCompute);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(0), TextureUsageBit::kSrvCompute);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(1), TextureUsageBit::kSrvCompute);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getDepthDownscale().getRt(), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getGBuffer().getColorRt(0), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getGBuffer().getColorRt(1), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
 		rpass.newTextureDependency(getRenderer().getBloom().getPyramidRt(), TextureUsageBit::kSrvCompute);
-		rpass.newBufferDependency(getRenderer().getClusterBinning().getDependency(), BufferUsageBit::kSrvCompute);
-		rpass.newTextureDependency(getRenderer().getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvCompute);
+		rpass.newBufferDependency(getClusterBinning().getDependency(), BufferUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvCompute);
 		rpass.newTextureDependency(classTileMapRt, TextureUsageBit::kSrvCompute);
 
 		rpass.newTextureDependency(transientRt1, TextureUsageBit::kUavCompute);
@@ -227,15 +227,15 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
 			cmdb.bindSampler(1, 0, getRenderer().getSamplers().m_trilinearClampShadow.get());
 
-			rgraphCtx.bindSrv(0, 0, getRenderer().getGBuffer().getColorRt(0));
-			rgraphCtx.bindSrv(1, 0, getRenderer().getGBuffer().getColorRt(1));
-			rgraphCtx.bindSrv(2, 0, getRenderer().getGBuffer().getColorRt(2));
-			rgraphCtx.bindSrv(3, 0, getRenderer().getDepthDownscale().getRt());
-			rgraphCtx.bindSrv(4, 0, getRenderer().getGBuffer().getDepthRt());
+			rgraphCtx.bindSrv(0, 0, getGBuffer().getColorRt(0));
+			rgraphCtx.bindSrv(1, 0, getGBuffer().getColorRt(1));
+			rgraphCtx.bindSrv(2, 0, getGBuffer().getColorRt(2));
+			rgraphCtx.bindSrv(3, 0, getDepthDownscale().getRt());
+			rgraphCtx.bindSrv(4, 0, getGBuffer().getDepthRt());
 			rgraphCtx.bindSrv(5, 0, getRenderer().getBloom().getPyramidRt());
-			cmdb.bindSrv(6, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kGlobalIlluminationProbe));
-			cmdb.bindSrv(7, 0, getRenderer().getClusterBinning().getClustersBuffer());
-			rgraphCtx.bindSrv(8, 0, getRenderer().getShadowMapping().getShadowmapRt());
+			cmdb.bindSrv(6, 0, getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kGlobalIlluminationProbe));
+			cmdb.bindSrv(7, 0, getClusterBinning().getClustersBuffer());
+			rgraphCtx.bindSrv(8, 0, getShadowMapping().getShadowmapRt());
 			rgraphCtx.bindSrv(9, 0, classTileMapRt);
 
 			rgraphCtx.bindUav(0, 0, transientRt1);
@@ -268,14 +268,14 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 		rpass.newBufferDependency(sbtHandle, BufferUsageBit::kShaderBindingTable);
 		rpass.newTextureDependency(transientRt1, TextureUsageBit::kUavTraceRays);
 		rpass.newTextureDependency(hitPosAndDepthRt, TextureUsageBit::kUavTraceRays);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvTraceRays);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(1), TextureUsageBit::kSrvTraceRays);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSrvTraceRays);
+		rpass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvTraceRays);
+		rpass.newTextureDependency(getGBuffer().getColorRt(1), TextureUsageBit::kSrvTraceRays);
+		rpass.newTextureDependency(getGBuffer().getColorRt(2), TextureUsageBit::kSrvTraceRays);
 		if(getRenderer().getGeneratedSky().isEnabled())
 		{
 			rpass.newTextureDependency(getRenderer().getGeneratedSky().getEnvironmentMapRt(), TextureUsageBit::kSrvTraceRays);
 		}
-		rpass.newTextureDependency(getRenderer().getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvTraceRays);
+		rpass.newTextureDependency(getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvTraceRays);
 		rpass.newAccelerationStructureDependency(getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle(),
 												 AccelerationStructureUsageBit::kTraceRaysSrv);
 		rpass.newBufferDependency(indirectArgsHandle, BufferUsageBit::kIndirectTraceRays);
@@ -322,7 +322,7 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 				rgraphCtx.bindSrv(srv++, 2, getRenderer().getGeneratedSky().getEnvironmentMapRt());
 			}
 
-			rgraphCtx.bindSrv(srv++, 2, getRenderer().getShadowMapping().getShadowmapRt());
+			rgraphCtx.bindSrv(srv++, 2, getShadowMapping().getShadowmapRt());
 
 			const auto& arr = GpuSceneArrays::GlobalIlluminationProbe::getSingleton();
 			cmdb.bindSrv(srv++, 2,
@@ -334,9 +334,9 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 				cmdb.bindSrv(srv++, 2, TextureView(getDummyGpuResources().m_texture3DSrv.get(), TextureSubresourceDesc::all()));
 			}
 
-			rgraphCtx.bindSrv(srv++, 2, getRenderer().getGBuffer().getDepthRt());
-			rgraphCtx.bindSrv(srv++, 2, getRenderer().getGBuffer().getColorRt(1));
-			rgraphCtx.bindSrv(srv++, 2, getRenderer().getGBuffer().getColorRt(2));
+			rgraphCtx.bindSrv(srv++, 2, getGBuffer().getDepthRt());
+			rgraphCtx.bindSrv(srv++, 2, getGBuffer().getColorRt(1));
+			rgraphCtx.bindSrv(srv++, 2, getGBuffer().getColorRt(2));
 
 			rgraphCtx.bindUav(0, 2, transientRt1);
 			rgraphCtx.bindUav(1, 2, hitPosAndDepthRt);
@@ -363,8 +363,8 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 	{
 		NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("ReflectionProbeFallback");
 
-		rpass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
-		rpass.newBufferDependency(getRenderer().getClusterBinning().getDependency(), BufferUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
+		rpass.newBufferDependency(getClusterBinning().getDependency(), BufferUsageBit::kSrvCompute);
 		rpass.newBufferDependency(indirectArgsHandle, BufferUsageBit::kIndirectCompute);
 		rpass.newTextureDependency(transientRt1, TextureUsageBit::kUavCompute);
 		rpass.newTextureDependency(hitPosAndDepthRt, TextureUsageBit::kUavCompute);
@@ -384,10 +384,10 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 
 			cmdb.bindShaderProgram(m_probeFallbackGrProg.get());
 
-			rgraphCtx.bindSrv(0, 0, getRenderer().getGBuffer().getDepthRt());
+			rgraphCtx.bindSrv(0, 0, getGBuffer().getDepthRt());
 			cmdb.bindSrv(1, 0, pixelsFailedSsrBuff);
-			cmdb.bindSrv(2, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kReflectionProbe));
-			cmdb.bindSrv(3, 0, getRenderer().getClusterBinning().getClustersBuffer());
+			cmdb.bindSrv(2, 0, getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kReflectionProbe));
+			cmdb.bindSrv(3, 0, getClusterBinning().getClustersBuffer());
 			cmdb.bindSrv(4, 0, BufferView(m_indirectArgsBuffer.get()).setRange(sizeof(U32)));
 
 			const LightComponent* dirLight = SceneGraph::getSingleton().getDirectionalLight();
@@ -424,9 +424,9 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 
 		rpass.newTextureDependency(transientRt1, TextureUsageBit::kSrvCompute);
 		rpass.newTextureDependency(hitPosAndDepthRt, TextureUsageBit::kSrvCompute);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(1), TextureUsageBit::kSrvCompute);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getGBuffer().getColorRt(1), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
 		rpass.newTextureDependency(classTileMapRt, TextureUsageBit::kSrvCompute);
 
 		rpass.newTextureDependency(transientRt2, TextureUsageBit::kUavCompute);
@@ -441,9 +441,9 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 
 			rgraphCtx.bindSrv(0, 0, transientRt1);
 			rgraphCtx.bindSrv(1, 0, hitPosAndDepthRt);
-			rgraphCtx.bindSrv(2, 0, getRenderer().getGBuffer().getDepthRt());
-			rgraphCtx.bindSrv(3, 0, getRenderer().getGBuffer().getColorRt(1));
-			rgraphCtx.bindSrv(4, 0, getRenderer().getGBuffer().getColorRt(2));
+			rgraphCtx.bindSrv(2, 0, getGBuffer().getDepthRt());
+			rgraphCtx.bindSrv(3, 0, getGBuffer().getColorRt(1));
+			rgraphCtx.bindSrv(4, 0, getGBuffer().getColorRt(2));
 			rgraphCtx.bindSrv(5, 0, classTileMapRt);
 
 			rgraphCtx.bindUav(0, 0, transientRt2);
@@ -503,7 +503,7 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 
 		rpass.newTextureDependency(transientRt1, TextureUsageBit::kSrvCompute);
 		rpass.newTextureDependency(writeMomentsRt, TextureUsageBit::kSrvCompute);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(1), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getGBuffer().getColorRt(1), TextureUsageBit::kSrvCompute);
 		rpass.newTextureDependency(classTileMapRt, TextureUsageBit::kSrvCompute);
 
 		rpass.newTextureDependency(transientRt2, TextureUsageBit::kUavCompute);
@@ -517,7 +517,7 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 
 			rgraphCtx.bindSrv(0, 0, transientRt1);
 			rgraphCtx.bindSrv(1, 0, writeMomentsRt);
-			rgraphCtx.bindSrv(2, 0, getRenderer().getGBuffer().getColorRt(1));
+			rgraphCtx.bindSrv(2, 0, getGBuffer().getColorRt(1));
 			rgraphCtx.bindSrv(3, 0, classTileMapRt);
 
 			rgraphCtx.bindUav(0, 0, transientRt2);

+ 14 - 7
AnKi/Renderer/Renderer.cpp

@@ -201,17 +201,21 @@ Error Renderer::initInternal(const RendererInitInfo& inf)
 	}
 
 	// Init the stages
-#define ANKI_RENDERER_OBJECT_DEF(name, name2, initCondition) \
+#define ANKI_RENDERER_OBJECT_DEF(type, name, initCondition) \
 	if(initCondition) \
 	{ \
-		m_##name2 = newInstance<name>(RendererMemoryPool::getSingleton()); \
-		ANKI_R_LOGV("Initializing " ANKI_STRINGIZE(name)); \
-		const Error err = m_##name2->init(); \
+		m_##name = newInstance<type>(RendererMemoryPool::getSingleton()); \
+		ANKI_R_LOGV("Initializing " ANKI_STRINGIZE(type)); \
+		const Error err = m_##name->init(); \
 		if(err) \
 		{ \
-			ANKI_R_LOGE("Initialization failed: " ANKI_STRINGIZE(name)); \
+			ANKI_R_LOGE("Initialization failed: " ANKI_STRINGIZE(type)); \
 			return err; \
 		} \
+	} \
+	else \
+	{ \
+		m_##name = nullptr; \
 	}
 #include <AnKi/Renderer/RendererObject.def.h>
 
@@ -305,10 +309,14 @@ Error Renderer::populateRenderGraph(RenderingContext& ctx)
 		m_accelerationStructureBuilder->populateRenderGraph(ctx);
 	}
 	m_gbuffer->populateRenderGraph(ctx);
+	m_depthDownscale->populateRenderGraph(ctx);
 	m_shadowMapping->populateRenderGraph(ctx);
 	m_clusterBinning2->populateRenderGraph(ctx);
 	m_generatedSky->populateRenderGraph(ctx);
-	m_indirectDiffuseProbes->populateRenderGraph(ctx);
+	if(m_indirectDiffuseProbes)
+	{
+		m_indirectDiffuseProbes->populateRenderGraph(ctx);
+	}
 	if(m_indirectDiffuseClipmaps)
 	{
 		m_indirectDiffuseClipmaps->populateRenderGraph(ctx);
@@ -317,7 +325,6 @@ Error Renderer::populateRenderGraph(RenderingContext& ctx)
 	m_volumetricLightingAccumulation->populateRenderGraph(ctx);
 	m_motionVectors->populateRenderGraph(ctx);
 	m_gbufferPost->populateRenderGraph(ctx);
-	m_depthDownscale->populateRenderGraph(ctx);
 	if(m_rtShadows)
 	{
 		m_rtShadows->populateRenderGraph(ctx);

+ 8 - 12
AnKi/Renderer/Renderer.h

@@ -95,23 +95,19 @@ public:
 
 	Error render(Texture* presentTex);
 
-#define ANKI_RENDERER_OBJECT_DEF(name, name2, initCondition) \
-	name& get##name() \
+#define ANKI_RENDERER_OBJECT_DEF(type, name, initCondition) \
+	type& get##type() \
 	{ \
-		ANKI_ASSERT(m_##name2); \
-		return *m_##name2; \
+		ANKI_ASSERT(m_##name != nullptr && m_##name != numberToPtr<type*>(kMaxPtrSize)); \
+		return *m_##name; \
 	} \
-	Bool is##name##Enabled() const \
+	Bool is##type##Enabled() const \
 	{ \
-		return m_##name2 != nullptr; \
+		ANKI_ASSERT(m_##name != numberToPtr<type*>(kMaxPtrSize) && "Calling this before the renderer had a chance to decide if to initialize it"); \
+		return m_##name != nullptr; \
 	}
 #include <AnKi/Renderer/RendererObject.def.h>
 
-	Bool getRtShadowsEnabled() const
-	{
-		return m_rtShadows != nullptr;
-	}
-
 	const UVec2& getInternalResolution() const
 	{
 		return m_internalResolution;
@@ -224,7 +220,7 @@ private:
 
 	/// @name Rendering stages
 	/// @{
-#define ANKI_RENDERER_OBJECT_DEF(name, name2, initCondition) name* m_##name2 = nullptr;
+#define ANKI_RENDERER_OBJECT_DEF(name, name2, initCondition) name* m_##name2 = numberToPtr<name*>(kMaxPtrSize);
 #include <AnKi/Renderer/RendererObject.def.h>
 	/// @}
 

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

@@ -19,12 +19,13 @@ ANKI_RENDERER_OBJECT_DEF(VolumetricFog, volumetricFog, 1)
 ANKI_RENDERER_OBJECT_DEF(DepthDownscale, depthDownscale, 1)
 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(IndirectDiffuseProbes, indirectDiffuseProbes,
+						 !(GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled && g_rtIndirectDiffuseClipmapsCVar))
 ANKI_RENDERER_OBJECT_DEF(IndirectDiffuseClipmaps, indirectDiffuseClipmaps,
 						 GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled&& g_rtIndirectDiffuseClipmapsCVar)
-ANKI_RENDERER_OBJECT_DEF(ShadowmapsResolve, shadowmapsResolve, 1)
+ANKI_RENDERER_OBJECT_DEF(VolumetricLightingAccumulation, volumetricLightingAccumulation, 1)
 ANKI_RENDERER_OBJECT_DEF(RtShadows, rtShadows, GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled&& g_rayTracedShadowsCVar)
+ANKI_RENDERER_OBJECT_DEF(ShadowmapsResolve, shadowmapsResolve, 1)
 ANKI_RENDERER_OBJECT_DEF(AccelerationStructureBuilder, accelerationStructureBuilder,
 						 GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled
 							 && (g_rayTracedShadowsCVar || g_rtMaterialFetchDbgCVar || g_rtReflectionsCVar || g_rtIndirectDiffuseCVar

+ 11 - 0
AnKi/Renderer/RendererObject.h

@@ -132,6 +132,17 @@ protected:
 	{
 		return Renderer::getSingleton().m_dummyResources;
 	}
+
+#define ANKI_RENDERER_OBJECT_DEF(type, name, initCondition) \
+	ANKI_FORCE_INLINE type& get##type() \
+	{ \
+		return getRenderer().get##type(); \
+	} \
+	ANKI_FORCE_INLINE Bool is##type##Enabled() const \
+	{ \
+		return getRenderer().is##type##Enabled(); \
+	}
+#include <AnKi/Renderer/RendererObject.def.h>
 };
 
 class RtMaterialFetchRendererObject : protected RendererObject

+ 16 - 17
AnKi/Renderer/RtShadows.cpp

@@ -137,8 +137,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 	ANKI_TRACE_SCOPED_EVENT(RtShadows);
 
 #define ANKI_DEPTH_DEP \
-	getRenderer().getDepthDownscale().getRt(), TextureUsageBit::kSrvTraceRays | TextureUsageBit::kSrvCompute, \
-		DepthDownscale::kQuarterInternalResolution
+	getDepthDownscale().getRt(), TextureUsageBit::kSrvTraceRays | TextureUsageBit::kSrvCompute, DepthDownscale::kQuarterInternalResolution
 
 	RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
 
@@ -270,12 +269,12 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 												 AccelerationStructureUsageBit::kTraceRaysSrv);
 		rpass.newTextureDependency(ANKI_DEPTH_DEP);
 		rpass.newTextureDependency(getRenderer().getMotionVectors().getMotionVectorsRt(), TextureUsageBit::kSrvTraceRays);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSrvTraceRays);
+		rpass.newTextureDependency(getGBuffer().getColorRt(2), TextureUsageBit::kSrvTraceRays);
 
 		rpass.newTextureDependency(m_runCtx.m_prevMomentsRt, TextureUsageBit::kSrvTraceRays);
 		rpass.newTextureDependency(m_runCtx.m_currentMomentsRt, TextureUsageBit::kUavTraceRays);
 
-		rpass.newBufferDependency(getRenderer().getClusterBinning().getDependency(), BufferUsageBit::kSrvTraceRays);
+		rpass.newBufferDependency(getClusterBinning().getDependency(), BufferUsageBit::kSrvTraceRays);
 
 		rpass.setWork([this, sbtBuffer, &ctx](RenderPassWorkContext& rgraphCtx) {
 			ANKI_TRACE_SCOPED_EVENT(RtShadows);
@@ -312,10 +311,10 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 			rgraphCtx.bindUav(0, 2, m_runCtx.m_intermediateShadowsRts[0]);
 			rgraphCtx.bindSrv(0, 2, m_runCtx.m_historyRt);
 			cmdb.bindSampler(1, 2, getRenderer().getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindSrv(1, 2, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
+			rgraphCtx.bindSrv(1, 2, getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
 			rgraphCtx.bindSrv(2, 2, getRenderer().getMotionVectors().getMotionVectorsRt());
 			cmdb.bindSrv(3, 2, TextureView(m_dummyHistoryLenTex.get(), TextureSubresourceDesc::all()));
-			rgraphCtx.bindSrv(4, 2, getRenderer().getGBuffer().getColorRt(2));
+			rgraphCtx.bindSrv(4, 2, getGBuffer().getColorRt(2));
 			rgraphCtx.bindSrv(5, 2, getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle());
 			rgraphCtx.bindSrv(6, 2, m_runCtx.m_prevMomentsRt);
 			rgraphCtx.bindUav(1, 2, m_runCtx.m_currentMomentsRt);
@@ -337,7 +336,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 
 		rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[0], TextureUsageBit::kSrvCompute);
 		rpass.newTextureDependency(ANKI_DEPTH_DEP);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
 		rpass.newTextureDependency(m_runCtx.m_currentMomentsRt, TextureUsageBit::kSrvCompute);
 
 		rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[1], TextureUsageBit::kUavCompute);
@@ -353,7 +352,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 
 		rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[1], TextureUsageBit::kSrvCompute);
 		rpass.newTextureDependency(ANKI_DEPTH_DEP);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
 		rpass.newTextureDependency(m_runCtx.m_currentMomentsRt, TextureUsageBit::kSrvCompute);
 
 		rpass.newTextureDependency(m_runCtx.m_historyRt, TextureUsageBit::kUavCompute);
@@ -367,7 +366,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 		rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[0], TextureUsageBit::kSrvCompute);
 		rpass.newTextureDependency(m_runCtx.m_currentMomentsRt, TextureUsageBit::kSrvCompute);
 		rpass.newTextureDependency(ANKI_DEPTH_DEP);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
 
 		rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[1], TextureUsageBit::kUavCompute);
 		rpass.newTextureDependency(m_runCtx.m_varianceRts[1], TextureUsageBit::kUavCompute);
@@ -383,7 +382,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 			rgraphCtx.bindSrv(0, 0, m_runCtx.m_intermediateShadowsRts[0]);
 			rgraphCtx.bindSrv(1, 0, m_runCtx.m_currentMomentsRt);
 			cmdb.bindSrv(2, 0, TextureView(m_dummyHistoryLenTex.get(), TextureSubresourceDesc::all()));
-			rgraphCtx.bindSrv(3, 0, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
+			rgraphCtx.bindSrv(3, 0, getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
 
 			rgraphCtx.bindUav(0, 0, m_runCtx.m_intermediateShadowsRts[1]);
 			rgraphCtx.bindUav(1, 0, m_runCtx.m_varianceRts[1]);
@@ -406,7 +405,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 			NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("RtShadows SVGF Atrous");
 
 			rpass.newTextureDependency(ANKI_DEPTH_DEP);
-			rpass.newTextureDependency(getRenderer().getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
+			rpass.newTextureDependency(getGBuffer().getColorRt(2), TextureUsageBit::kSrvCompute);
 			rpass.newTextureDependency(m_runCtx.m_intermediateShadowsRts[readRtIdx], TextureUsageBit::kSrvCompute);
 			rpass.newTextureDependency(m_runCtx.m_varianceRts[readRtIdx], TextureUsageBit::kSrvCompute);
 
@@ -439,7 +438,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 
 				cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
 
-				rgraphCtx.bindSrv(0, 0, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
+				rgraphCtx.bindSrv(0, 0, getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
 				rgraphCtx.bindSrv(1, 0, m_runCtx.m_intermediateShadowsRts[readRtIdx]);
 				rgraphCtx.bindSrv(2, 0, m_runCtx.m_varianceRts[readRtIdx]);
 
@@ -466,7 +465,7 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 		NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("RtShadows Upscale");
 
 		rpass.newTextureDependency(m_runCtx.m_historyRt, TextureUsageBit::kSrvCompute);
-		rpass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
 		rpass.newTextureDependency(ANKI_DEPTH_DEP);
 
 		rpass.newTextureDependency(m_runCtx.m_upscaledRt, TextureUsageBit::kUavCompute);
@@ -481,8 +480,8 @@ void RtShadows::populateRenderGraph(RenderingContext& ctx)
 
 			rgraphCtx.bindSrv(0, 0, m_runCtx.m_historyRt);
 			rgraphCtx.bindUav(0, 0, m_runCtx.m_upscaledRt);
-			rgraphCtx.bindSrv(1, 0, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
-			rgraphCtx.bindSrv(2, 0, getRenderer().getGBuffer().getDepthRt());
+			rgraphCtx.bindSrv(1, 0, getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
+			rgraphCtx.bindSrv(2, 0, getGBuffer().getDepthRt());
 
 			dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
 		});
@@ -498,8 +497,8 @@ void RtShadows::runDenoise(const RenderingContext& ctx, RenderPassWorkContext& r
 
 	cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
 	rgraphCtx.bindSrv(0, 0, m_runCtx.m_intermediateShadowsRts[(horizontal) ? 0 : 1]);
-	rgraphCtx.bindSrv(1, 0, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
-	rgraphCtx.bindSrv(2, 0, getRenderer().getGBuffer().getColorRt(2));
+	rgraphCtx.bindSrv(1, 0, getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
+	rgraphCtx.bindSrv(2, 0, getGBuffer().getColorRt(2));
 	rgraphCtx.bindSrv(3, 0, m_runCtx.m_currentMomentsRt);
 	cmdb.bindSrv(4, 0, TextureView(m_dummyHistoryLenTex.get(), TextureSubresourceDesc::all()));
 

+ 1 - 1
AnKi/Renderer/ShadowMapping.cpp

@@ -469,7 +469,7 @@ void ShadowMapping::processLights(RenderingContext& ctx)
 		// HZB generation
 		HzbDirectionalLightInput hzbGenIn;
 		hzbGenIn.m_cascadeCount = cascadeCount;
-		hzbGenIn.m_depthBufferRt = getRenderer().getGBuffer().getDepthRt();
+		hzbGenIn.m_depthBufferRt = getGBuffer().getDepthRt();
 		hzbGenIn.m_depthBufferRtSize = getRenderer().getInternalResolution();
 		hzbGenIn.m_cameraProjectionMatrix = ctx.m_matrices.m_projection;
 		hzbGenIn.m_cameraInverseViewProjectionMatrix = ctx.m_matrices.m_invertedViewProjection;

+ 19 - 21
AnKi/Renderer/ShadowmapsResolve.cpp

@@ -28,7 +28,7 @@ Error ShadowmapsResolve::init()
 	for(MutatorValue quality = 0; quality < 3; ++quality)
 	{
 		ANKI_CHECK(loadShaderProgram("ShaderBinaries/ShadowmapsResolve.ankiprogbin",
-									 {{"QUALITY", quality}, {"DIRECTIONAL_LIGHT_SHADOW_RESOLVED", getRenderer().getRtShadowsEnabled()}}, m_prog,
+									 {{"QUALITY", quality}, {"DIRECTIONAL_LIGHT_SHADOW_RESOLVED", isRtShadowsEnabled()}}, m_prog,
 									 m_grProgs[quality]));
 	}
 
@@ -53,15 +53,14 @@ void ShadowmapsResolve::populateRenderGraph(RenderingContext& ctx)
 		});
 
 		rpass.newTextureDependency(m_runCtx.m_rt, TextureUsageBit::kUavCompute);
-		rpass.newTextureDependency((m_quarterRez) ? getRenderer().getDepthDownscale().getRt() : getRenderer().getGBuffer().getDepthRt(),
-								   TextureUsageBit::kSrvCompute);
-		rpass.newTextureDependency(getRenderer().getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency((m_quarterRez) ? getDepthDownscale().getRt() : getGBuffer().getDepthRt(), TextureUsageBit::kSrvCompute);
+		rpass.newTextureDependency(getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvCompute);
 
-		rpass.newBufferDependency(getRenderer().getClusterBinning().getDependency(), BufferUsageBit::kSrvCompute);
+		rpass.newBufferDependency(getClusterBinning().getDependency(), BufferUsageBit::kSrvCompute);
 
-		if(getRenderer().getRtShadowsEnabled())
+		if(isRtShadowsEnabled())
 		{
-			rpass.newTextureDependency(getRenderer().getRtShadows().getRt(), TextureUsageBit::kSrvCompute);
+			rpass.newTextureDependency(getRtShadows().getRt(), TextureUsageBit::kSrvCompute);
 		}
 	}
 	else
@@ -75,15 +74,14 @@ void ShadowmapsResolve::populateRenderGraph(RenderingContext& ctx)
 		});
 
 		rpass.newTextureDependency(m_runCtx.m_rt, TextureUsageBit::kRtvDsvWrite);
-		rpass.newTextureDependency((m_quarterRez) ? getRenderer().getDepthDownscale().getRt() : getRenderer().getGBuffer().getDepthRt(),
-								   TextureUsageBit::kSrvPixel);
-		rpass.newTextureDependency(getRenderer().getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvPixel);
+		rpass.newTextureDependency((m_quarterRez) ? getDepthDownscale().getRt() : getGBuffer().getDepthRt(), TextureUsageBit::kSrvPixel);
+		rpass.newTextureDependency(getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvPixel);
 
-		rpass.newBufferDependency(getRenderer().getClusterBinning().getDependency(), BufferUsageBit::kSrvPixel);
+		rpass.newBufferDependency(getClusterBinning().getDependency(), BufferUsageBit::kSrvPixel);
 
-		if(getRenderer().getRtShadowsEnabled())
+		if(isRtShadowsEnabled())
 		{
-			rpass.newTextureDependency(getRenderer().getRtShadows().getRt(), TextureUsageBit::kSrvPixel);
+			rpass.newTextureDependency(getRtShadows().getRt(), TextureUsageBit::kSrvPixel);
 		}
 	}
 }
@@ -109,10 +107,10 @@ void ShadowmapsResolve::run(RenderPassWorkContext& rgraphCtx, RenderingContext&
 	cmdb.bindShaderProgram(m_grProgs[quality].get());
 
 	cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
-	cmdb.bindSrv(0, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
-	cmdb.bindSrv(1, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
-	rgraphCtx.bindSrv(2, 0, getRenderer().getShadowMapping().getShadowmapRt());
-	cmdb.bindSrv(3, 0, getRenderer().getClusterBinning().getClustersBuffer());
+	cmdb.bindSrv(0, 0, getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
+	cmdb.bindSrv(1, 0, getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
+	rgraphCtx.bindSrv(2, 0, getShadowMapping().getShadowmapRt());
+	cmdb.bindSrv(3, 0, getClusterBinning().getClustersBuffer());
 
 	cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
 	cmdb.bindSampler(1, 0, getRenderer().getSamplers().m_trilinearClampShadow.get());
@@ -120,17 +118,17 @@ void ShadowmapsResolve::run(RenderPassWorkContext& rgraphCtx, RenderingContext&
 
 	if(m_quarterRez)
 	{
-		rgraphCtx.bindSrv(4, 0, getRenderer().getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
+		rgraphCtx.bindSrv(4, 0, getDepthDownscale().getRt(), DepthDownscale::kQuarterInternalResolution);
 	}
 	else
 	{
-		rgraphCtx.bindSrv(4, 0, getRenderer().getGBuffer().getDepthRt());
+		rgraphCtx.bindSrv(4, 0, getGBuffer().getDepthRt());
 	}
 	cmdb.bindSrv(5, 0, TextureView(&m_noiseImage->getTexture(), TextureSubresourceDesc::all()));
 
-	if(getRenderer().getRtShadowsEnabled())
+	if(isRtShadowsEnabled())
 	{
-		rgraphCtx.bindSrv(6, 0, getRenderer().getRtShadows().getRt());
+		rgraphCtx.bindSrv(6, 0, getRtShadows().getRt());
 	}
 
 	if(g_preferComputeCVar || g_shadowMappingPcfCVar || g_shadowMappingPcssCVar)

+ 6 - 7
AnKi/Renderer/Ssao.cpp

@@ -100,9 +100,8 @@ void Ssao::populateRenderGraph(RenderingContext& ctx)
 			ppass = &pass;
 		}
 
-		ppass->newTextureDependency(getRenderer().getGBuffer().getColorRt(2), readUsage);
-		ppass->newTextureDependency((g_ssaoQuarterRezCVar) ? getRenderer().getDepthDownscale().getRt() : getRenderer().getGBuffer().getDepthRt(),
-									readUsage);
+		ppass->newTextureDependency(getGBuffer().getColorRt(2), readUsage);
+		ppass->newTextureDependency((g_ssaoQuarterRezCVar) ? getDepthDownscale().getRt() : getGBuffer().getDepthRt(), readUsage);
 		ppass->newTextureDependency(finalRt, writeUsage);
 
 		ppass->setWork([this, &ctx, finalRt](RenderPassWorkContext& rgraphCtx) {
@@ -111,8 +110,8 @@ void Ssao::populateRenderGraph(RenderingContext& ctx)
 
 			cmdb.bindShaderProgram(m_grProg.get());
 
-			rgraphCtx.bindSrv(0, 0, getRenderer().getGBuffer().getColorRt(2));
-			rgraphCtx.bindSrv(1, 0, (g_ssaoQuarterRezCVar) ? getRenderer().getDepthDownscale().getRt() : getRenderer().getGBuffer().getDepthRt());
+			rgraphCtx.bindSrv(0, 0, getGBuffer().getColorRt(2));
+			rgraphCtx.bindSrv(1, 0, (g_ssaoQuarterRezCVar) ? getDepthDownscale().getRt() : getGBuffer().getDepthRt());
 
 			cmdb.bindSrv(2, 0, TextureView(&m_noiseImage->getTexture(), TextureSubresourceDesc::all()));
 			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
@@ -166,7 +165,7 @@ void Ssao::populateRenderGraph(RenderingContext& ctx)
 		}
 
 		ppass->newTextureDependency(finalRt, readUsage);
-		ppass->newTextureDependency(getRenderer().getGBuffer().getDepthRt(), readUsage);
+		ppass->newTextureDependency(getGBuffer().getDepthRt(), readUsage);
 		ppass->newTextureDependency(bentNormalsAndSsaoTempRt, writeUsage);
 
 		ppass->setWork([this, finalRt, bentNormalsAndSsaoTempRt, &ctx](RenderPassWorkContext& rgraphCtx) {
@@ -177,7 +176,7 @@ void Ssao::populateRenderGraph(RenderingContext& ctx)
 
 			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
 			rgraphCtx.bindSrv(0, 0, finalRt);
-			rgraphCtx.bindSrv(1, 0, getRenderer().getGBuffer().getDepthRt());
+			rgraphCtx.bindSrv(1, 0, getGBuffer().getDepthRt());
 
 			const UVec2 rez = (g_ssaoQuarterRezCVar) ? getRenderer().getInternalResolution() / 2u : getRenderer().getInternalResolution();
 

+ 1 - 1
AnKi/Renderer/TemporalAA.cpp

@@ -80,7 +80,7 @@ void TemporalAA::populateRenderGraph(RenderingContext& ctx)
 		prpass = &pass;
 	}
 
-	prpass->newTextureDependency(getRenderer().getGBuffer().getDepthRt(), readUsage);
+	prpass->newTextureDependency(getGBuffer().getDepthRt(), readUsage);
 	prpass->newTextureDependency(getRenderer().getLightShading().getRt(), readUsage);
 	prpass->newTextureDependency(m_runCtx.m_historyRt, readUsage);
 	prpass->newTextureDependency(getRenderer().getMotionVectors().getMotionVectorsRt(), readUsage);

+ 3 - 4
AnKi/Renderer/TemporalUpscaler.cpp

@@ -66,8 +66,7 @@ void TemporalUpscaler::populateRenderGraph(RenderingContext& ctx)
 
 		pass.newTextureDependency(getRenderer().getLightShading().getRt(), readUsage);
 		pass.newTextureDependency(getRenderer().getMotionVectors().getMotionVectorsRt(), readUsage);
-		pass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), readUsage,
-								  TextureSubresourceDesc::firstSurface(DepthStencilAspectBit::kDepth));
+		pass.newTextureDependency(getGBuffer().getDepthRt(), readUsage, TextureSubresourceDesc::firstSurface(DepthStencilAspectBit::kDepth));
 		pass.newTextureDependency(m_runCtx.m_rt, writeUsage);
 
 		pass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
@@ -84,8 +83,8 @@ void TemporalUpscaler::populateRenderGraph(RenderingContext& ctx)
 			const TextureView srcView = rgraphCtx.createTextureView(getRenderer().getLightShading().getRt(), TextureSubresourceDesc::firstSurface());
 			const TextureView motionVectorsView =
 				rgraphCtx.createTextureView(getRenderer().getMotionVectors().getMotionVectorsRt(), TextureSubresourceDesc::firstSurface());
-			const TextureView depthView = rgraphCtx.createTextureView(getRenderer().getGBuffer().getDepthRt(),
-																	  TextureSubresourceDesc::firstSurface(DepthStencilAspectBit::kDepth));
+			const TextureView depthView =
+				rgraphCtx.createTextureView(getGBuffer().getDepthRt(), TextureSubresourceDesc::firstSurface(DepthStencilAspectBit::kDepth));
 			const TextureView exposureView =
 				rgraphCtx.createTextureView(getRenderer().getTonemapping().getExposureAndAvgLuminanceRt(), TextureSubresourceDesc::firstSurface());
 			const TextureView dstView = rgraphCtx.createTextureView(m_runCtx.m_rt, TextureSubresourceDesc::firstSurface());

+ 48 - 14
AnKi/Renderer/VolumetricLightingAccumulation.cpp

@@ -6,6 +6,7 @@
 #include <AnKi/Renderer/VolumetricLightingAccumulation.h>
 #include <AnKi/Renderer/ShadowMapping.h>
 #include <AnKi/Renderer/IndirectDiffuseProbes.h>
+#include <AnKi/Renderer/IndirectDiffuseClipmaps.h>
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Renderer/ClusterBinning.h>
 #include <AnKi/Resource/ImageResource.h>
@@ -36,7 +37,8 @@ Error VolumetricLightingAccumulation::init()
 	ANKI_CHECK(ResourceManager::getSingleton().loadResource("EngineAssets/BlueNoise_Rgba8_64x64.png", m_noiseImage));
 
 	// Shaders
-	ANKI_CHECK(loadShaderProgram("ShaderBinaries/VolumetricLightingAccumulation.ankiprogbin", {{"ENABLE_SHADOWS", 1}}, m_prog, m_grProg));
+	ANKI_CHECK(loadShaderProgram("ShaderBinaries/VolumetricLightingAccumulation.ankiprogbin",
+								 {{"ENABLE_SHADOWS", 1}, {"CLIPMAP_DIFFUSE_INDIRECT", isIndirectDiffuseClipmapsEnabled()}}, m_prog, m_grProg));
 
 	// Create RTs
 	TextureInitInfo texinit = getRenderer().create2DRenderTargetInitInfo(
@@ -64,13 +66,23 @@ void VolumetricLightingAccumulation::populateRenderGraph(RenderingContext& ctx)
 
 	pass.newTextureDependency(m_runCtx.m_rts[0], TextureUsageBit::kSrvCompute);
 	pass.newTextureDependency(m_runCtx.m_rts[1], TextureUsageBit::kUavCompute);
-	pass.newTextureDependency(getRenderer().getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvCompute);
+	pass.newTextureDependency(getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvCompute);
 
-	pass.newBufferDependency(getRenderer().getClusterBinning().getDependency(), BufferUsageBit::kSrvCompute);
+	pass.newBufferDependency(getClusterBinning().getDependency(), BufferUsageBit::kSrvCompute);
 
-	if(getRenderer().getIndirectDiffuseProbes().hasCurrentlyRefreshedVolumeRt())
+	if(isIndirectDiffuseProbesEnabled() && getIndirectDiffuseProbes().hasCurrentlyRefreshedVolumeRt())
 	{
-		pass.newTextureDependency(getRenderer().getIndirectDiffuseProbes().getCurrentlyRefreshedVolumeRt(), TextureUsageBit::kSrvCompute);
+		pass.newTextureDependency(getIndirectDiffuseProbes().getCurrentlyRefreshedVolumeRt(), TextureUsageBit::kSrvCompute);
+	}
+
+	if(isIndirectDiffuseClipmapsEnabled())
+	{
+		for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
+		{
+			pass.newTextureDependency(getIndirectDiffuseClipmaps().getRts().m_avgIrradianceVolumes[i], TextureUsageBit::kSrvCompute);
+			pass.newTextureDependency(getIndirectDiffuseClipmaps().getRts().m_distanceMomentsVolumes[i], TextureUsageBit::kSrvCompute);
+			pass.newTextureDependency(getIndirectDiffuseClipmaps().getRts().m_probeValidityVolumes[i], TextureUsageBit::kSrvCompute);
+		}
 	}
 
 	pass.setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
@@ -86,17 +98,39 @@ void VolumetricLightingAccumulation::populateRenderGraph(RenderingContext& ctx)
 
 		rgraphCtx.bindUav(0, 0, m_runCtx.m_rts[1]);
 
-		cmdb.bindSrv(0, 0, TextureView(&m_noiseImage->getTexture(), TextureSubresourceDesc::all()));
+		cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
 
-		rgraphCtx.bindSrv(1, 0, m_runCtx.m_rts[0]);
+		U32 srv = 0;
+		cmdb.bindSrv(srv++, 0, TextureView(&m_noiseImage->getTexture(), TextureSubresourceDesc::all()));
+		rgraphCtx.bindSrv(srv++, 0, m_runCtx.m_rts[0]);
 
-		cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
-		cmdb.bindSrv(2, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
-		cmdb.bindSrv(3, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
-		rgraphCtx.bindSrv(4, 0, getRenderer().getShadowMapping().getShadowmapRt());
-		cmdb.bindSrv(5, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kGlobalIlluminationProbe));
-		cmdb.bindSrv(6, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kFogDensityVolume));
-		cmdb.bindSrv(7, 0, getRenderer().getClusterBinning().getClustersBuffer());
+		cmdb.bindSrv(srv++, 0, getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
+		cmdb.bindSrv(srv++, 0, getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
+		rgraphCtx.bindSrv(srv++, 0, getShadowMapping().getShadowmapRt());
+		cmdb.bindSrv(srv++, 0, getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kFogDensityVolume));
+		cmdb.bindSrv(srv++, 0, getClusterBinning().getClustersBuffer());
+
+		if(isIndirectDiffuseProbesEnabled())
+		{
+			cmdb.bindSrv(srv++, 0, getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kGlobalIlluminationProbe));
+		}
+		else
+		{
+			for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
+			{
+				rgraphCtx.bindSrv(srv++, 0, getIndirectDiffuseClipmaps().getRts().m_avgIrradianceVolumes[i]);
+			}
+
+			for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
+			{
+				rgraphCtx.bindSrv(srv++, 0, getIndirectDiffuseClipmaps().getRts().m_distanceMomentsVolumes[i]);
+			}
+
+			for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
+			{
+				rgraphCtx.bindSrv(srv++, 0, getIndirectDiffuseClipmaps().getRts().m_probeValidityVolumes[i]);
+			}
+		}
 
 		const SkyboxComponent* sky = SceneGraph::getSingleton().getSkybox();
 

+ 81 - 252
AnKi/Shaders/IndirectDiffuseClipmaps.ankiprog

@@ -6,7 +6,7 @@
 #pragma anki 16bit
 
 #pragma anki mutator GPU_WAVE_SIZE 16 32 64
-#pragma anki mutator RADIANCE_OCTAHEDRON_MAP_SIZE 8 10 12 14
+#pragma anki mutator RADIANCE_OCTAHEDRON_MAP_SIZE 8 10 12 14 16 18 20
 #pragma anki mutator IRRADIANCE_OCTAHEDRON_MAP_SIZE 4 5 6
 #pragma anki mutator RT_MATERIAL_FETCH_CLIPMAP 0 1
 
@@ -16,7 +16,7 @@
 #pragma anki technique Apply comp mutators
 #pragma anki technique VisualizeProbes vert pixel mutators
 
-// #define ANKI_ASSERTIONS_ENABLED 1
+#define ANKI_ASSERTIONS_ENABLED 1
 
 #include <AnKi/Shaders/Include/GpuSceneTypes.h>
 #include <AnKi/Shaders/Functions.hlsl>
@@ -24,66 +24,13 @@
 #include <AnKi/Shaders/ImportanceSampling.hlsl>
 #include <AnKi/Shaders/PackFunctions.hlsl>
 #include <AnKi/Shaders/FastMathFunctions.hlsl>
+#include <AnKi/Shaders/IndirectDiffuseClipmaps.hlsl>
 
 #if defined(RT_MATERIAL_FETCH_CLIPMAP) && RT_MATERIAL_FETCH_CLIPMAP
 #	define CLIPMAP_VOLUME
 #endif
 #include <AnKi/Shaders/RtMaterialFetch.hlsl>
 
-F32 computeClipmapFade(Clipmap clipmap, Vec3 cameraPos, Vec3 lookDir, Vec3 worldPos)
-{
-	const Vec3 offset = normalize(lookDir) * kIndirectDiffuseClipmapForwardBias * (clipmap.m_index + 1);
-	const Vec3 biasedCameraPos = cameraPos + offset;
-
-	const Vec3 probeSize = clipmap.m_size / clipmap.m_probeCounts;
-	const Vec3 halfSize = clipmap.m_size * 0.5;
-	const Vec3 aabbMin = biasedCameraPos - halfSize + probeSize;
-	const Vec3 aabbMax = biasedCameraPos + halfSize - probeSize;
-
-	const Vec3 distances = select(worldPos > cameraPos, aabbMax - cameraPos, cameraPos - aabbMin);
-
-	Vec3 a = abs(worldPos - cameraPos) / distances;
-	a = min(1.0, a);
-	a = pow(a, 32.0);
-	a = 1.0 - a;
-
-	F32 fade = a.x * a.y * a.z;
-
-	return fade;
-}
-
-Bool insideClipmap(Clipmap clipmap, Vec3 worldPos)
-{
-	return (all(worldPos < clipmap.m_aabbMin + clipmap.m_size) && all(worldPos > clipmap.m_aabbMin));
-}
-
-U16 findClipmapOnPosition(Clipmap clipmaps[kIndirectDiffuseClipmapCount], Vec3 cameraPos, Vec3 lookDir, Vec3 worldPos, F32 randFactor)
-{
-	for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
-	{
-		const F32 fade = computeClipmapFade(clipmaps[i], cameraPos, lookDir, worldPos);
-		if(fade > randFactor)
-		{
-			return i;
-		}
-	}
-
-	return kIndirectDiffuseClipmapCount;
-}
-
-U16 findClipmapOnPositionCheap(Clipmap clipmaps[kIndirectDiffuseClipmapCount], Vec3 worldPos)
-{
-	for(U32 i = 0; i < kIndirectDiffuseClipmapCount; ++i)
-	{
-		if(insideClipmap(clipmaps[i], worldPos))
-		{
-			return i;
-		}
-	}
-
-	return kIndirectDiffuseClipmapCount;
-}
-
 Vec2 generateRandomUv(U32 sampleIdx, U32 sampleCount, U32 frame)
 {
 	const UVec3 r = rand3DPCG16(UVec3(frame % 8u, frame % 4u, frame % 16u));
@@ -95,183 +42,6 @@ HVec3 generateRandomPointInSphere(U32 sampleIdx, U32 sampleCount, U32 frame)
 	return octahedronDecode(generateRandomUv(sampleIdx, sampleCount, frame));
 }
 
-/// Find out the clipmap for a given sample point and sample the probes in the volumes.
-Vec3 sampleClipmapIrradianceCommon(Vec3 samplePoint, Vec3 normal, Vec3 cameraPos, Vec3 lookDir, Clipmap clipmaps[kIndirectDiffuseClipmapCount],
-								   Texture3D<Vec4> volumes[kIndirectDiffuseClipmapCount],
-								   Texture3D<Vec4> distanceMomentsVolumes[kIndirectDiffuseClipmapCount],
-								   Texture3D<Vec4> probeValidityVolumes[kIndirectDiffuseClipmapCount], SamplerState linearAnyRepeatSampler,
-								   F32 slowVersionRandFactor, Bool fastVersion, Bool biasSamplePoint)
-{
-#if 1
-	const U16 clipmapIdx = (fastVersion) ? findClipmapOnPositionCheap(clipmaps, samplePoint)
-										 : findClipmapOnPosition(clipmaps, cameraPos, lookDir, samplePoint, slowVersionRandFactor);
-#else
-	U16 clipmapIdx = 0;
-	if(!insideClipmap(clipmaps[clipmapIdx], samplePoint))
-	{
-		clipmapIdx = 10;
-	}
-#endif
-
-#if 0
-	if(clipmapIdx == 0)
-	{
-		return Vec3(1, 0, 0);
-	}
-	else if(clipmapIdx == 1)
-	{
-		return Vec3(0, 1, 0);
-	}
-	else if(clipmapIdx == 2)
-	{
-		return Vec3(0, 0, 1);
-	}
-	else
-	{
-		return Vec3(1, 0, 1);
-	}
-#endif
-
-	if(clipmapIdx >= kIndirectDiffuseClipmapCount)
-	{
-		return 0.0;
-	}
-
-	const Clipmap clipmap = clipmaps[clipmapIdx];
-	const Vec3 probeSize = clipmap.m_size / clipmap.m_probeCounts;
-	const Vec3 fakeVolumeSize = clipmap.m_probeCounts; // Volume size without the octahedron
-
-	const Vec3 biasDir = normalize(cameraPos - samplePoint);
-	const Vec3 biasedWorldPos = (biasSamplePoint) ? samplePoint + biasDir * probeSize * 0.2 : samplePoint;
-
-	F32 octahedronSize = 0.0;
-	Vec3 realVolumeSize;
-	{
-		volumes[0].GetDimensions(realVolumeSize.x, realVolumeSize.y, realVolumeSize.z);
-
-		octahedronSize = realVolumeSize.x / clipmap.m_probeCounts.x;
-		octahedronSize -= 2.0; // The border
-	};
-	const F32 distMomentsOctSize = octahedronSize;
-	const Vec3 distMomentsRealVolumeSize = realVolumeSize;
-
-	const Vec3 samplePointUvw = frac(biasedWorldPos / clipmap.m_size);
-	const Vec3 icoord = floor(samplePointUvw * fakeVolumeSize - 0.5);
-	const Vec3 fcoord = frac(samplePointUvw * fakeVolumeSize - 0.5);
-
-	const Vec3 firstProbePosition = floor((biasedWorldPos - probeSize / 2.0) / probeSize) * probeSize + probeSize / 2.0;
-
-	F32 weightSum = 0.0;
-	Vec3 value = 0.0;
-	for(U32 i = 0u; i < 8u; ++i)
-	{
-		const Vec3 xyz = Vec3(UVec3(i, i >> 1u, i >> 2u) & 1u);
-		Vec3 coords = icoord + xyz;
-
-		// Repeat
-		coords = select(coords >= 0.0, coords, fakeVolumeSize + coords);
-		coords = select(coords < fakeVolumeSize, coords, coords - fakeVolumeSize);
-
-		if(!fastVersion)
-		{
-			const Bool valid = probeValidityVolumes[NonUniformResourceIndex(clipmapIdx)][coords.xzy].x > 0.8;
-			if(!valid)
-			{
-				continue;
-			}
-		}
-
-		// Reject probes outside the current clipmap. The accurate version doesn't need that because it fades between clipmaps.
-		const Vec3 probePosition = firstProbePosition + xyz * probeSize;
-		if(fastVersion)
-		{
-			if(!insideClipmap(clipmap, probePosition))
-			{
-				continue;
-			}
-		}
-
-		// Filtering weight
-		const Vec3 w3 = select(xyz == 0.0, 1.0 - fcoord, fcoord);
-		F32 w = w3.x * w3.y * w3.z;
-
-		// Normal weight
-		const Vec3 dir = normalize(probePosition - samplePoint);
-		const F32 wNormal = (dot(dir, normal) + 1.0) * 0.5;
-		w *= (wNormal * wNormal) + 0.2;
-
-		// Chebyshev occlusion
-		if(!fastVersion)
-		{
-			Vec3 uvw = coords.xzy;
-			uvw.xy *= distMomentsOctSize + 2.0;
-			uvw.xy += 1.0;
-			uvw.xy += octahedronEncode(normalize(biasedWorldPos - probePosition)) * distMomentsOctSize;
-			uvw.z += 0.5;
-			uvw /= distMomentsRealVolumeSize;
-			const Vec2 distMoments = distanceMomentsVolumes[NonUniformResourceIndex(clipmapIdx)].SampleLevel(linearAnyRepeatSampler, uvw, 0.0);
-
-			const F32 variance = abs(distMoments.x * distMoments.x - distMoments.y);
-
-			const F32 posToProbeDist = length(biasedWorldPos - probePosition);
-			F32 chebyshevWeight = 1.0;
-			if(posToProbeDist > distMoments.x) // occluded
-			{
-				// v must be greater than 0, which is guaranteed by the if condition above.
-				const F32 v = posToProbeDist - distMoments.x;
-				chebyshevWeight = variance / (variance + (v * v));
-
-				// Increase the contrast in the weight
-				chebyshevWeight = chebyshevWeight * chebyshevWeight * chebyshevWeight;
-				chebyshevWeight = max(chebyshevWeight, 0.05);
-			}
-
-			w *= chebyshevWeight;
-		}
-
-		// Compute the actual coords
-		Vec3 uvw = coords.xzy;
-		uvw.xy *= octahedronSize + 2.0;
-		uvw.xy += 1.0;
-		uvw.xy += octahedronEncode(normal) * octahedronSize;
-		uvw.z += 0.5;
-		uvw /= realVolumeSize;
-
-		const Vec3 ir = volumes[NonUniformResourceIndex(clipmapIdx)].SampleLevel(linearAnyRepeatSampler, uvw, 0.0);
-		value += ir * w;
-		weightSum += w;
-	}
-
-	if(weightSum > kEpsilonF32)
-	{
-		value /= weightSum;
-	}
-	else
-	{
-		value = 0.0;
-	}
-
-	return value;
-}
-
-Vec3 sampleClipmapIrradianceAccurate(Vec3 samplePoint, Vec3 normal, Vec3 cameraPos, Vec3 lookDir, Clipmap clipmaps[kIndirectDiffuseClipmapCount],
-									 Texture3D<Vec4> volumes[kIndirectDiffuseClipmapCount],
-									 Texture3D<Vec4> distanceMomentsVolumes[kIndirectDiffuseClipmapCount],
-									 Texture3D<Vec4> probeValidityVolumes[kIndirectDiffuseClipmapCount], SamplerState linearAnyRepeatSampler,
-									 F32 randFactor, Bool biasSamplePoint = true)
-{
-	return sampleClipmapIrradianceCommon(samplePoint, normal, cameraPos, lookDir, clipmaps, volumes, distanceMomentsVolumes, probeValidityVolumes,
-										 linearAnyRepeatSampler, randFactor, false, biasSamplePoint);
-}
-
-Vec3 sampleClipmapIrradianceCheap(Vec3 samplePoint, Vec3 normal, Clipmap clipmaps[kIndirectDiffuseClipmapCount],
-								  Texture3D<Vec4> volumes[kIndirectDiffuseClipmapCount], SamplerState linearAnyRepeatSampler,
-								  Bool biasSamplePoint = true)
-{
-	return sampleClipmapIrradianceCommon(samplePoint, normal, samplePoint, samplePoint, clipmaps, volumes, volumes, volumes, linearAnyRepeatSampler,
-										 0.0, true, biasSamplePoint);
-}
-
 // ===========================================================================
 // RtMaterialFetch                                                           =
 // ===========================================================================
@@ -346,7 +116,7 @@ ANKI_FAST_CONSTANTS(Consts, g_consts)
 			clipmaps[i] = g_globalRendererConstants.m_indirectDiffuseClipmaps[i];
 			clipmaps[i].m_aabbMin = clipmaps[i].m_prevFrameAabbMin;
 		}
-		const Vec3 irradiance = sampleClipmapIrradianceCheap(hitPos, gbuffer.m_worldNormal, clipmaps, g_irradianceVolumes, g_linearRepeatAnySampler);
+		const Vec3 irradiance = sampleClipmapIrradianceCheap(hitPos, gbuffer.m_worldNormal, clipmaps, g_irradianceVolumes, g_linearAnyRepeatSampler);
 #		endif
 
 		radiance += irradiance * gbuffer.m_diffuse / kPi;
@@ -414,7 +184,7 @@ ANKI_FAST_CONSTANTS(Consts, g_consts)
 	const Bool biasSamplePoint = !hit; // Bias the sample point if it's not for the 2nd bounce
 	const Vec3 irradiance = sampleClipmapIrradianceAccurate(
 		rayOrigin, rayDir2, g_globalRendererConstants.m_cameraPosition, lookDir, g_globalRendererConstants.m_indirectDiffuseClipmaps,
-		g_irradianceVolumes, g_distanceMomentsVolumes, g_probeValidityVolumes, g_linearRepeatAnySampler, randFactors.x, biasSamplePoint);
+		g_irradianceVolumes, g_distanceMomentsVolumes, g_probeValidityVolumes, g_linearAnyRepeatSampler, randFactors.x, biasSamplePoint);
 
 	Vec3 final;
 	if(hit)
@@ -426,7 +196,7 @@ ANKI_FAST_CONSTANTS(Consts, g_consts)
 		final = irradiance;
 	}
 
-	g_colorAndPdfTex[coord].xyz = lerp(g_colorAndPdfTex[coord].xyz, final, 0.2);
+	TEX(g_colorAndPdfTex, coord).xyz = final;
 }
 #	endif // RT_MATERIAL_FETCH_CLIPMAP
 #endif
@@ -609,6 +379,7 @@ constexpr U32 kThreadCount = min(32, GPU_WAVE_SIZE); // Keep it bellow 32 to avo
 Texture3D<Vec4> g_radianceVolumes[kIndirectDiffuseClipmapCount] : register(t0);
 
 RWTexture3D<Vec4> g_irradianceVolumes[kIndirectDiffuseClipmapCount] : register(u0);
+RWTexture3D<Vec4> g_avgIrradianceVolumes[kIndirectDiffuseClipmapCount] : register(u3);
 
 ConstantBuffer<GlobalRendererConstants> g_globalRendererConstants : register(b0);
 
@@ -616,6 +387,8 @@ SamplerState g_linearAnyRepeatSampler : register(s0);
 
 groupshared U64Vec3 g_irradianceResults[IRRADIANCE_OCTAHEDRON_MAP_SIZE][IRRADIANCE_OCTAHEDRON_MAP_SIZE];
 
+groupshared Vec3 g_avgIrradiance[kThreadCount];
+
 void InterlockedAddColor(U32 x, U32 y, Vec3 color)
 {
 	[unroll] for(U32 i = 0; i < 3; ++i)
@@ -710,6 +483,7 @@ Vec3 decodeAtomicColor(U32 x, U32 y)
 	GroupMemoryBarrierWithGroupSync();
 
 	// Write the irradiance
+	Vec3 threadAvgIrradiance = 0.0;
 	for(U32 pixel = svGroupIndex * irradiancePixelsPerThread; pixel < min(irradianceTexelCount, (svGroupIndex + 1) * irradiancePixelsPerThread);
 		++pixel)
 	{
@@ -725,6 +499,8 @@ Vec3 decodeAtomicColor(U32 x, U32 y)
 
 		const Vec3 irradiance = decodeAtomicColor(x, y) * k2Pi;
 
+		threadAvgIrradiance += irradiance / irradianceTexelCount;
+
 		TEX(g_irradianceVolumes[clipmapIdx], irradianceTexelCoord).xyz = irradiance;
 
 		// Write the borders
@@ -739,6 +515,30 @@ Vec3 decodeAtomicColor(U32 x, U32 y)
 			TEX(g_irradianceVolumes[clipmapIdx], actualVolumeTexCoord).xyz = irradiance;
 		}
 	}
+
+	g_avgIrradiance[svGroupIndex] = threadAvgIrradiance;
+
+	GroupMemoryBarrierWithGroupSync();
+
+	// Compute the avg radiance
+	[loop] for(U32 s = kThreadCount / 2u; s > 0u; s >>= 1u)
+	{
+		if(svGroupIndex < s)
+		{
+			g_avgIrradiance[svGroupIndex] += g_avgIrradiance[svGroupIndex + s];
+		}
+
+#	if ANKI_PLATFORM_MOBILE
+		if(s > WaveGetLaneCount())
+		{
+			GroupMemoryBarrierWithGroupSync();
+		}
+#	else
+		GroupMemoryBarrierWithGroupSync();
+#	endif
+	}
+
+	g_avgIrradianceVolumes[clipmapIdx][probeId.xzy].xyz = g_avgIrradiance[0];
 }
 #endif
 
@@ -754,6 +554,7 @@ Texture2D<Vec4> g_blueNoiseTex : register(t2);
 Texture3D<Vec4> g_clipmapVolumes[kIndirectDiffuseClipmapCount] : register(t3);
 Texture3D<Vec4> g_probeValidityVolumes[kIndirectDiffuseClipmapCount] : register(t6); // WARNING: Adjust if kIndirectDiffuseClipmapCount changed
 Texture3D<Vec4> g_distanceMomentsVolumes[kIndirectDiffuseClipmapCount] : register(t9);
+Texture3D<Vec4> g_avgIrradianceVolumes[kIndirectDiffuseClipmapCount] : register(t12);
 
 RWTexture2D<Vec4> g_outTex : register(u0);
 
@@ -789,14 +590,31 @@ SamplerState g_linearAnyRepeatSampler : register(s0);
 	const Mat3x4 cameraTrf = g_globalRendererConstants.m_matrices.m_cameraTransform;
 	const Vec3 lookDir = -Vec3(cameraTrf.m_row0[2], cameraTrf.m_row1[2], cameraTrf.m_row2[2]);
 
-#	if 1
-	const Vec3 irradiance = sampleClipmapIrradianceAccurate(worldPos, normal, g_globalRendererConstants.m_cameraPosition, lookDir,
-															g_globalRendererConstants.m_indirectDiffuseClipmaps, g_clipmapVolumes,
-															g_distanceMomentsVolumes, g_probeValidityVolumes, g_linearAnyRepeatSampler, noise);
-#	else
-	const Vec3 irradiance = sampleClipmapIrradianceCheap(worldPos, normal, g_globalRendererConstants.m_indirectDiffuseClipmaps, g_clipmapVolumes,
-														 g_linearAnyRepeatSampler);
-#	endif
+	const U32 method = 0;
+	Vec3 irradiance;
+	if(method == 0)
+	{
+		irradiance = sampleClipmapIrradianceAccurate(worldPos, normal, g_globalRendererConstants.m_cameraPosition, lookDir,
+													 g_globalRendererConstants.m_indirectDiffuseClipmaps, g_clipmapVolumes, g_distanceMomentsVolumes,
+													 g_probeValidityVolumes, g_linearAnyRepeatSampler, noise);
+	}
+	else if(method == 1)
+	{
+		irradiance = sampleClipmapIrradianceCheap(worldPos, normal, g_globalRendererConstants.m_indirectDiffuseClipmaps, g_clipmapVolumes,
+												  g_linearAnyRepeatSampler);
+	}
+	else if(method == 2)
+	{
+		irradiance = sampleClipmapAvgIrradianceAccurate(worldPos, normal, g_globalRendererConstants.m_cameraPosition, lookDir,
+														g_globalRendererConstants.m_indirectDiffuseClipmaps, g_avgIrradianceVolumes,
+														g_distanceMomentsVolumes, g_probeValidityVolumes, g_linearAnyRepeatSampler, noise);
+	}
+	else
+	{
+		irradiance = sampleClipmapAvgIrradianceCheap(worldPos, g_globalRendererConstants.m_cameraPosition, lookDir,
+													 g_globalRendererConstants.m_indirectDiffuseClipmaps, g_avgIrradianceVolumes, noise,
+													 g_linearAnyRepeatSampler, true);
+	}
 
 	TEX(g_outTex, svDispatchThreadId.xy).xyz = irradiance;
 }
@@ -906,22 +724,33 @@ FragOut main(VertOut input)
 	const Vec4 p = mul(g_globalRendererConstants.m_matrices.m_viewProjectionJitter, Vec4(collisionPoint, 1.0));
 	output.m_svDepth = p.z / p.w;
 
-	const Vec3 normal = normalize(collisionPoint - input.m_probeCenter);
-
 	UVec3 texSize;
 	g_volume.GetDimensions(texSize.x, texSize.y, texSize.z);
-	const U32 octProbeSize = texSize.x / clipmap.m_probeCounts.x - 2;
+
+	const Bool hasOctMap = texSize.x != clipmap.m_probeCounts.x;
 
 	Vec3 uvw = frac(input.m_probeCenter.xzy / clipmap.m_size.xzy);
 	const UVec3 texelCoord = uvw * clipmap.m_probeCounts.xzy;
 
-	uvw.xy = texelCoord.xy * (octProbeSize + 2);
-	uvw.xy += octahedronEncode(normal) * octProbeSize + 1.0;
-	uvw.xy /= clipmap.m_probeCounts.xz * (octProbeSize + 2);
+	if(hasOctMap)
+	{
+		const U32 octProbeSize = texSize.x / clipmap.m_probeCounts.x - 2;
+
+		const Vec3 normal = normalize(collisionPoint - input.m_probeCenter);
+
+		uvw.xy = texelCoord.xy * (octProbeSize + 2);
+		uvw.xy += octahedronEncode(normal) * octProbeSize + 1.0;
+		uvw.xy /= clipmap.m_probeCounts.xz * (octProbeSize + 2);
 
-	uvw.z = (texelCoord.z + 0.5) / clipmap.m_probeCounts.y;
+		uvw.z = (texelCoord.z + 0.5) / clipmap.m_probeCounts.y;
+	}
+	else
+	{
+		uvw = texelCoord + 0.5;
+		uvw /= texSize;
+	}
 
-	const Bool valid = g_probeValidityVolume[texelCoord].x > 0.9;
+	const Bool valid = TEX(g_probeValidityVolume, texelCoord).x > 0.9;
 	Vec3 radiance;
 	if(valid)
 	{

+ 4 - 4
AnKi/Shaders/IndirectDiffuseClipmaps.hlsl

@@ -171,7 +171,7 @@ Vec3 sampleClipmapIrradianceCommon(SampleClipmapsConfig cfg, SampleClipmapsArgs
 
 		if(cfg.m_doInvalidProbeRejection)
 		{
-			const Bool valid = probeValidityVolumes[NonUniformResourceIndex(clipmapIdx)][coords.xzy].x > 0.8;
+			const Bool valid = TEX(probeValidityVolumes[NonUniformResourceIndex(clipmapIdx)], coords.xzy).x > 0.8;
 			if(!valid)
 			{
 				continue;
@@ -244,7 +244,7 @@ Vec3 sampleClipmapIrradianceCommon(SampleClipmapsConfig cfg, SampleClipmapsArgs
 		}
 		else
 		{
-			v = primaryVolumes[NonUniformResourceIndex(clipmapIdx)][coords.xzy];
+			v = TEX(primaryVolumes[NonUniformResourceIndex(clipmapIdx)], coords.xzy);
 		}
 
 		value += v * w;
@@ -295,9 +295,9 @@ Vec3 sampleClipmapIrradianceCheap(Vec3 samplePoint, Vec3 normal, Clipmap clipmap
 	cfg.m_biasSamplePoint = biasSamplePoint;
 	cfg.m_doChebyshevOcclusion = false;
 	cfg.m_doInvalidProbeRejection = false;
-	cfg.m_fastClipmapSelection = false;
+	cfg.m_fastClipmapSelection = true;
 	cfg.m_primaryVolumesHaveOctMap = true;
-	cfg.m_normalRejection = false;
+	cfg.m_normalRejection = true;
 
 	SampleClipmapsArgs args;
 	args.m_cameraPos = 0.0;

+ 30 - 31
AnKi/Shaders/Reflections.ankiprog

@@ -54,36 +54,6 @@ enum
 };
 
 // Functions
-template<typename T>
-vector<T, 3> getDiffuseIndirect(StructuredBuffer<GpuSceneGlobalIlluminationProbe> giProbes, Vec3 worldPos, Vec3 worldNormal,
-								SamplerState linearAnyClampSampler)
-{
-	const U32 probeCount = getStructuredBufferElementCount(giProbes);
-	U32 i;
-	for(i = 0; i < probeCount; ++i)
-	{
-		if(any(worldPos >= giProbes[i].m_aabbMax) || any(worldPos <= giProbes[i].m_aabbMin))
-		{
-			continue;
-		}
-		else
-		{
-			break;
-		}
-	}
-
-	const Bool probeFound = (i != probeCount);
-	if(probeFound)
-	{
-		const GpuSceneGlobalIlluminationProbe probe = giProbes[i];
-		return sampleGlobalIllumination<T>(worldPos, worldNormal, probe, getBindlessTexture3DVec4(probe.m_volumeTexture), linearAnyClampSampler);
-	}
-	else
-	{
-		return T(0);
-	}
-}
-
 HVec4 encodeColorDepthAndSampleCount(HVec3 color, F16 depth, U32 sampleCount)
 {
 	HVec4 signs;
@@ -650,6 +620,35 @@ struct Consts
 };
 ANKI_FAST_CONSTANTS(Consts, g_consts)
 
+template<typename T>
+vector<T, 3> getDiffuseIndirect(Vec3 worldPos, Vec3 worldNormal)
+{
+	const U32 probeCount = getStructuredBufferElementCount(g_giProbes);
+	U32 i;
+	for(i = 0; i < probeCount; ++i)
+	{
+		if(any(worldPos >= g_giProbes[i].m_aabbMax) || any(worldPos <= g_giProbes[i].m_aabbMin))
+		{
+			continue;
+		}
+		else
+		{
+			break;
+		}
+	}
+
+	const Bool probeFound = (i != probeCount);
+	if(probeFound)
+	{
+		const GpuSceneGlobalIlluminationProbe probe = g_giProbes[i];
+		return sampleGlobalIllumination<T>(worldPos, worldNormal, probe, getBindlessTexture3DVec4(probe.m_volumeTexture), g_linearClampAnySampler);
+	}
+	else
+	{
+		return T(0);
+	}
+}
+
 [shader("raygeneration")] void main()
 {
 	UVec2 halfViewportSize;
@@ -691,7 +690,7 @@ ANKI_FAST_CONSTANTS(Consts, g_consts)
 
 	if(!hasHitSky && g_consts.m_giProbeCount > 0)
 	{
-		const HVec3 indirectDiffuse = getDiffuseIndirect<F16>(g_giProbes, hitPos, gbuffer.m_worldNormal, g_linearClampAnySampler);
+		const HVec3 indirectDiffuse = getDiffuseIndirect<F16>(hitPos, gbuffer.m_worldNormal);
 		radiance += gbuffer.m_diffuse * indirectDiffuse;
 	}
 

+ 58 - 72
AnKi/Shaders/VolumetricLightingAccumulation.ankiprog

@@ -5,12 +5,17 @@
 
 // This shader accumulates the lighting for every cluster fraction
 
+#pragma anki 16bit
+
 #pragma anki mutator ENABLE_SHADOWS 0 1
+#pragma anki mutator CLIPMAP_DIFFUSE_INDIRECT 0 1
 
 #pragma anki technique comp
 
 #include <AnKi/Shaders/Include/MiscRendererTypes.h>
 #include <AnKi/Shaders/ClusteredShadingFunctions.hlsl>
+#include <AnKi/Shaders/IndirectDiffuseClipmaps.hlsl>
+#include <AnKi/Shaders/ImportanceSampling.hlsl>
 
 constexpr F32 kPhaseFunctionAnisotropy = 0.3;
 
@@ -22,45 +27,41 @@ RWTexture3D<Vec4> g_volume : register(u0);
 Texture2D<Vec4> g_noiseTex : register(t0);
 Texture3D<Vec4> g_prevVolume : register(t1);
 
-ConstantBuffer<GlobalRendererConstants> g_globalConstants : register(b0);
 StructuredBuffer<PointLight> g_pointLights : register(t2);
 StructuredBuffer<SpotLight> g_spotLights : register(t3);
 Texture2D<Vec4> g_shadowAtlasTex : register(t4);
-StructuredBuffer<GlobalIlluminationProbe> g_giProbes : register(t5);
-StructuredBuffer<FogDensityVolume> g_fogDensityVolumes : register(t6);
-StructuredBuffer<Cluster> g_clusters : register(t7);
+StructuredBuffer<FogDensityVolume> g_fogDensityVolumes : register(t5);
+StructuredBuffer<Cluster> g_clusters : register(t6);
+#if CLIPMAP_DIFFUSE_INDIRECT
+Texture3D<Vec4> g_avgIrradianceVolumes[kIndirectDiffuseClipmapCount] : register(t7);
+Texture3D<Vec4> g_probeValidityVolumes[kIndirectDiffuseClipmapCount] : register(t10);
+Texture3D<Vec4> g_distanceMomentsVolumes[kIndirectDiffuseClipmapCount] : register(t13);
+#else
+StructuredBuffer<GlobalIlluminationProbe> g_giProbes : register(t7);
+#endif
 
-ANKI_FAST_CONSTANTS(VolumetricLightingConstants, g_fogUnis)
+ConstantBuffer<GlobalRendererConstants> g_globalConstants : register(b0);
 
-static Vec3 g_svDispatchThreadId;
+ANKI_FAST_CONSTANTS(VolumetricLightingConstants, g_consts)
 
-Vec3 readRand()
+Vec3 worldPosInsideClusterAndZViewSpace(Vec3 relativePos, Vec3 clusterIdf, out F32 negativeZViewSpace, out Vec3 uvw)
 {
-	Vec3 random = g_noiseTex.SampleLevel(g_linearAnyRepeatSampler, (g_svDispatchThreadId.xy + 0.5) / 64.0, 0.0).rgb;
-	random = animateBlueNoise(random, g_globalConstants.m_frame);
+	// XY UV
+	uvw.xy = lerp(clusterIdf.xy, clusterIdf.xy + 1.0, relativePos.xy) / Vec2(g_consts.m_volumeSize.xy);
 
-	return random;
-}
-
-Vec3 worldPosInsideClusterAndZViewSpace(Vec3 relativePos, out F32 negativeZViewSpace, out Vec3 uvw)
-{
 	// Compute the linear depth
-	const F32 maxLinearDepth = g_fogUnis.m_maxZSplitsToProcessf / F32(g_globalConstants.m_zSplitCount);
-	const F32 linearDepthFraction = maxLinearDepth / F32(g_fogUnis.m_volumeSize.z);
-	const F32 linearDepthNear = g_svDispatchThreadId.z * linearDepthFraction;
-	const F32 linearDepthFar = (g_svDispatchThreadId.z + 1.0) * linearDepthFraction;
+	const F32 maxLinearDepth = g_consts.m_maxZSplitsToProcessf / F32(g_globalConstants.m_zSplitCount);
+	const F32 linearDepthFraction = maxLinearDepth / F32(g_consts.m_volumeSize.z);
+	const F32 linearDepthNear = clusterIdf.z * linearDepthFraction;
+	const F32 linearDepthFar = (clusterIdf.z + 1.0) * linearDepthFraction;
 	const F32 linearDepth = lerp(linearDepthNear, linearDepthFar, relativePos.z);
 	uvw.z = linearDepth;
 
-	// Z view space
+	// View space
 	negativeZViewSpace =
 		linearDepth * (g_globalConstants.m_matrices.m_far - g_globalConstants.m_matrices.m_near) + g_globalConstants.m_matrices.m_near;
 	const F32 zViewSpace = -negativeZViewSpace;
-
-	// Get the position in view space
-	const Vec2 uv = lerp(g_svDispatchThreadId.xy, g_svDispatchThreadId.xy + 1.0, relativePos.xy) / Vec2(g_fogUnis.m_volumeSize.xy);
-	uvw.xy = uv;
-	const Vec2 xyViewSpace = uvToNdc(uv) * g_globalConstants.m_matrices.m_unprojectionParameters.xy * zViewSpace;
+	const Vec2 xyViewSpace = uvToNdc(uvw.xy) * g_globalConstants.m_matrices.m_unprojectionParameters.xy * zViewSpace;
 
 	// Get the final world pos
 	const Vec3 worldPos = mul(g_globalConstants.m_matrices.m_cameraTransform, Vec4(xyViewSpace, zViewSpace, 1.0));
@@ -68,11 +69,11 @@ Vec3 worldPosInsideClusterAndZViewSpace(Vec3 relativePos, out F32 negativeZViewS
 	return worldPos;
 }
 
-Vec3 worldPosInsideCluster(Vec3 relativePos)
+Vec3 worldPosInsideCluster(Vec3 relativePos, Vec3 clusterIdf)
 {
 	F32 unused;
 	Vec3 unused1;
-	return worldPosInsideClusterAndZViewSpace(relativePos, unused, unused1);
+	return worldPosInsideClusterAndZViewSpace(relativePos, clusterIdf, unused, unused1);
 }
 
 // https://developer.nvidia.com/gpugems/GPUGems2/gpugems2_chapter16.html
@@ -88,7 +89,7 @@ F32 phaseFunction(Vec3 viewDir, Vec3 lightDir, F32 g)
 	return saturate(a * b);
 }
 
-Vec4 accumulateLightsAndFog(Cluster cluster, Vec3 worldPos, F32 negativeZViewSpace)
+Vec4 accumulateLightsAndFog(Cluster cluster, Vec3 worldPos, F32 negativeZViewSpace, F32 noise)
 {
 	ANKI_MAYBE_UNUSED(negativeZViewSpace);
 
@@ -146,7 +147,7 @@ Vec4 accumulateLightsAndFog(Cluster cluster, Vec3 worldPos, F32 negativeZViewSpa
 
 		const Vec3 l = normalize(frag2Light);
 
-		factor *= computeSpotFactor<RF32>(l, light.m_outerCos, light.m_innerCos, light.m_direction);
+		factor *= computeSpotFactor<F32>(l, light.m_outerCos, light.m_innerCos, light.m_direction);
 
 		factor *= phaseFunction(viewDir, light.m_direction, kPhaseFunctionAnisotropy);
 
@@ -161,59 +162,42 @@ Vec4 accumulateLightsAndFog(Cluster cluster, Vec3 worldPos, F32 negativeZViewSpa
 	}
 
 	// Indirect diffuse GI
+#if CLIPMAP_DIFFUSE_INDIRECT
 	{
-		Vec3 diffIndirect;
+		const Mat3x4 cameraTrf = g_globalConstants.m_matrices.m_cameraTransform;
+		const Vec3 lookDir = -Vec3(cameraTrf.m_row0[2], cameraTrf.m_row1[2], cameraTrf.m_row2[2]);
 
-		const U32 oneProbe = WaveActiveAllTrue(countbits(cluster.m_giProbesMask) == 1);
-		if(oneProbe)
+		Vec3 irradiance;
+		if(1)
 		{
-			// Only one probe, do a fast path without blend weight
-
-			const GlobalIlluminationProbe probe = g_giProbes[firstbitlow2(cluster.m_giProbesMask)];
-
-			// Sample
-			diffIndirect =
-				sampleGlobalIllumination<F32>(worldPos, viewDir, probe, getBindlessTexture3DVec4(probe.m_volumeTexture), g_linearAnyClampSampler);
+			irradiance =
+				sampleClipmapAvgIrradianceCheap(worldPos, g_globalConstants.m_cameraPosition, lookDir, g_globalConstants.m_indirectDiffuseClipmaps,
+												g_avgIrradianceVolumes, noise, g_linearAnyRepeatSampler, false);
 		}
 		else
 		{
-			// Zero or more than one probes, do a slow path that blends them together
-
-			F32 totalBlendWeight = kEpsilonF32;
-			diffIndirect = 0.0;
-
-			// Loop probes
-			[loop] while(cluster.m_giProbesMask != 0u)
-			{
-				const U32 idx = U32(firstbitlow2(cluster.m_giProbesMask));
-				cluster.m_giProbesMask &= ~(1u << idx);
-				const GlobalIlluminationProbe probe = g_giProbes[idx];
-
-				// Compute blend weight
-				const F32 blendWeight = computeProbeBlendWeight(worldPos, probe.m_aabbMin, probe.m_aabbMax, probe.m_fadeDistance);
-				totalBlendWeight += blendWeight;
-
-				// Sample
-				const Vec3 c = sampleGlobalIllumination<F32>(worldPos, viewDir, probe, getBindlessTextureNonUniformIndex3DVec4(probe.m_volumeTexture),
-															 g_linearAnyClampSampler);
-				diffIndirect += c * blendWeight;
-			}
-
-			// Normalize
-			diffIndirect /= totalBlendWeight;
+			irradiance = sampleClipmapAvgIrradianceAccurate(
+				worldPos, 0.0, g_globalConstants.m_cameraPosition, lookDir, g_globalConstants.m_indirectDiffuseClipmaps, g_avgIrradianceVolumes,
+				g_distanceMomentsVolumes, g_probeValidityVolumes, g_linearAnyRepeatSampler, noise, false, false);
 		}
 
+		color += irradiance * kPi; // Not sure why the multiplication with Pi but it looks more correct
+	}
+#else
+	{
+		Vec3 diffIndirect = sampleGiProbes<F32>(cluster, g_giProbes, viewDir, worldPos, g_linearAnyClampSampler);
 		diffIndirect *= kPi; // Irradiance is pre-divided with PI so fix it
 
 		color += diffIndirect;
 	}
+#endif
 
 	// Fog density
 	F32 fogDensity = 0.0;
 	{
 		// Calculate the constant density
-		const F32 fogFactor = saturate((worldPos.y - g_fogUnis.m_minHeight) * g_fogUnis.m_oneOverMaxMinusMinHeight);
-		fogDensity = lerp(g_fogUnis.m_densityAtMinHeight, g_fogUnis.m_densityAtMaxHeight, fogFactor);
+		const F32 fogFactor = saturate((worldPos.y - g_consts.m_minHeight) * g_consts.m_oneOverMaxMinusMinHeight);
+		fogDensity = lerp(g_consts.m_densityAtMinHeight, g_consts.m_densityAtMaxHeight, fogFactor);
 
 		[loop] while(cluster.m_fogDensityVolumesMask != 0u)
 		{
@@ -243,17 +227,19 @@ Vec4 accumulateLightsAndFog(Cluster cluster, Vec3 worldPos, F32 negativeZViewSpa
 
 [numthreads(8, 8, 8)] void main(UVec3 svDispatchThreadId : SV_DISPATCHTHREADID)
 {
-	if(any(svDispatchThreadId >= g_fogUnis.m_volumeSize))
+	const UVec3 clusterId = svDispatchThreadId;
+	if(any(clusterId >= g_consts.m_volumeSize))
 	{
 		return;
 	}
 
-	g_svDispatchThreadId = svDispatchThreadId;
-
 	// Find a random pos inside the cluster
+	Vec3 random = TEX(g_noiseTex, (clusterId.xy + clusterId.z) % 64).rgb;
+	random = animateBlueNoise(random, g_globalConstants.m_frame);
+
 	F32 negativeZViewSpace;
 	Vec3 uvw;
-	const Vec3 worldPos = worldPosInsideClusterAndZViewSpace(readRand(), negativeZViewSpace, uvw);
+	const Vec3 worldPos = worldPosInsideClusterAndZViewSpace(random, clusterId, negativeZViewSpace, uvw);
 
 	// Get the cluster
 	const UVec2 tileIdxXY = UVec2(uvw.xy * Vec2(g_globalConstants.m_tileCounts));
@@ -266,12 +252,12 @@ Vec4 accumulateLightsAndFog(Cluster cluster, Vec3 worldPos, F32 negativeZViewSpa
 	cluster = mergeClusters(cluster, split);
 
 	// Get lighting
-	Vec4 lightAndFog = accumulateLightsAndFog(cluster, worldPos, negativeZViewSpace);
+	Vec4 lightAndFog = accumulateLightsAndFog(cluster, worldPos, negativeZViewSpace, random.x);
 
 	// Read the prev result
 	{
 		// Better get a new world pos in the center of the cluster. Using worldPos creates noisy results
-		const Vec3 midWPos = worldPosInsideCluster(Vec3(0.5, 0.5, 0.5));
+		const Vec3 midWPos = worldPosInsideCluster(Vec3(0.5, 0.5, 0.5), clusterId);
 
 		// Project
 		const Vec4 prevClipPos4 = mul(g_globalConstants.m_previousMatrices.m_viewProjection, Vec4(midWPos, 1.0));
@@ -281,12 +267,12 @@ Vec4 accumulateLightsAndFog(Cluster cluster, Vec3 worldPos, F32 negativeZViewSpa
 		if(all(prevClipPos.xy > -1.0) && all(prevClipPos.xy < 1.0))
 		{
 			const F32 linearDepth = linearizeDepth(prevClipPos.z, g_globalConstants.m_matrices.m_near, g_globalConstants.m_matrices.m_far);
-			const Vec3 uvw = Vec3(ndcToUv(prevClipPos.xy), linearDepth * (F32(g_globalConstants.m_zSplitCount) / g_fogUnis.m_maxZSplitsToProcessf));
+			const Vec3 uvw = Vec3(ndcToUv(prevClipPos.xy), linearDepth * (F32(g_globalConstants.m_zSplitCount) / g_consts.m_maxZSplitsToProcessf));
 			const Vec4 history = g_prevVolume.SampleLevel(g_linearAnyClampSampler, uvw, 0.0);
 			lightAndFog = lerp(history, lightAndFog, 1.0 / 16.0);
 		}
 	}
 
 	// Write result
-	g_volume[svDispatchThreadId] = lightAndFog;
+	TEX(g_volume, clusterId) = lightAndFog;
 }