浏览代码

Hook up the new cluster binning to indirect diffuse and specular

Panagiotis Christopoulos Charitos 2 年之前
父节点
当前提交
42bb717974

+ 83 - 0
AnKi/Renderer/ClusterBinning2.cpp

@@ -6,9 +6,14 @@
 #include <AnKi/Renderer/ClusterBinning2.h>
 #include <AnKi/Renderer/PrimaryNonRenderableVisibility.h>
 #include <AnKi/Renderer/Renderer.h>
+#include <AnKi/Renderer/ProbeReflections.h>
+#include <AnKi/Renderer/VolumetricLightingAccumulation.h>
 #include <AnKi/Core/GpuMemory/GpuVisibleTransientMemoryPool.h>
 #include <AnKi/Scene/Components/CameraComponent.h>
+#include <AnKi/Scene/Components/LightComponent.h>
 #include <AnKi/Collision/Functions.h>
+#include <AnKi/Util/Tracer.h>
+#include <AnKi/Util/HighRezTimer.h>
 
 namespace anki {
 
@@ -47,6 +52,23 @@ void ClusterBinning2::populateRenderGraph(RenderingContext& ctx)
 {
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
 
+	// Fire an async job to fill the general uniforms
+	{
+		m_runCtx.m_rctx = &ctx;
+
+		RebarAllocation alloc;
+		m_runCtx.m_uniformsCpu = RebarTransientMemoryPool::getSingleton().allocateFrame<ClusteredShadingUniforms2>(1, alloc);
+
+		m_runCtx.m_clusterUniformsOffset = alloc.m_offset;
+
+		CoreThreadHive::getSingleton().submitTask(
+			[](void* userData, [[maybe_unused]] U32 threadId, [[maybe_unused]] ThreadHive& hive,
+			   [[maybe_unused]] ThreadHiveSemaphore* signalSemaphore) {
+				static_cast<ClusterBinning2*>(userData)->writeClusterUniformsInternal();
+			},
+			this);
+	}
+
 	// Allocate the clusters buffer
 	{
 		const U32 clusterCount = getRenderer().getTileCounts().x() * getRenderer().getTileCounts().y() + getRenderer().getZSplitCount();
@@ -272,4 +294,65 @@ void ClusterBinning2::populateRenderGraph(RenderingContext& ctx)
 	}
 }
 
+void ClusterBinning2::writeClusterUniformsInternal()
+{
+	ANKI_TRACE_SCOPED_EVENT(RWriteClusterShadingObjects);
+
+	RenderingContext& ctx = *m_runCtx.m_rctx;
+	ClusteredShadingUniforms2& unis = *m_runCtx.m_uniformsCpu;
+
+	unis.m_renderingSize = Vec2(F32(getRenderer().getInternalResolution().x()), F32(getRenderer().getInternalResolution().y()));
+
+	unis.m_time = F32(HighRezTimer::getCurrentTime());
+	unis.m_frame = getRenderer().getFrameCount() & kMaxU32;
+
+	Plane nearPlane;
+	extractClipPlane(ctx.m_matrices.m_viewProjection, FrustumPlaneType::kNear, nearPlane);
+	unis.m_nearPlaneWSpace = Vec4(nearPlane.getNormal().xyz(), nearPlane.getOffset());
+	unis.m_near = ctx.m_cameraNear;
+	unis.m_far = ctx.m_cameraFar;
+	unis.m_cameraPosition = ctx.m_matrices.m_cameraTransform.getTranslationPart().xyz();
+
+	unis.m_tileCounts = getRenderer().getTileCounts();
+	unis.m_zSplitCount = getRenderer().getZSplitCount();
+	unis.m_zSplitCountOverFrustumLength = F32(getRenderer().getZSplitCount()) / (ctx.m_cameraFar - ctx.m_cameraNear);
+	unis.m_zSplitMagic.x() = (ctx.m_cameraNear - ctx.m_cameraFar) / (ctx.m_cameraNear * F32(getRenderer().getZSplitCount()));
+	unis.m_zSplitMagic.y() = ctx.m_cameraFar / (ctx.m_cameraNear * F32(getRenderer().getZSplitCount()));
+	unis.m_tileSize = getRenderer().getTileSize();
+	unis.m_lightVolumeLastZSplit = getRenderer().getVolumetricLightingAccumulation().getFinalZSplit();
+
+	unis.m_reflectionProbesMipCount = F32(getRenderer().getProbeReflections().getReflectionTextureMipmapCount());
+
+	unis.m_matrices = ctx.m_matrices;
+	unis.m_previousMatrices = ctx.m_prevMatrices;
+
+	// Directional light
+	const LightComponent* dirLight = SceneGraph::getSingleton().getDirectionalLight();
+	if(dirLight)
+	{
+		const CameraComponent& cam = SceneGraph::getSingleton().getActiveCameraNode().getFirstComponentOfType<CameraComponent>();
+
+		DirectionalLight& out = unis.m_directionalLight;
+
+		out.m_diffuseColor = dirLight->getDiffuseColor().xyz();
+		out.m_shadowCascadeCount = cam.getShadowCascadeCount();
+		out.m_direction = dirLight->getDirection();
+		out.m_active = 1;
+		for(U32 i = 0; i < kMaxShadowCascades; ++i)
+		{
+			out.m_shadowCascadeDistances[i] = cam.getShadowCascadeDistance(i);
+		}
+		out.m_shadowLayer = (dirLight->getShadowEnabled()) ? 1 : kMaxU32; // TODO RT
+
+		for(U cascade = 0; cascade < cam.getShadowCascadeCount(); ++cascade)
+		{
+			// out.m_textureMatrices[cascade] = in.m_textureMatrices[cascade]; TODO
+		}
+	}
+	else
+	{
+		unis.m_directionalLight.m_active = 0;
+	}
+}
+
 } // end namespace anki

+ 33 - 0
AnKi/Renderer/ClusterBinning2.h

@@ -25,6 +25,33 @@ public:
 	/// Populate the rendergraph.
 	void populateRenderGraph(RenderingContext& ctx);
 
+	BufferOffsetRange getClusteredShadingUniforms() const
+	{
+		ANKI_ASSERT(m_runCtx.m_clusterUniformsOffset != kMaxPtrSize);
+		return BufferOffsetRange{&RebarTransientMemoryPool::getSingleton().getBuffer(), m_runCtx.m_clusterUniformsOffset,
+								 sizeof(ClusteredShadingUniforms2)};
+	}
+
+	const BufferOffsetRange& getPackedObjectsBuffer(GpuSceneNonRenderableObjectType type) const
+	{
+		return m_runCtx.m_packedObjectsBuffers[type];
+	}
+
+	BufferHandle getPackedObjectsBufferHandle(GpuSceneNonRenderableObjectType type) const
+	{
+		return m_runCtx.m_packedObjectsHandles[type];
+	}
+
+	const BufferOffsetRange& getClustersBuffer() const
+	{
+		return m_runCtx.m_clustersBuffer;
+	}
+
+	BufferHandle getClustersBufferHandle() const
+	{
+		return m_runCtx.m_clustersHandle;
+	}
+
 private:
 	ShaderProgramResourcePtr m_jobSetupProg;
 	ShaderProgramPtr m_jobSetupGrProg;
@@ -43,7 +70,13 @@ private:
 
 		Array<BufferHandle, U32(GpuSceneNonRenderableObjectType::kCount)> m_packedObjectsHandles;
 		Array<BufferOffsetRange, U32(GpuSceneNonRenderableObjectType::kCount)> m_packedObjectsBuffers;
+
+		PtrSize m_clusterUniformsOffset = kMaxPtrSize; ///< Offset into the ReBAR buffer.
+		ClusteredShadingUniforms2* m_uniformsCpu = nullptr;
+		RenderingContext* m_rctx = nullptr;
 	} m_runCtx;
+
+	void writeClusterUniformsInternal();
 };
 /// @}
 

+ 17 - 8
AnKi/Renderer/IndirectDiffuse.cpp

@@ -10,7 +10,7 @@
 #include <AnKi/Renderer/DownscaleBlur.h>
 #include <AnKi/Renderer/MotionVectors.h>
 #include <AnKi/Renderer/IndirectDiffuseProbes.h>
-#include <AnKi/Renderer/ClusterBinning.h>
+#include <AnKi/Renderer/ClusterBinning2.h>
 #include <AnKi/Renderer/PackVisibleClusteredObjects.h>
 #include <AnKi/Core/CVarSet.h>
 
@@ -223,12 +223,14 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 		// Create main pass
 		TextureUsageBit readUsage;
 		TextureUsageBit writeUsage;
+		BufferUsageBit readBufferUsage;
 		RenderPassDescriptionBase* prpass;
 		if(preferCompute)
 		{
 			ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("IndirectDiffuse");
 			readUsage = TextureUsageBit::kSampledCompute;
 			writeUsage = TextureUsageBit::kImageComputeWrite;
+			readBufferUsage = BufferUsageBit::kStorageComputeRead;
 			prpass = &rpass;
 		}
 		else
@@ -237,6 +239,7 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 			rpass.setFramebufferInfo(m_main.m_fbDescr, {m_runCtx.m_mainRtHandles[kWrite]}, {}, (enableVrs) ? m_runCtx.m_sriRt : RenderTargetHandle());
 			readUsage = TextureUsageBit::kSampledFragment;
 			writeUsage = TextureUsageBit::kFramebufferWrite;
+			readBufferUsage = BufferUsageBit::kStorageFragmentRead;
 			prpass = &rpass;
 
 			if(enableVrs)
@@ -261,17 +264,23 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 		prpass->newTextureDependency(getRenderer().getMotionVectors().getHistoryLengthRt(), readUsage);
 		prpass->newTextureDependency(m_runCtx.m_mainRtHandles[kRead], readUsage);
 
+		prpass->newBufferDependency(
+			getRenderer().getClusterBinning2().getPackedObjectsBufferHandle(GpuSceneNonRenderableObjectType::kGlobalIlluminationProbe),
+			readBufferUsage);
+		prpass->newBufferDependency(getRenderer().getClusterBinning2().getClustersBufferHandle(), readBufferUsage);
+
 		prpass->setWork([this, &ctx, enableVrs](RenderPassWorkContext& rgraphCtx) {
 			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 			cmdb.bindShaderProgram(m_main.m_grProg.get());
 
-			cmdb.bindUniformBuffer(0, 0, &RebarTransientMemoryPool::getSingleton().getBuffer(),
-								   getRenderer().getClusterBinning().getClusteredUniformsRebarToken().m_offset,
-								   getRenderer().getClusterBinning().getClusteredUniformsRebarToken().m_range);
-			getRenderer().getPackVisibleClusteredObjects().bindClusteredObjectBuffer(cmdb, 0, 1, ClusteredObjectType::kGlobalIlluminationProbe);
-			cmdb.bindStorageBuffer(0, 2, &RebarTransientMemoryPool::getSingleton().getBuffer(),
-								   getRenderer().getClusterBinning().getClustersRebarToken().m_offset,
-								   getRenderer().getClusterBinning().getClustersRebarToken().m_range);
+			BufferOffsetRange buff = getRenderer().getClusterBinning2().getClusteredShadingUniforms();
+			cmdb.bindUniformBuffer(0, 0, buff.m_buffer, buff.m_offset, buff.m_range);
+
+			buff = getRenderer().getClusterBinning2().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kGlobalIlluminationProbe);
+			cmdb.bindStorageBuffer(0, 1, buff.m_buffer, buff.m_offset, buff.m_range);
+
+			buff = getRenderer().getClusterBinning2().getClustersBuffer();
+			cmdb.bindStorageBuffer(0, 2, buff.m_buffer, buff.m_offset, buff.m_range);
 
 			cmdb.bindSampler(0, 3, getRenderer().getSamplers().m_trilinearClamp.get());
 			rgraphCtx.bindColorTexture(0, 4, getRenderer().getGBuffer().getColorRt(2));

+ 16 - 8
AnKi/Renderer/IndirectSpecular.cpp

@@ -12,7 +12,7 @@
 #include <AnKi/Renderer/ProbeReflections.h>
 #include <AnKi/Renderer/MotionVectors.h>
 #include <AnKi/Renderer/VrsSriGeneration.h>
-#include <AnKi/Renderer/ClusterBinning.h>
+#include <AnKi/Renderer/ClusterBinning2.h>
 #include <AnKi/Renderer/PackVisibleClusteredObjects.h>
 #include <AnKi/Core/CVarSet.h>
 
@@ -119,6 +119,7 @@ void IndirectSpecular::populateRenderGraph(RenderingContext& ctx)
 		RenderPassDescriptionBase* ppass;
 		TextureUsageBit readUsage;
 		TextureUsageBit writeUsage;
+		BufferUsageBit readBufferUsage;
 		if(preferCompute)
 		{
 			ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("SSR");
@@ -126,6 +127,7 @@ void IndirectSpecular::populateRenderGraph(RenderingContext& ctx)
 			ppass = &pass;
 			readUsage = TextureUsageBit::kSampledCompute;
 			writeUsage = TextureUsageBit::kImageComputeWrite;
+			readBufferUsage = BufferUsageBit::kStorageComputeRead;
 		}
 		else
 		{
@@ -136,6 +138,7 @@ void IndirectSpecular::populateRenderGraph(RenderingContext& ctx)
 			ppass = &pass;
 			readUsage = TextureUsageBit::kSampledFragment;
 			writeUsage = TextureUsageBit::kFramebufferWrite;
+			readBufferUsage = BufferUsageBit::kStorageFragmentRead;
 
 			if(enableVrs)
 			{
@@ -160,6 +163,10 @@ void IndirectSpecular::populateRenderGraph(RenderingContext& ctx)
 		ppass->newTextureDependency(getRenderer().getMotionVectors().getMotionVectorsRt(), readUsage);
 		ppass->newTextureDependency(getRenderer().getMotionVectors().getHistoryLengthRt(), readUsage);
 
+		ppass->newBufferDependency(getRenderer().getClusterBinning2().getPackedObjectsBufferHandle(GpuSceneNonRenderableObjectType::kReflectionProbe),
+								   readBufferUsage);
+		ppass->newBufferDependency(getRenderer().getClusterBinning2().getClustersBufferHandle(), readBufferUsage);
+
 		ppass->setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
 			run(ctx, rgraphCtx);
 		});
@@ -207,13 +214,14 @@ void IndirectSpecular::run(const RenderingContext& ctx, RenderPassWorkContext& r
 	cmdb.bindSampler(0, 9, getRenderer().getSamplers().m_trilinearRepeat.get());
 	cmdb.bindTexture(0, 10, &m_noiseImage->getTextureView());
 
-	cmdb.bindUniformBuffer(0, 11, &RebarTransientMemoryPool::getSingleton().getBuffer(),
-						   getRenderer().getClusterBinning().getClusteredUniformsRebarToken().m_offset,
-						   getRenderer().getClusterBinning().getClusteredUniformsRebarToken().m_range);
-	getRenderer().getPackVisibleClusteredObjects().bindClusteredObjectBuffer(cmdb, 0, 12, ClusteredObjectType::kReflectionProbe);
-	cmdb.bindStorageBuffer(0, 13, &RebarTransientMemoryPool::getSingleton().getBuffer(),
-						   getRenderer().getClusterBinning().getClustersRebarToken().m_offset,
-						   getRenderer().getClusterBinning().getClustersRebarToken().m_range);
+	BufferOffsetRange buff = getRenderer().getClusterBinning2().getClusteredShadingUniforms();
+	cmdb.bindUniformBuffer(0, 11, buff.m_buffer, buff.m_offset, buff.m_range);
+
+	buff = getRenderer().getClusterBinning2().getPackedObjectsBuffer(GpuSceneNonRenderableObjectType::kReflectionProbe);
+	cmdb.bindStorageBuffer(0, 12, buff.m_buffer, buff.m_offset, buff.m_range);
+
+	buff = getRenderer().getClusterBinning2().getClustersBuffer();
+	cmdb.bindStorageBuffer(0, 13, buff.m_buffer, buff.m_offset, buff.m_range);
 
 	cmdb.bindAllBindless(1);
 

+ 5 - 0
AnKi/Scene/Components/CameraComponent.h

@@ -92,6 +92,11 @@ public:
 		}
 	}
 
+	U32 getShadowCascadeCount() const
+	{
+		return m_frustum.getShadowCascadeCount();
+	}
+
 	F32 getShadowCascadeDistance(U32 cascade) const
 	{
 		if(ANKI_SCENE_ASSERT(cascade < m_frustum.getShadowCascadeCount()))

+ 16 - 0
AnKi/Shaders/ClusteredShadingCommon.hlsl

@@ -139,6 +139,8 @@ Cluster mergeClusters(Cluster tileCluster, Cluster zCluster)
 }
 
 #if defined(CLUSTERED_SHADING_CLUSTERS_BINDING)
+// TODO rm
+
 /// Get the final cluster after ORing and ANDing the masks.
 Cluster getClusterFragCoord(Vec3 fragCoord, U32 tileSize, UVec2 tileCounts, U32 zSplitCount, F32 a, F32 b)
 {
@@ -152,4 +154,18 @@ Cluster getClusterFragCoord(Vec3 fragCoord)
 	return getClusterFragCoord(fragCoord, g_clusteredShading.m_tileSize, g_clusteredShading.m_tileCounts, g_clusteredShading.m_zSplitCount,
 							   g_clusteredShading.m_zSplitMagic.x, g_clusteredShading.m_zSplitMagic.y);
 }
+#else
+/// Get the final cluster after ORing and ANDing the masks.
+Cluster getClusterFragCoord(StructuredBuffer<Cluster> clusters, Vec3 fragCoord, U32 tileSize, UVec2 tileCounts, U32 zSplitCount, F32 a, F32 b)
+{
+	const Cluster tileCluster = clusters[computeTileClusterIndexFragCoord(fragCoord.xy, tileSize, tileCounts.x)];
+	const Cluster zCluster = clusters[computeZSplitClusterIndex(fragCoord.z, zSplitCount, a, b) + tileCounts.x * tileCounts.y];
+	return mergeClusters(tileCluster, zCluster);
+}
+
+Cluster getClusterFragCoord(StructuredBuffer<Cluster> clusters, ClusteredShadingUniforms2 unis, Vec3 fragCoord)
+{
+	return getClusterFragCoord(clusters, fragCoord, unis.m_tileSize, unis.m_tileCounts, unis.m_zSplitCount, unis.m_zSplitMagic.x,
+							   unis.m_zSplitMagic.y);
+}
 #endif

+ 30 - 0
AnKi/Shaders/Include/ClusteredShadingTypes.h

@@ -282,6 +282,36 @@ constexpr U32 kSizeof_ClusteredShadingUniforms =
 	(6u + (U32)ClusteredObjectType::kCount) * sizeof(Vec4) + 2u * sizeof(CommonMatrices) + sizeof(DirectionalLight);
 static_assert(sizeof(ClusteredShadingUniforms) == kSizeof_ClusteredShadingUniforms);
 
+/// Common uniforms for light shading passes.
+struct ClusteredShadingUniforms2
+{
+	Vec2 m_renderingSize;
+	F32 m_time;
+	U32 m_frame;
+
+	Vec4 m_nearPlaneWSpace;
+
+	Vec3 m_cameraPosition;
+	F32 m_reflectionProbesMipCount;
+
+	UVec2 m_tileCounts;
+	U32 m_zSplitCount;
+	F32 m_zSplitCountOverFrustumLength; ///< m_zSplitCount/(far-near)
+
+	Vec2 m_zSplitMagic; ///< It's the "a" and "b" of computeZSplitClusterIndex(). See there for details.
+	U32 m_tileSize;
+	U32 m_lightVolumeLastZSplit;
+
+	UVec2 m_padding0;
+	F32 m_near;
+	F32 m_far;
+
+	DirectionalLight m_directionalLight;
+
+	CommonMatrices m_matrices;
+	CommonMatrices m_previousMatrices;
+};
+
 // Define the type of some cluster object masks
 #if ANKI_GLSL
 #	if ANKI_CLUSTERED_SHADING_USE_64BIT

+ 8 - 10
AnKi/Shaders/IndirectDiffuse.hlsl

@@ -10,6 +10,7 @@
 #include <AnKi/Shaders/ImportanceSampling.hlsl>
 #include <AnKi/Shaders/TonemappingFunctions.hlsl>
 #include <AnKi/Shaders/Include/MiscRendererTypes.h>
+#include <AnKi/Shaders/ClusteredShadingCommon.hlsl>
 
 #define ENABLE_SSGI true
 #define ENABLE_PROBES true
@@ -19,19 +20,16 @@
 
 ANKI_SPECIALIZATION_CONSTANT_U32(kSampleCount, 0u);
 
-#define CLUSTERED_SHADING_SET 0u
-#define CLUSTERED_SHADING_UNIFORMS_BINDING 0u
-#define CLUSTERED_SHADING_GI_BINDING 1u
-#define CLUSTERED_SHADING_CLUSTERS_BINDING 2u
-#include <AnKi/Shaders/ClusteredShadingCommon.hlsl>
-
+[[vk::binding(0)]] ConstantBuffer<ClusteredShadingUniforms2> g_clusteredShading;
+[[vk::binding(1)]] StructuredBuffer<GlobalIlluminationProbe> g_giProbes;
+[[vk::binding(2)]] StructuredBuffer<Cluster> g_clusters;
 [[vk::binding(3)]] SamplerState g_linearAnyClampSampler;
 [[vk::binding(4)]] Texture2D<Vec4> g_gbufferRt2;
-[[vk::binding(5)]] Texture2D g_depthTex;
+[[vk::binding(5)]] Texture2D<Vec4> g_depthTex;
 [[vk::binding(6)]] Texture2D<RVec4> g_lightBufferRt;
 [[vk::binding(7)]] Texture2D<RVec4> g_historyTex;
-[[vk::binding(8)]] Texture2D g_motionVectorsTex;
-[[vk::binding(9)]] Texture2D g_historyLengthTex;
+[[vk::binding(8)]] Texture2D<Vec4> g_motionVectorsTex;
+[[vk::binding(9)]] Texture2D<Vec4> g_historyLengthTex;
 
 #if defined(ANKI_COMPUTE_SHADER)
 [[vk::binding(10)]] RWTexture2D<RVec4> g_outUav;
@@ -151,7 +149,7 @@ RVec3 main([[vk::location(0)]] Vec2 uv : TEXCOORD, Vec4 svPosition : SV_POSITION
 		RVec3 probeColor = Vec3(0.0, 0.0, 0.0);
 
 		// Get the cluster
-		Cluster cluster = getClusterFragCoord(Vec3(fragCoord * 2.0, depth));
+		Cluster cluster = getClusterFragCoord(g_clusters, g_clusteredShading, Vec3(fragCoord * 2.0, depth));
 
 		const U32 oneProbe = WaveActiveAllTrue(countbits(cluster.m_giProbesMask) == 1);
 		if(oneProbe)

+ 9 - 9
AnKi/Shaders/IndirectSpecular.hlsl

@@ -11,28 +11,28 @@
 #include <AnKi/Shaders/Include/MiscRendererTypes.h>
 #include <AnKi/Shaders/TonemappingFunctions.hlsl>
 #include <AnKi/Shaders/SsRaymarching.hlsl>
+#include <AnKi/Shaders/ClusteredShadingCommon.hlsl>
 
 [[vk::binding(0)]] ConstantBuffer<SsrUniforms> g_unis;
 
 [[vk::binding(1)]] SamplerState g_trilinearClampSampler;
 [[vk::binding(2)]] Texture2D<RVec4> g_gbufferRt1;
 [[vk::binding(3)]] Texture2D<RVec4> g_gbufferRt2;
-[[vk::binding(4)]] Texture2D g_depthRt;
+[[vk::binding(4)]] Texture2D<Vec4> g_depthRt;
 [[vk::binding(5)]] Texture2D<RVec4> g_lightBufferRt;
 
 [[vk::binding(6)]] Texture2D<RVec4> g_historyTex;
-[[vk::binding(7)]] Texture2D g_motionVectorsTex;
+[[vk::binding(7)]] Texture2D<Vec4> g_motionVectorsTex;
 [[vk::binding(8)]] Texture2D<RVec4> g_historyLengthTex;
 
 [[vk::binding(9)]] SamplerState g_trilinearRepeatSampler;
 [[vk::binding(10)]] Texture2D<RVec4> g_noiseTex;
-constexpr Vec2 kNoiseTexSize = 64.0;
 
-#define CLUSTERED_SHADING_SET 0u
-#define CLUSTERED_SHADING_UNIFORMS_BINDING 11u
-#define CLUSTERED_SHADING_REFLECTIONS_BINDING 12u
-#define CLUSTERED_SHADING_CLUSTERS_BINDING 13u
-#include <AnKi/Shaders/ClusteredShadingCommon.hlsl>
+[[vk::binding(11)]] ConstantBuffer<ClusteredShadingUniforms2> g_clusteredShading;
+[[vk::binding(12)]] StructuredBuffer<ReflectionProbe> g_reflectionProbes;
+[[vk::binding(13)]] StructuredBuffer<Cluster> g_clusters;
+
+constexpr Vec2 kNoiseTexSize = 64.0;
 
 #if defined(ANKI_COMPUTE_SHADER)
 [[vk::binding(14)]] RWTexture2D<RVec4> g_outUav;
@@ -190,7 +190,7 @@ RVec3 main(Vec2 uv : TEXCOORD, Vec4 svPosition : SV_POSITION) : SV_TARGET0
 		const Vec2 ndc = uvToNdc(uv);
 		const Vec4 worldPos4 = mul(g_clusteredShading.m_matrices.m_invertedViewProjectionJitter, Vec4(ndc, depth, 1.0));
 		const Vec3 worldPos = worldPos4.xyz / worldPos4.w;
-		Cluster cluster = getClusterFragCoord(Vec3(fragCoord * 2.0, depth));
+		Cluster cluster = getClusterFragCoord(g_clusters, g_clusteredShading, Vec3(fragCoord * 2.0, depth));
 
 		// Compute the refl dir in word space this time
 		const RVec3 viewDir = normalize(g_clusteredShading.m_cameraPosition - worldPos);