Browse Source

Add the skeleton for RT indirect diffuse

Panagiotis Christopoulos Charitos 11 months ago
parent
commit
15958fc98c

+ 203 - 0
AnKi/Renderer/IndirectDiffuse.cpp

@@ -0,0 +1,203 @@
+// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <AnKi/Renderer/IndirectDiffuse.h>
+#include <AnKi/Renderer/Renderer.h>
+#include <AnKi/Renderer/AccelerationStructureBuilder.h>
+#include <AnKi/Renderer/GBuffer.h>
+#include <AnKi/Renderer/Sky.h>
+#include <AnKi/Renderer/ShadowMapping.h>
+#include <AnKi/Util/Tracer.h>
+#include <AnKi/Core/GpuMemory/UnifiedGeometryBuffer.h>
+#include <AnKi/Shaders/Include/MaterialTypes.h>
+#include <AnKi/Scene/Components/SkyboxComponent.h>
+
+namespace anki {
+
+Error IndirectDiffuse::init()
+{
+	const Bool bRt = GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled && g_rtIndirectDiffuseCVar;
+
+	ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/IndirectDiffuse.ankiprogbin", m_mainProg));
+
+	if(bRt)
+	{
+		ShaderProgramResourceVariantInitInfo variantInitInfo(m_mainProg);
+		variantInitInfo.requestTechniqueAndTypes(ShaderTypeBit::kRayGen, "RtMaterialFetch");
+		const ShaderProgramResourceVariant* variant;
+		m_mainProg->getOrCreateVariant(variantInitInfo, variant);
+		m_libraryGrProg.reset(&variant->getProgram());
+		m_rayGenShaderGroupIdx = variant->getShaderGroupHandleIndex();
+
+		ShaderProgramResourceVariantInitInfo variantInitInfo2(m_mainProg);
+		variantInitInfo2.requestTechniqueAndTypes(ShaderTypeBit::kMiss, "RtMaterialFetch");
+		m_mainProg->getOrCreateVariant(variantInitInfo2, variant);
+		m_missShaderGroupIdx = variant->getShaderGroupHandleIndex();
+
+		ANKI_CHECK(loadShaderProgram("ShaderBinaries/RtSbtBuild.ankiprogbin", {{"TECHNIQUE", 1}}, m_sbtProg, m_sbtBuildGrProg, "SbtBuild"));
+
+		m_sbtRecordSize = getAlignedRoundUp(GrManager::getSingleton().getDeviceCapabilities().m_sbtRecordAlignment,
+											GrManager::getSingleton().getDeviceCapabilities().m_shaderGroupHandleSize + U32(sizeof(UVec4)));
+	}
+
+	m_transientRtDesc1 = getRenderer().create2DRenderTargetDescription(
+		getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y(), Format::kR16G16B16A16_Sfloat, "IndirectDiffuse #1");
+	m_transientRtDesc1.bake();
+
+	return Error::kNone;
+}
+
+void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
+{
+	ANKI_TRACE_SCOPED_EVENT(IndirectDiffuse);
+
+	const Bool bRt = GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled && g_rtIndirectDiffuseCVar;
+
+	if(!bRt)
+	{
+		return;
+	}
+
+	RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
+
+	const RenderTargetHandle transientRt1 = rgraph.newRenderTarget(m_transientRtDesc1);
+
+	// SBT build
+	BufferHandle sbtHandle;
+	BufferView sbtBuffer;
+	{
+		BufferHandle visibilityDep;
+		BufferView visibleRenderableIndicesBuff, buildSbtIndirectArgsBuff;
+		getRenderer().getAccelerationStructureBuilder().getVisibilityInfo(visibilityDep, visibleRenderableIndicesBuff, buildSbtIndirectArgsBuff);
+
+		// Allocate SBT
+		U32 sbtAlignment = (GrManager::getSingleton().getDeviceCapabilities().m_structuredBufferNaturalAlignment)
+							   ? sizeof(U32)
+							   : GrManager::getSingleton().getDeviceCapabilities().m_structuredBufferBindOffsetAlignment;
+		sbtAlignment = computeCompoundAlignment(sbtAlignment, GrManager::getSingleton().getDeviceCapabilities().m_sbtRecordAlignment);
+		U8* sbtMem;
+		sbtBuffer = RebarTransientMemoryPool::getSingleton().allocate(
+			(GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount() + 2) * m_sbtRecordSize, sbtAlignment, sbtMem);
+		sbtHandle = rgraph.importBuffer(sbtBuffer, BufferUsageBit::kNone);
+
+		// Write the first 2 entries of the SBT
+		ConstWeakArray<U8> shaderGroupHandles = m_libraryGrProg->getShaderGroupHandles();
+		const U32 shaderHandleSize = GrManager::getSingleton().getDeviceCapabilities().m_shaderGroupHandleSize;
+		memcpy(sbtMem, &shaderGroupHandles[m_rayGenShaderGroupIdx * shaderHandleSize], shaderHandleSize);
+		memcpy(sbtMem + m_sbtRecordSize, &shaderGroupHandles[m_missShaderGroupIdx * shaderHandleSize], shaderHandleSize);
+
+		// Create the pass
+		NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("RtIndirectDiffuse build SBT");
+
+		rpass.newBufferDependency(visibilityDep, BufferUsageBit::kIndirectCompute | BufferUsageBit::kSrvCompute);
+		rpass.newBufferDependency(sbtHandle, BufferUsageBit::kUavCompute);
+
+		rpass.setWork([this, buildSbtIndirectArgsBuff, sbtBuffer, visibleRenderableIndicesBuff](RenderPassWorkContext& rgraphCtx) {
+			ANKI_TRACE_SCOPED_EVENT(IndirectDiffuse);
+			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
+
+			cmdb.bindShaderProgram(m_sbtBuildGrProg.get());
+
+			cmdb.bindSrv(0, 0, GpuSceneArrays::Renderable::getSingleton().getBufferView());
+			cmdb.bindSrv(1, 0, visibleRenderableIndicesBuff);
+			cmdb.bindSrv(2, 0, BufferView(&m_libraryGrProg->getShaderGroupHandlesGpuBuffer()));
+
+			cmdb.bindUav(0, 0, sbtBuffer);
+
+			RtShadowsSbtBuildConstants consts = {};
+			ANKI_ASSERT(m_sbtRecordSize % 4 == 0);
+			consts.m_sbtRecordDwordSize = m_sbtRecordSize / 4;
+			const U32 shaderHandleSize = GrManager::getSingleton().getDeviceCapabilities().m_shaderGroupHandleSize;
+			ANKI_ASSERT(shaderHandleSize % 4 == 0);
+			consts.m_shaderHandleDwordSize = shaderHandleSize / 4;
+			cmdb.setFastConstants(&consts, sizeof(consts));
+
+			cmdb.dispatchComputeIndirect(buildSbtIndirectArgsBuff);
+		});
+	}
+
+	// Ray gen
+	{
+		NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("RtIndirectDiffuse");
+
+		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);
+		if(getRenderer().getGeneratedSky().isEnabled())
+		{
+			rpass.newTextureDependency(getRenderer().getGeneratedSky().getEnvironmentMapRt(), TextureUsageBit::kSrvTraceRays);
+		}
+		rpass.newTextureDependency(getRenderer().getShadowMapping().getShadowmapRt(), TextureUsageBit::kSrvTraceRays);
+		rpass.newAccelerationStructureDependency(getRenderer().getAccelerationStructureBuilder().getAccelerationStructureHandle(),
+												 AccelerationStructureUsageBit::kTraceRaysSrv);
+
+		rpass.setWork([this, sbtBuffer, &ctx, transientRt1](RenderPassWorkContext& rgraphCtx) {
+			ANKI_TRACE_SCOPED_EVENT(Reflections);
+			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
+
+			cmdb.bindShaderProgram(m_libraryGrProg.get());
+
+			// More globals
+			cmdb.bindSampler(ANKI_MATERIAL_REGISTER_TILINEAR_REPEAT_SAMPLER, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
+			cmdb.bindSrv(ANKI_MATERIAL_REGISTER_GPU_SCENE, 0, GpuSceneBuffer::getSingleton().getBufferView());
+			cmdb.bindSrv(ANKI_MATERIAL_REGISTER_MESH_LODS, 0, GpuSceneArrays::MeshLod::getSingleton().getBufferView());
+			cmdb.bindSrv(ANKI_MATERIAL_REGISTER_TRANSFORMS, 0, GpuSceneArrays::Transform::getSingleton().getBufferView());
+
+#define ANKI_UNIFIED_GEOM_FORMAT(fmt, shaderType, reg) \
+	cmdb.bindSrv( \
+		reg, 0, \
+		BufferView(&UnifiedGeometryBuffer::getSingleton().getBuffer(), 0, \
+				   getAlignedRoundDown(getFormatInfo(Format::k##fmt).m_texelSize, UnifiedGeometryBuffer::getSingleton().getBuffer().getSize())), \
+		Format::k##fmt);
+#include <AnKi/Shaders/Include/UnifiedGeometryTypes.def.h>
+
+			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));
+
+			const LightComponent* dirLight = SceneGraph::getSingleton().getDirectionalLight();
+			const SkyboxComponent* sky = SceneGraph::getSingleton().getSkybox();
+			const Bool bSkySolidColor =
+				(!sky || sky->getSkyboxType() == SkyboxType::kSolidColor || (!dirLight && sky->getSkyboxType() == SkyboxType::kGenerated));
+			if(bSkySolidColor)
+			{
+				cmdb.bindSrv(4, 2, TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDesc::all()));
+			}
+			else if(sky->getSkyboxType() == SkyboxType::kImage2D)
+			{
+				cmdb.bindSrv(4, 2, TextureView(&sky->getImageResource().getTexture(), TextureSubresourceDesc::all()));
+			}
+			else
+			{
+				rgraphCtx.bindSrv(4, 2, getRenderer().getGeneratedSky().getEnvironmentMapRt());
+			}
+
+			cmdb.bindSrv(5, 2, GpuSceneArrays::GlobalIlluminationProbe::getSingleton().getBufferView());
+			cmdb.bindSrv(6, 2, BufferView(&getRenderer().getDummyBuffer()));
+			rgraphCtx.bindSrv(7, 2, getRenderer().getShadowMapping().getShadowmapRt());
+
+			rgraphCtx.bindUav(0, 2, transientRt1);
+			cmdb.bindUav(1, 2, TextureView(&getRenderer().getDummyTexture2d(), TextureSubresourceDesc::all()));
+
+			cmdb.bindSampler(0, 2, getRenderer().getSamplers().m_trilinearClamp.get());
+			cmdb.bindSampler(1, 2, getRenderer().getSamplers().m_trilinearClampShadow.get());
+
+			UVec4 dummyConsts;
+			cmdb.setFastConstants(&dummyConsts, sizeof(dummyConsts));
+
+			cmdb.traceRays(sbtBuffer, m_sbtRecordSize, GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount(), 1,
+						   getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y(), 1);
+		});
+	}
+
+	m_runCtx.m_rt = transientRt1;
+}
+
+} // end namespace anki

+ 60 - 0
AnKi/Renderer/IndirectDiffuse.h

@@ -0,0 +1,60 @@
+// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <AnKi/Renderer/RendererObject.h>
+
+namespace anki {
+
+/// @addtogroup renderer
+/// @{
+
+inline BoolCVar g_rtIndirectDiffuseCVar("R", "RtIndirectDiffuse", false, "Enable RT GI");
+
+class IndirectDiffuse : public RendererObject
+{
+public:
+	IndirectDiffuse()
+	{
+		registerDebugRenderTarget("IndirectDiffuse");
+	}
+
+	Error init();
+
+	void populateRenderGraph(RenderingContext& ctx);
+
+	void getDebugRenderTarget([[maybe_unused]] CString rtName, Array<RenderTargetHandle, kMaxDebugRenderTargets>& handles,
+							  [[maybe_unused]] ShaderProgramPtr& optionalShaderProgram) const override
+	{
+		handles[0] = m_runCtx.m_rt;
+	}
+
+	RenderTargetHandle getRt() const
+	{
+		return m_runCtx.m_rt;
+	}
+
+public:
+	ShaderProgramResourcePtr m_sbtProg;
+	ShaderProgramResourcePtr m_mainProg;
+	ShaderProgramPtr m_sbtBuildGrProg;
+	ShaderProgramPtr m_libraryGrProg;
+
+	U32 m_sbtRecordSize = 0;
+	U32 m_rayGenShaderGroupIdx = 0;
+	U32 m_missShaderGroupIdx = 0;
+
+	RenderTargetDesc m_transientRtDesc1;
+
+	class
+	{
+	public:
+		RenderTargetHandle m_rt;
+	} m_runCtx;
+};
+/// @}
+
+} // namespace anki

+ 18 - 2
AnKi/Renderer/LightShading.cpp

@@ -18,6 +18,7 @@
 #include <AnKi/Renderer/ClusterBinning.h>
 #include <AnKi/Renderer/ClusterBinning.h>
 #include <AnKi/Renderer/Ssao.h>
 #include <AnKi/Renderer/Ssao.h>
 #include <AnKi/Renderer/Reflections.h>
 #include <AnKi/Renderer/Reflections.h>
+#include <AnKi/Renderer/IndirectDiffuse.h>
 #include <AnKi/Util/CVarSet.h>
 #include <AnKi/Util/CVarSet.h>
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Scene/Components/SkyboxComponent.h>
 #include <AnKi/Scene/Components/SkyboxComponent.h>
@@ -29,7 +30,10 @@ Error LightShading::init()
 {
 {
 	{
 	{
 		// Load shaders and programs
 		// Load shaders and programs
-		ANKI_CHECK(loadShaderProgram("ShaderBinaries/LightShading.ankiprogbin", m_lightShading.m_prog, m_lightShading.m_grProg));
+		ANKI_CHECK(loadShaderProgram(
+			"ShaderBinaries/LightShading.ankiprogbin",
+			{{"INDIRECT_DIFFUSE_TEX", GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled && g_rtIndirectDiffuseCVar}},
+			m_lightShading.m_prog, m_lightShading.m_grProg));
 
 
 		// Create RT descr
 		// Create RT descr
 		const UVec2 internalResolution = getRenderer().getInternalResolution();
 		const UVec2 internalResolution = getRenderer().getInternalResolution();
@@ -82,7 +86,14 @@ void LightShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgrap
 		cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
 		cmdb.bindConstantBuffer(0, 0, ctx.m_globalRenderingConstantsBuffer);
 		cmdb.bindSrv(0, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
 		cmdb.bindSrv(0, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
 		cmdb.bindSrv(1, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
 		cmdb.bindSrv(1, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kLight));
-		cmdb.bindSrv(2, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kGlobalIlluminationProbe));
+		if(GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled && g_rtIndirectDiffuseCVar)
+		{
+			rgraphCtx.bindSrv(2, 0, getRenderer().getIndirectDiffuse().getRt());
+		}
+		else
+		{
+			cmdb.bindSrv(2, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kGlobalIlluminationProbe));
+		}
 		cmdb.bindSrv(3, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kReflectionProbe));
 		cmdb.bindSrv(3, 0, getRenderer().getClusterBinning().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kReflectionProbe));
 		cmdb.bindSrv(4, 0, getRenderer().getClusterBinning().getClustersBuffer());
 		cmdb.bindSrv(4, 0, getRenderer().getClusterBinning().getClustersBuffer());
 
 
@@ -264,6 +275,11 @@ void LightShading::populateRenderGraph(RenderingContext& ctx)
 	pass.newTextureDependency(getRenderer().getSsao().getRt(), readUsage);
 	pass.newTextureDependency(getRenderer().getSsao().getRt(), readUsage);
 	pass.newTextureDependency(getRenderer().getReflections().getRt(), readUsage);
 	pass.newTextureDependency(getRenderer().getReflections().getRt(), readUsage);
 
 
+	if(GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled && g_rtIndirectDiffuseCVar)
+	{
+		pass.newTextureDependency(getRenderer().getIndirectDiffuse().getRt(), TextureUsageBit::kSrvPixel);
+	}
+
 	// Fog
 	// Fog
 	pass.newTextureDependency(getRenderer().getVolumetricFog().getRt(), readUsage);
 	pass.newTextureDependency(getRenderer().getVolumetricFog().getRt(), readUsage);
 
 

+ 5 - 7
AnKi/Renderer/Reflections.cpp

@@ -53,6 +53,9 @@ Error Reflections::init()
 		variantInitInfo2.addMutation("SSR_SAMPLE_GBUFFER", bSsrSamplesGBuffer);
 		variantInitInfo2.addMutation("SSR_SAMPLE_GBUFFER", bSsrSamplesGBuffer);
 		m_mainProg->getOrCreateVariant(variantInitInfo2, variant);
 		m_mainProg->getOrCreateVariant(variantInitInfo2, variant);
 		m_missShaderGroupIdx = variant->getShaderGroupHandleIndex();
 		m_missShaderGroupIdx = variant->getShaderGroupHandleIndex();
+
+		m_sbtRecordSize = getAlignedRoundUp(GrManager::getSingleton().getDeviceCapabilities().m_sbtRecordAlignment,
+											GrManager::getSingleton().getDeviceCapabilities().m_shaderGroupHandleSize + U32(sizeof(UVec4)));
 	}
 	}
 
 
 	ANKI_CHECK(loadShaderProgram("ShaderBinaries/Reflections.ankiprogbin", mutation, m_mainProg, m_spatialDenoisingGrProg, "SpatialDenoise"));
 	ANKI_CHECK(loadShaderProgram("ShaderBinaries/Reflections.ankiprogbin", mutation, m_mainProg, m_spatialDenoisingGrProg, "SpatialDenoise"));
@@ -65,11 +68,6 @@ Error Reflections::init()
 	ANKI_CHECK(loadShaderProgram("ShaderBinaries/Reflections.ankiprogbin", mutation, m_mainProg, m_probeFallbackGrProg, "ReflectionProbeFallback"));
 	ANKI_CHECK(loadShaderProgram("ShaderBinaries/Reflections.ankiprogbin", mutation, m_mainProg, m_probeFallbackGrProg, "ReflectionProbeFallback"));
 	ANKI_CHECK(loadShaderProgram("ShaderBinaries/Reflections.ankiprogbin", mutation, m_mainProg, m_tileClassificationGrProg, "Classification"));
 	ANKI_CHECK(loadShaderProgram("ShaderBinaries/Reflections.ankiprogbin", mutation, m_mainProg, m_tileClassificationGrProg, "Classification"));
 
 
-	m_sbtRecordSize = (bRtReflections)
-						  ? getAlignedRoundUp(GrManager::getSingleton().getDeviceCapabilities().m_sbtRecordAlignment,
-											  GrManager::getSingleton().getDeviceCapabilities().m_shaderGroupHandleSize + U32(sizeof(UVec4)))
-						  : 0;
-
 	m_transientRtDesc1 = getRenderer().create2DRenderTargetDescription(
 	m_transientRtDesc1 = getRenderer().create2DRenderTargetDescription(
 		getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y(), Format::kR16G16B16A16_Sfloat, "Reflections #1");
 		getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y(), Format::kR16G16B16A16_Sfloat, "Reflections #1");
 	m_transientRtDesc1.bake();
 	m_transientRtDesc1.bake();
@@ -258,10 +256,10 @@ void Reflections::populateRenderGraph(RenderingContext& ctx)
 	// SBT build
 	// SBT build
 	BufferHandle sbtHandle;
 	BufferHandle sbtHandle;
 	BufferView sbtBuffer;
 	BufferView sbtBuffer;
-	BufferHandle visibilityDep;
-	BufferView visibleRenderableIndicesBuff, buildSbtIndirectArgsBuff;
 	if(bRtReflections)
 	if(bRtReflections)
 	{
 	{
+		BufferHandle visibilityDep;
+		BufferView visibleRenderableIndicesBuff, buildSbtIndirectArgsBuff;
 		getRenderer().getAccelerationStructureBuilder().getVisibilityInfo(visibilityDep, visibleRenderableIndicesBuff, buildSbtIndirectArgsBuff);
 		getRenderer().getAccelerationStructureBuilder().getVisibilityInfo(visibilityDep, visibleRenderableIndicesBuff, buildSbtIndirectArgsBuff);
 
 
 		// Allocate SBT
 		// Allocate SBT

+ 2 - 1
AnKi/Renderer/Renderer.cpp

@@ -48,6 +48,7 @@
 #include <AnKi/Renderer/MotionBlur.h>
 #include <AnKi/Renderer/MotionBlur.h>
 #include <AnKi/Renderer/RtMaterialFetchDbg.h>
 #include <AnKi/Renderer/RtMaterialFetchDbg.h>
 #include <AnKi/Renderer/Reflections.h>
 #include <AnKi/Renderer/Reflections.h>
+#include <AnKi/Renderer/IndirectDiffuse.h>
 #include <AnKi/Renderer/Utils/Drawer.h>
 #include <AnKi/Renderer/Utils/Drawer.h>
 #include <AnKi/Renderer/Utils/GpuVisibility.h>
 #include <AnKi/Renderer/Utils/GpuVisibility.h>
 #include <AnKi/Renderer/Utils/MipmapGenerator.h>
 #include <AnKi/Renderer/Utils/MipmapGenerator.h>
@@ -294,7 +295,7 @@ Error Renderer::populateRenderGraph(RenderingContext& ctx)
 	{
 	{
 		m_rtMaterialFetchDbg->populateRenderGraph(ctx);
 		m_rtMaterialFetchDbg->populateRenderGraph(ctx);
 	}
 	}
-
+	m_indirectDiffuse->populateRenderGraph(ctx);
 	m_reflections->populateRenderGraph(ctx);
 	m_reflections->populateRenderGraph(ctx);
 	m_shadowmapsResolve->populateRenderGraph(ctx);
 	m_shadowmapsResolve->populateRenderGraph(ctx);
 	m_volumetricFog->populateRenderGraph(ctx);
 	m_volumetricFog->populateRenderGraph(ctx);

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

@@ -38,6 +38,7 @@ ANKI_RENDERER_OBJECT_DEF(MotionBlur, motionBlur, 1)
 ANKI_RENDERER_OBJECT_DEF(RtMaterialFetchDbg, rtMaterialFetchDbg,
 ANKI_RENDERER_OBJECT_DEF(RtMaterialFetchDbg, rtMaterialFetchDbg,
 						 GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled&& g_rtMaterialFetchDbgCVar)
 						 GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled&& g_rtMaterialFetchDbgCVar)
 ANKI_RENDERER_OBJECT_DEF(Reflections, reflections, 1)
 ANKI_RENDERER_OBJECT_DEF(Reflections, reflections, 1)
+ANKI_RENDERER_OBJECT_DEF(IndirectDiffuse, indirectDiffuse, 1)
 
 
 // Util objects
 // Util objects
 ANKI_RENDERER_OBJECT_DEF(RenderableDrawer, drawer, 1)
 ANKI_RENDERER_OBJECT_DEF(RenderableDrawer, drawer, 1)

+ 2 - 2
AnKi/Renderer/Utils/GpuVisibility.cpp

@@ -1110,7 +1110,7 @@ void GpuVisibilityAccelerationStructures::pupulateRenderGraph(GpuVisibilityAccel
 	const U32 aabbCount = GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount();
 	const U32 aabbCount = GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount();
 
 
 	out.m_instancesBuffer = allocateStructuredBuffer<AccelerationStructureInstance>(aabbCount);
 	out.m_instancesBuffer = allocateStructuredBuffer<AccelerationStructureInstance>(aabbCount);
-	out.m_dependency = rgraph.importBuffer(out.m_instancesBuffer, BufferUsageBit::kUavCompute);
+	out.m_dependency = rgraph.importBuffer(out.m_instancesBuffer, BufferUsageBit::kNone);
 
 
 	out.m_renderablesBuffer = allocateStructuredBuffer<LodAndRenderableIndex>(aabbCount + 1);
 	out.m_renderablesBuffer = allocateStructuredBuffer<LodAndRenderableIndex>(aabbCount + 1);
 
 
@@ -1157,7 +1157,7 @@ void GpuVisibilityAccelerationStructures::pupulateRenderGraph(GpuVisibilityAccel
 			cmdb.bindSrv(3, 0, GpuSceneArrays::Transform::getSingleton().getBufferView());
 			cmdb.bindSrv(3, 0, GpuSceneArrays::Transform::getSingleton().getBufferView());
 			cmdb.bindUav(0, 0, instancesBuff);
 			cmdb.bindUav(0, 0, instancesBuff);
 			cmdb.bindUav(1, 0, visRenderablesBuff);
 			cmdb.bindUav(1, 0, visRenderablesBuff);
-			cmdb.bindUav(2, 0, BufferView(m_counterBuffer.get(), 0, sizeof(U32) * 2));
+			cmdb.bindUav(2, 0, BufferView(m_counterBuffer.get()));
 			cmdb.bindUav(3, 0, zeroInstancesAndSbtBuildDispatchArgsBuff);
 			cmdb.bindUav(3, 0, zeroInstancesAndSbtBuildDispatchArgsBuff);
 
 
 			const U32 aabbCount = GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount();
 			const U32 aabbCount = GpuSceneArrays::RenderableBoundingVolumeRt::getSingleton().getElementCount();

+ 1 - 1
AnKi/Shaders/ImportanceSampling.hlsl

@@ -49,7 +49,7 @@ Vec2 hammersleyRandom16(U32 sampleIdx, U32 sampleCount, UVec2 random)
 }
 }
 
 
 /// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
 /// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
-/// From a uniform 2D point inside a circle get a 3D point in the surface of a hemisphere. It's oriented in the z axis
+/// From a uniform 2D point inside a circle get a 3D point in the surface of a hemisphere. It's oriented in the +Z. uv is in [0, 1]
 Vec3 hemisphereSampleUniform(Vec2 uv)
 Vec3 hemisphereSampleUniform(Vec2 uv)
 {
 {
 	const F32 phi = uv.y * 2.0 * kPi;
 	const F32 phi = uv.y * 2.0 * kPi;

+ 191 - 0
AnKi/Shaders/IndirectDiffuse.ankiprog

@@ -0,0 +1,191 @@
+// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma anki 16bit
+
+#pragma anki technique RtMaterialFetch rgen miss
+
+#include <AnKi/Shaders/RtMaterialFetch.hlsl>
+#include <AnKi/Shaders/Include/GpuSceneTypes.h>
+#include <AnKi/Shaders/PackFunctions.hlsl>
+#include <AnKi/Shaders/ImportanceSampling.hlsl>
+#include <AnKi/Shaders/Functions.hlsl>
+#include <AnKi/Shaders/LightFunctions.hlsl>
+
+// Config and consts
+constexpr Bool kTryShadowmapFirst = true;
+
+// Functions
+Vec3 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<F32>(worldPos, worldNormal, probe, getBindlessTexture3DVec4(probe.m_volumeTexture), linearAnyClampSampler);
+	}
+	else
+	{
+		return 0.0;
+	}
+}
+
+// ===========================================================================
+// RayGen                                                                    =
+// ===========================================================================
+#if ANKI_RAY_GEN_SHADER
+
+[Shader("raygeneration")] void main()
+{
+	Vec2 outSize;
+	g_colorAndPdfTex.GetDimensions(outSize.x, outSize.y);
+
+	const UVec2 coord = DispatchRaysIndex().xy;
+	const Vec2 uv = Vec2(coord) / outSize;
+
+	const F32 depth = g_depthTex[coord].x;
+	const Vec4 rt2 = g_gbufferRt2[coord];
+	const Vec3 worldNormal = unpackNormalFromGBuffer(rt2);
+
+#	if 0
+	const Vec4 v4 = mul(g_globalRendererConstants.m_matrices.m_invertedViewProjectionJitter, Vec4(uvToNdc(uv), depth, 1.0));
+	const Vec3 worldPos = v4.xyz / v4.w;
+
+	// Rand
+	const UVec3 seed = rand3DPCG16(UVec3(coord, g_globalRendererConstants.m_frame % 8u));
+	const Vec2 randFactors = hammersleyRandom16(g_globalRendererConstants.m_frame % 64u, 64u, seed);
+
+	const Vec3 rayOrigin = worldPos;
+
+	const Mat3 tbn = rotationFromDirection(worldNormal);
+	const Vec3 rayDir = mul(tbn, hemisphereSampleCos(randFactors));
+#	else
+	const Vec4 v4 = mul(g_globalRendererConstants.m_matrices.m_invertedViewProjectionJitter, Vec4(uvToNdc(uv), 1.0, 1.0));
+	const Vec3 worldPos = v4.xyz / v4.w;
+
+	const Vec3 rayOrigin = g_globalRendererConstants.m_matrices.m_cameraTransform.getTranslationPart().xyz;
+	const Vec3 rayDir = normalize(worldPos - rayOrigin);
+#	endif
+
+	// Trace
+	RtMaterialFetchRayPayload payload;
+	payload = (RtMaterialFetchRayPayload)0;
+	payload.m_textureLod = 100.0;
+	const U32 flags = RAY_FLAG_FORCE_OPAQUE;
+	const U32 sbtRecordOffset = 0u;
+	const U32 sbtRecordStride = 0u;
+	const U32 missIndex = 0u;
+	const U32 cullMask = 0xFFu;
+	RayDesc ray;
+	ray.Origin = rayOrigin;
+	ray.TMin = 0.1;
+	ray.Direction = rayDir;
+	ray.TMax = 100.0; // TODO
+	TraceRay(g_tlas, flags, cullMask, sbtRecordOffset, sbtRecordStride, missIndex, ray, payload);
+
+#	if 1
+	g_colorAndPdfTex[coord] = Vec4(payload.m_diffuseColor * 0.0 + payload.m_worldNormal * 0.0 + payload.m_rayT * 0.0 + payload.m_emission * 1.0, 0.0);
+	return;
+#	endif
+
+	const Bool hasHitSky = payload.m_rayT < 0.0;
+	if(hasHitSky)
+	{
+		payload.m_rayT = 100.0; // TODO
+	}
+
+	const Vec3 hitPos = worldPos + rayDir * payload.m_rayT;
+
+	const DirectionalLight dirLight = g_globalRendererConstants.m_directionalLight;
+
+	// Trace shadow
+	Vec4 vv4 = mul(g_globalRendererConstants.m_matrices.m_viewProjection, Vec4(hitPos, 1.0));
+	vv4.xy /= vv4.w;
+	const Bool bInsideFrustum = all(vv4.xy > -1.0) && all(vv4.xy < 1.0) && vv4.w > 0.0;
+
+	F32 shadow = 0.0;
+	if(hasHitSky)
+	{
+		// Skybox
+		shadow = 1.0;
+
+		if(g_globalRendererConstants.m_sky.m_type == 0)
+		{
+			payload.m_emission = g_globalRendererConstants.m_sky.m_solidColor;
+		}
+		else
+		{
+			const Vec2 uv = (g_globalRendererConstants.m_sky.m_type == 1) ? equirectangularMapping(rayDir) : octahedronEncode(rayDir);
+			payload.m_emission = g_envMap.SampleLevel(g_linearClampAnySampler, uv, 0.0).xyz;
+		}
+	}
+	else if(bInsideFrustum && kTryShadowmapFirst)
+	{
+		const F32 negativeZViewSpace = -mul(g_globalRendererConstants.m_matrices.m_view, Vec4(hitPos, 1.0)).z;
+		const U32 shadowCascadeCount = dirLight.m_shadowCascadeCount_31bit_active_1bit >> 1u;
+
+		const U32 cascadeIdx = computeShadowCascadeIndex(negativeZViewSpace, dirLight.m_shadowCascadeDistances, shadowCascadeCount);
+
+		shadow = computeShadowFactorDirLight<F32>(dirLight, cascadeIdx, hitPos, g_shadowAtlasTex, g_shadowSampler);
+	}
+	else
+	{
+		constexpr U32 qFlags = RAY_FLAG_FORCE_OPAQUE | RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH;
+		RayQuery<qFlags> q;
+		RayDesc ray;
+		ray.Origin = worldPos + rayDir * (payload.m_rayT - 0.01);
+		ray.TMin = 0.01;
+		ray.Direction = -dirLight.m_direction;
+		ray.TMax = 100.0; // TODO
+		q.TraceRayInline(g_tlas, qFlags, cullMask, ray);
+		q.Proceed();
+		shadow = (q.CommittedStatus() == COMMITTED_TRIANGLE_HIT) ? 0.0 : 1.0;
+	}
+
+	// Do simple light shading
+	Vec3 outColor = payload.m_emission;
+	Vec3 indirectDiffuse = 0.0;
+	if(!hasHitSky)
+	{
+		indirectDiffuse = getDiffuseIndirect(g_giProbes, hitPos, payload.m_worldNormal, g_linearClampAnySampler);
+	}
+	// outColor += payload.m_diffuseColor * indirectDiffuse;
+
+	const Vec3 l = -dirLight.m_direction;
+	const F32 lambert = max(0.0, dot(l, payload.m_worldNormal));
+	const Vec3 diffC = diffuseLobe(payload.m_diffuseColor);
+	outColor += diffC * dirLight.m_diffuseColor * lambert * shadow;
+
+	g_colorAndPdfTex[coord] = Vec4(outColor, 0.0);
+}
+#endif // ANKI_RAY_GEN_SHADER
+
+// ===========================================================================
+// Miss                                                                      =
+// ===========================================================================
+#if ANKI_MISS_SHADER
+	[Shader("miss")] void main(inout RtMaterialFetchRayPayload payload)
+{
+	payload.m_diffuseColor = 0.0;
+	payload.m_worldNormal = 0.0;
+	payload.m_emission = 0.0;
+	payload.m_rayT = -1.0;
+}
+#endif // ANKI_MISS_SHADER

+ 3 - 0
AnKi/Shaders/Intellisense.hlsl

@@ -25,6 +25,7 @@
 #define in
 #define in
 #define inout
 #define inout
 #define discard return
 #define discard return
+#define Shader(x)
 
 
 #define ANKI_BEGIN_NAMESPACE
 #define ANKI_BEGIN_NAMESPACE
 #define ANKI_END_NAMESPACE
 #define ANKI_END_NAMESPACE
@@ -295,6 +296,8 @@ void DispatchMesh(U32 groupSizeX, U32 groupSizeY, U32 groupSizeZ, T payload);
 
 
 void SetMeshOutputCounts(U32 vertexCount, U32 primitiveCount);
 void SetMeshOutputCounts(U32 vertexCount, U32 primitiveCount);
 
 
+UVec2 DispatchRaysIndex();
+
 // Workgraphs
 // Workgraphs
 
 
 template<typename T>
 template<typename T>

+ 11 - 1
AnKi/Shaders/LightShading.ankiprog

@@ -3,6 +3,8 @@
 // Code licensed under the BSD License.
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
+#pragma anki mutator INDIRECT_DIFFUSE_TEX 0 1
+
 #pragma anki technique vert pixel
 #pragma anki technique vert pixel
 
 
 #include <AnKi/Shaders/QuadVert.hlsl>
 #include <AnKi/Shaders/QuadVert.hlsl>
@@ -16,8 +18,11 @@
 ConstantBuffer<GlobalRendererConstants> g_globalConstants : register(b0);
 ConstantBuffer<GlobalRendererConstants> g_globalConstants : register(b0);
 StructuredBuffer<PointLight> g_pointLights : register(t0);
 StructuredBuffer<PointLight> g_pointLights : register(t0);
 StructuredBuffer<SpotLight> g_spotLights : register(t1);
 StructuredBuffer<SpotLight> g_spotLights : register(t1);
+#	if INDIRECT_DIFFUSE_TEX
+Texture2D<Vec4> g_indirectDiffuseTex : register(t2);
+#	else
 StructuredBuffer<GlobalIlluminationProbe> g_giProbes : register(t2);
 StructuredBuffer<GlobalIlluminationProbe> g_giProbes : register(t2);
-StructuredBuffer<ReflectionProbe> g_reflectionProbes : register(t3);
+#	endif
 StructuredBuffer<Cluster> g_clusters : register(t4);
 StructuredBuffer<Cluster> g_clusters : register(t4);
 
 
 SamplerState g_nearestAnyClampSampler : register(s0);
 SamplerState g_nearestAnyClampSampler : register(s0);
@@ -79,8 +84,13 @@ RVec4 main(VertOut input) : SV_TARGET0
 	RVec3 outColor = gbuffer.m_emission;
 	RVec3 outColor = gbuffer.m_emission;
 
 
 	// Indirect diffuse
 	// Indirect diffuse
+#	if INDIRECT_DIFFUSE_TEX
+	const RVec3 indirectCol = g_indirectDiffuseTex[coord];
+	outColor += indirectCol * gbuffer.m_diffuse;
+#	else
 	const RVec3 probeColor = sampleGiProbes<RF32>(cluster, g_giProbes, bentNormal, worldPos, g_trilinearClampSampler);
 	const RVec3 probeColor = sampleGiProbes<RF32>(cluster, g_giProbes, bentNormal, worldPos, g_trilinearClampSampler);
 	outColor += probeColor * gbuffer.m_diffuse;
 	outColor += probeColor * gbuffer.m_diffuse;
+#	endif
 
 
 	// Indirect specular
 	// Indirect specular
 	{
 	{

+ 1 - 1
Samples/Common/SampleApp.cpp

@@ -74,7 +74,7 @@ Error SampleApp::userMainLoop(Bool& quit, Second elapsedTime)
 
 
 	if(in.getKey(KeyCode::kI) == 1)
 	if(in.getKey(KeyCode::kI) == 1)
 	{
 	{
-		renderer.setCurrentDebugRenderTarget((renderer.getCurrentDebugRenderTarget() == "Ssao") ? "" : "Ssao");
+		renderer.setCurrentDebugRenderTarget((renderer.getCurrentDebugRenderTarget() == "IndirectDiffuse") ? "" : "IndirectDiffuse");
 	}
 	}
 
 
 	if(in.getKey(KeyCode::kO) == 1)
 	if(in.getKey(KeyCode::kO) == 1)

+ 1 - 1
Sandbox/Main.cpp

@@ -348,7 +348,7 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 
 
 	if(in.getKey(KeyCode::kI) == 1)
 	if(in.getKey(KeyCode::kI) == 1)
 	{
 	{
-		renderer.setCurrentDebugRenderTarget((renderer.getCurrentDebugRenderTarget() == "Ssao") ? "" : "Ssao");
+		renderer.setCurrentDebugRenderTarget((renderer.getCurrentDebugRenderTarget() == "IndirectDiffuse") ? "" : "IndirectDiffuse");
 	}
 	}
 
 
 	if(in.getKey(KeyCode::kO) == 1)
 	if(in.getKey(KeyCode::kO) == 1)