Explorar o código

Remove the GI from the reflection cubes

Panagiotis Christopoulos Charitos %!s(int64=6) %!d(string=hai) anos
pai
achega
3d96b2ae77

+ 38 - 25
shaders/ApplyIrradianceToReflection.glslp

@@ -3,50 +3,63 @@
 // Code licensed under the BSD License.
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
-#pragma anki start vert
-#include <shaders/QuadVert.glsl>
-#pragma anki end
-
-#pragma anki start frag
+#pragma anki start comp
 #include <shaders/Pack.glsl>
 #include <shaders/Pack.glsl>
+#include <shaders/LightFunctions.glsl>
 
 
-layout(location = 0) in Vec2 in_uv;
-
-layout(location = 0) out Vec3 out_color;
+layout(local_size_x = 8, local_size_y = 8, local_size_z = 6) in;
 
 
 layout(set = 0, binding = 0) uniform sampler u_nearestAnyClampSampler;
 layout(set = 0, binding = 0) uniform sampler u_nearestAnyClampSampler;
-layout(set = 0, binding = 1) uniform sampler u_linearAnyClampSampler;
-
-layout(set = 0, binding = 2) uniform texture2D u_gbufferTex0;
-layout(set = 0, binding = 3) uniform texture2D u_gbufferTex1;
-layout(set = 0, binding = 4) uniform texture2D u_gbufferTex2;
+layout(set = 0, binding = 1) uniform texture2D u_gbufferTex[3u];
 
 
-layout(set = 0, binding = 5) uniform textureCubeArray u_irradianceTex;
-
-layout(push_constant, std430) uniform pc_
+layout(set = 0, binding = 2) buffer readonly ssbo_
 {
 {
-	Vec3 u_padding;
-	F32 u_faceIdx;
+	Vec4 u_irradianceDice[6u];
 };
 };
 
 
+layout(set = 0, binding = 3) uniform imageCube u_cubeTex;
+
 void main()
 void main()
 {
 {
+	const Vec2 cubeSize = Vec2(imageSize(u_cubeTex));
+	if(gl_GlobalInvocationID.x >= cubeSize.x || gl_GlobalInvocationID.y >= cubeSize.y)
+	{
+		return;
+	}
+
+	const U32 faceIdx = gl_LocalInvocationID.z;
+
 	// Compute the UVs to read the gbuffer from
 	// Compute the UVs to read the gbuffer from
-	Vec2 sampleUv = in_uv;
+	Vec2 sampleUv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(cubeSize);
 	sampleUv.x *= (1.0 / 6.0);
 	sampleUv.x *= (1.0 / 6.0);
-	sampleUv.x += (1.0 / 6.0) * u_faceIdx;
+	sampleUv.x += (1.0 / 6.0) * F32(faceIdx);
 
 
 	// Read the gbuffer
 	// Read the gbuffer
 	GbufferInfo gbuffer;
 	GbufferInfo gbuffer;
-	readGBuffer(u_gbufferTex0, u_gbufferTex1, u_gbufferTex2, u_nearestAnyClampSampler, sampleUv, 0.0, gbuffer);
+	readGBuffer(u_gbufferTex[0u], u_gbufferTex[1u], u_gbufferTex[2u], u_nearestAnyClampSampler, sampleUv, 0.0, gbuffer);
 
 
-	// Read the irradiance. Use the layer 0 because C++ will set the appropriate texture view
-	const Vec3 irradiance = textureLod(u_irradianceTex, u_linearAnyClampSampler, Vec4(gbuffer.m_normal, 0.0), 0.0).rgb;
+	// Sample
+	const Vec3 irradiance = sampleAmbientDice(u_irradianceDice[0u].xyz,
+		u_irradianceDice[1u].xyz,
+		u_irradianceDice[2u].xyz,
+		u_irradianceDice[3u].xyz,
+		u_irradianceDice[4u].xyz,
+		u_irradianceDice[5u].xyz,
+		gbuffer.m_normal);
 
 
 	// Compute the indirect term
 	// Compute the indirect term
 	const Vec3 indirect = gbuffer.m_diffuse * irradiance;
 	const Vec3 indirect = gbuffer.m_diffuse * irradiance;
 
 
-	// Write it
-	out_color = indirect;
+	// Read the prev color and apply indirect
+	const IVec3 coords = IVec3(gl_GlobalInvocationID.x, gl_GlobalInvocationID.y, faceIdx);
+	const Vec3 prevColor = imageLoad(u_cubeTex, coords).xyz;
+	const Vec3 prevColorWithIndirectDiffuse = prevColor + gbuffer.m_diffuse * indirect;
+
+	// Barrier just in case
+	memoryBarrierImage();
+	barrier();
+
+	// Write it back
+	imageStore(u_cubeTex, coords, Vec4(prevColorWithIndirectDiffuse, 0.0));
 }
 }
 #pragma anki end
 #pragma anki end

+ 2 - 3
shaders/ClusteredShadingCommon.glsl

@@ -58,7 +58,7 @@ layout(set = LIGHT_SET, binding = LIGHT_LIGHTS_BINDING + 2) uniform highp textur
 #endif
 #endif
 
 
 //
 //
-// Indirect uniforms (4)
+// Indirect uniforms (3)
 //
 //
 #if defined(LIGHT_INDIRECT_SPECULAR_BINDING)
 #if defined(LIGHT_INDIRECT_SPECULAR_BINDING)
 layout(std140, row_major, set = LIGHT_SET, binding = LIGHT_INDIRECT_SPECULAR_BINDING) uniform u3_
 layout(std140, row_major, set = LIGHT_SET, binding = LIGHT_INDIRECT_SPECULAR_BINDING) uniform u3_
@@ -67,8 +67,7 @@ layout(std140, row_major, set = LIGHT_SET, binding = LIGHT_INDIRECT_SPECULAR_BIN
 };
 };
 
 
 layout(set = LIGHT_SET, binding = LIGHT_INDIRECT_SPECULAR_BINDING + 1) uniform textureCubeArray u_reflectionsTex;
 layout(set = LIGHT_SET, binding = LIGHT_INDIRECT_SPECULAR_BINDING + 1) uniform textureCubeArray u_reflectionsTex;
-layout(set = LIGHT_SET, binding = LIGHT_INDIRECT_SPECULAR_BINDING + 2) uniform textureCubeArray u_irradianceTex;
-layout(set = LIGHT_SET, binding = LIGHT_INDIRECT_SPECULAR_BINDING + 3) uniform texture2D u_integrationLut;
+layout(set = LIGHT_SET, binding = LIGHT_INDIRECT_SPECULAR_BINDING + 2) uniform texture2D u_integrationLut;
 #endif
 #endif
 
 
 //
 //

+ 0 - 64
shaders/Irradiance.glslp

@@ -1,64 +0,0 @@
-// Copyright (C) 2009-2019, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-// Compute the irradiance given an environment map
-
-#pragma anki input const U32 ENV_TEX_TILE_SIZE
-#pragma anki input const F32 ENV_TEX_MIP
-
-#pragma anki start vert
-#include <shaders/QuadVert.glsl>
-#pragma anki end
-
-#pragma anki start frag
-#include <shaders/Functions.glsl>
-
-layout(location = 0) in Vec2 in_uv;
-layout(location = 0) out Vec3 out_color;
-
-layout(set = 0, binding = 0) uniform sampler u_linearAnyClampSampler;
-layout(set = 0, binding = 1) uniform textureCubeArray u_envTex;
-
-layout(push_constant, std430) uniform pc_
-{
-	UVec4 u_faceIdxPad3;
-};
-
-// Integrate the environment map to compute the irradiance for a single fragment
-void main()
-{
-	const U32 face = u_faceIdxPad3.x;
-	const F32 texArrIdx = 0.0; // The C++ code gives the layer idx using a tex view
-
-	// Get the r coordinate of the current face and fragment
-	const Vec3 ri = getCubemapDirection(UV_TO_NDC(in_uv), face);
-
-	Vec3 outCol = Vec3(0.0);
-
-	// For all the faces and texels of the environment map calculate a color sum
-	ANKI_LOOP for(U32 f = 0u; f < 6u; ++f)
-	{
-		ANKI_LOOP for(U32 i = 0u; i < ENV_TEX_TILE_SIZE; ++i)
-		{
-			ANKI_LOOP for(U32 j = 0u; j < ENV_TEX_TILE_SIZE; ++j)
-			{
-				const Vec2 uv = Vec2(j, i) / F32(ENV_TEX_TILE_SIZE);
-				const Vec2 ndc = UV_TO_NDC(uv);
-
-				const Vec3 r = getCubemapDirection(ndc, f);
-				const F32 lambert = dot(r, ri);
-
-				if(lambert > 0.0)
-				{
-					const Vec3 col = textureLod(u_envTex, u_linearAnyClampSampler, Vec4(r, texArrIdx), ENV_TEX_MIP).rgb;
-					outCol += col * lambert * cubeCoordSolidAngle(ndc, F32(ENV_TEX_TILE_SIZE));
-				}
-			}
-		}
-	}
-
-	out_color = outCol / PI;
-}
-#pragma anki end

+ 76 - 47
shaders/IrradianceDice.glslp

@@ -5,7 +5,10 @@
 
 
 // Compute the irradiance given a light shading result. The irradiance will be stored in an ambient dice.
 // Compute the irradiance given a light shading result. The irradiance will be stored in an ambient dice.
 
 
-#pragma anki input const U32 INPUT_TEXTURES_HEIGHT
+#pragma anki input const U32 WORKGROUP_SIZE
+#pragma anki mutator LIGHT_SHADING_TEX 0 1 // 0: texture2D, 1: textureCubeArray
+#pragma anki mutator STORE_LOCATION 0 1 // 0: in a 3D texture, 1: In an SSBO
+#pragma anki mutator SECOND_BOUNCE 0 1
 
 
 #pragma anki start comp
 #pragma anki start comp
 
 
@@ -14,46 +17,72 @@
 #include <shaders/LightFunctions.glsl>
 #include <shaders/LightFunctions.glsl>
 
 
 #define DEBUG_MODE 0 // 0: disable, 1: different color per dice face, 2: different color per cell
 #define DEBUG_MODE 0 // 0: disable, 1: different color per dice face, 2: different color per cell
-#define SECOND_BOUNCE 1
 
 
-layout(local_size_x = INPUT_TEXTURES_HEIGHT, local_size_y = INPUT_TEXTURES_HEIGHT, local_size_z = 1) in;
+layout(local_size_x = WORKGROUP_SIZE, local_size_y = WORKGROUP_SIZE, local_size_z = 1) in;
 
 
 layout(set = 0, binding = 0) uniform sampler u_nearestAnyClampSampler;
 layout(set = 0, binding = 0) uniform sampler u_nearestAnyClampSampler;
+#if LIGHT_SHADING_TEX == 0
 layout(set = 0, binding = 1) uniform texture2D u_lightShadingTex;
 layout(set = 0, binding = 1) uniform texture2D u_lightShadingTex;
-layout(set = 0, binding = 2) uniform texture2D u_gbufferTex0;
-layout(set = 0, binding = 3) uniform texture2D u_gbufferTex1;
-layout(set = 0, binding = 4) uniform texture2D u_gbufferTex2;
-layout(set = 0, binding = 5) uniform writeonly image3D u_irradianceVolume;
+#else
+layout(set = 0, binding = 1) uniform textureCubeArray u_lightShadingTex;
+#endif
 
 
-// This is a temporary buffer used instead of shared memory because it's too large
-layout(set = 0, binding = 6, std430) buffer ssbo_
+#if SECOND_BOUNCE == 1
+layout(set = 0, binding = 2) uniform texture2D u_gbufferTex[3u];
+#endif
+
+// This is a temporary buffer used instead of shared memory because the needs are too large
+layout(set = 0, binding = 3, std430) buffer ssbo_
 {
 {
-	Vec4 u_integrationResults[6u][INPUT_TEXTURES_HEIGHT * INPUT_TEXTURES_HEIGHT];
+	Vec4 u_integrationResults[6u][WORKGROUP_SIZE * WORKGROUP_SIZE];
 };
 };
 
 
+#if STORE_LOCATION == 0
+layout(set = 0, binding = 4) uniform writeonly image3D u_irradianceVolume;
+
 layout(push_constant, std430) uniform pc_
 layout(push_constant, std430) uniform pc_
 {
 {
 	IVec3 u_volumeTexel;
 	IVec3 u_volumeTexel;
 	I32 u_nextTexelOffsetInU;
 	I32 u_nextTexelOffsetInU;
 };
 };
+#else
+layout(set = 0, binding = 4, std430) writeonly buffer ssbo1_
+{
+	Vec4 u_irradianceDisceResults[6u];
+};
+#endif
 
 
 shared Vec3 s_diceIrradiance[6u];
 shared Vec3 s_diceIrradiance[6u];
 
 
+Vec3 sampleLightShadingTexture(const U32 face)
+{
+#if LIGHT_SHADING_TEX == 0
+	const Vec2 INPUT_TEXTURES_SIZE = Vec2(WORKGROUP_SIZE * 6u, WORKGROUP_SIZE);
+	const Vec2 uv =
+		(Vec2(gl_LocalInvocationID.x + WORKGROUP_SIZE * face, gl_LocalInvocationID.y) + 0.5) / INPUT_TEXTURES_SIZE;
+
+	return textureLod(u_lightShadingTex, u_nearestAnyClampSampler, uv, 0.0).rgb;
+#else
+	const Vec2 uv = (Vec2(gl_LocalInvocationID.x, gl_LocalInvocationID.y) + 0.5) / F32(WORKGROUP_SIZE);
+	const Vec2 ndc = UV_TO_NDC(uv);
+	const Vec3 cubeUvw = getCubemapDirection(ndc, face);
+	const F32 layerIdx = 0.0; // The C++ code sets the right layer in the view.
+
+	return textureLod(u_lightShadingTex, u_nearestAnyClampSampler, Vec4(cubeUvw, 0.0), 0.0).rgb;
+#endif
+}
+
 void main()
 void main()
 {
 {
-	const F32 INPUT_TEXTURES_HEIGHT_F = F32(INPUT_TEXTURES_HEIGHT);
-	const Vec2 INPUT_TEXTURES_SIZE = Vec2(INPUT_TEXTURES_HEIGHT * 6u, INPUT_TEXTURES_HEIGHT);
+	const F32 WORKGROUP_SIZE_F = F32(WORKGROUP_SIZE);
 
 
 	// Compute the NDC used in cubeCoordSolidAngle
 	// Compute the NDC used in cubeCoordSolidAngle
-	const Vec2 faceUv = (Vec2(gl_LocalInvocationID.xy) + 0.5) / INPUT_TEXTURES_HEIGHT_F;
+	const Vec2 faceUv = (Vec2(gl_LocalInvocationID.xy) + 0.5) / WORKGROUP_SIZE_F;
 	const Vec2 ndc = UV_TO_NDC(faceUv);
 	const Vec2 ndc = UV_TO_NDC(faceUv);
 
 
 	// Initialize
 	// Initialize
 	ANKI_UNROLL for(U32 f = 0u; f < 6u; ++f)
 	ANKI_UNROLL for(U32 f = 0u; f < 6u; ++f)
 	{
 	{
-		const Vec2 uv = (Vec2(gl_LocalInvocationID.x + INPUT_TEXTURES_HEIGHT_F * f, gl_LocalInvocationID.y) + 0.5)
-						/ INPUT_TEXTURES_SIZE;
-
 		// Get the direction of the dice face
 		// Get the direction of the dice face
 		const Vec3 diceDir = getCubemapDirection(Vec2(0.0), f);
 		const Vec3 diceDir = getCubemapDirection(Vec2(0.0), f);
 
 
@@ -61,19 +90,18 @@ void main()
 
 
 		// Compute integral part
 		// Compute integral part
 		const F32 lambert = max(0.0, dot(r, diceDir));
 		const F32 lambert = max(0.0, dot(r, diceDir));
-		const Vec3 lightShading = textureLod(u_lightShadingTex, u_nearestAnyClampSampler, uv, 0.0).rgb;
-		const Vec3 irradiance = lightShading * lambert * cubeCoordSolidAngle(ndc, INPUT_TEXTURES_HEIGHT_F);
+		const Vec3 lightShading = sampleLightShadingTexture(f);
+		const Vec3 irradiance = lightShading * lambert * cubeCoordSolidAngle(ndc, WORKGROUP_SIZE_F);
 
 
 		// Store
 		// Store
-		u_integrationResults[f][gl_LocalInvocationID.y * INPUT_TEXTURES_HEIGHT + gl_LocalInvocationID.x] =
-			irradiance.xyzx;
+		u_integrationResults[f][gl_LocalInvocationID.y * WORKGROUP_SIZE + gl_LocalInvocationID.x] = irradiance.xyzx;
 	}
 	}
 
 
 	memoryBarrierBuffer();
 	memoryBarrierBuffer();
 	barrier();
 	barrier();
 
 
 	// Reduce using prefix sum
 	// Reduce using prefix sum
-	const U32 WG_SIZE = INPUT_TEXTURES_HEIGHT * INPUT_TEXTURES_HEIGHT;
+	const U32 WG_SIZE = WORKGROUP_SIZE * WORKGROUP_SIZE;
 	ANKI_LOOP for(U32 s = WG_SIZE / 2u; s > 0u; s >>= 1u)
 	ANKI_LOOP for(U32 s = WG_SIZE / 2u; s > 0u; s >>= 1u)
 	{
 	{
 		if(gl_LocalInvocationIndex < s)
 		if(gl_LocalInvocationIndex < s)
@@ -101,9 +129,6 @@ void main()
 	// Initialize again for the 2nd bounce
 	// Initialize again for the 2nd bounce
 	ANKI_UNROLL for(U32 f = 0u; f < 6u; ++f)
 	ANKI_UNROLL for(U32 f = 0u; f < 6u; ++f)
 	{
 	{
-		const Vec2 uv = (Vec2(gl_LocalInvocationID.x + INPUT_TEXTURES_HEIGHT_F * f, gl_LocalInvocationID.y) + 0.5)
-						/ INPUT_TEXTURES_SIZE;
-
 		// Get the direction of the dice face
 		// Get the direction of the dice face
 		const Vec3 diceDir = getCubemapDirection(Vec2(0.0), f);
 		const Vec3 diceDir = getCubemapDirection(Vec2(0.0), f);
 
 
@@ -113,8 +138,11 @@ void main()
 		const F32 lambert = max(0.0, dot(r, diceDir));
 		const F32 lambert = max(0.0, dot(r, diceDir));
 
 
 		// Read the gbuffer
 		// Read the gbuffer
+		Vec2 gbufferUv = (Vec2(gl_LocalInvocationID.xy) + 0.5) / WORKGROUP_SIZE_F;
+		gbufferUv.x *= 1.0 / 6.0;
+		gbufferUv.x += (1.0 / 6.0) * F32(f);
 		GbufferInfo gbuffer;
 		GbufferInfo gbuffer;
-		readGBuffer(u_gbufferTex0, u_gbufferTex1, u_gbufferTex2, u_nearestAnyClampSampler, uv, 0.0, gbuffer);
+		readGBuffer(u_gbufferTex[0u], u_gbufferTex[1u], u_gbufferTex[2u], u_nearestAnyClampSampler, gbufferUv, 0.0, gbuffer);
 
 
 		// Sample irradiance
 		// Sample irradiance
 		Vec3 firstBounceIrradiance = sampleAmbientDice(s_diceIrradiance[0],
 		Vec3 firstBounceIrradiance = sampleAmbientDice(s_diceIrradiance[0],
@@ -127,13 +155,12 @@ void main()
 		firstBounceIrradiance = gbuffer.m_diffuse * firstBounceIrradiance / PI;
 		firstBounceIrradiance = gbuffer.m_diffuse * firstBounceIrradiance / PI;
 
 
 		// Compute 2nd bounce
 		// Compute 2nd bounce
-		const Vec3 lightShading = textureLod(u_lightShadingTex, u_nearestAnyClampSampler, uv, 0.0).rgb;
+		const Vec3 lightShading = sampleLightShadingTexture(f);
 		const Vec3 irradiance =
 		const Vec3 irradiance =
-			(firstBounceIrradiance + lightShading * lambert) * cubeCoordSolidAngle(ndc, INPUT_TEXTURES_HEIGHT_F);
+			(firstBounceIrradiance + lightShading * lambert) * cubeCoordSolidAngle(ndc, WORKGROUP_SIZE_F);
 
 
 		// Store
 		// Store
-		u_integrationResults[f][gl_LocalInvocationID.y * INPUT_TEXTURES_HEIGHT + gl_LocalInvocationID.x] =
-			irradiance.xyzx;
+		u_integrationResults[f][gl_LocalInvocationID.y * WORKGROUP_SIZE + gl_LocalInvocationID.x] = irradiance.xyzx;
 	}
 	}
 
 
 	memoryBarrierBuffer();
 	memoryBarrierBuffer();
@@ -157,33 +184,35 @@ void main()
 #endif
 #endif
 
 
 	// Store the results
 	// Store the results
-	if(gl_LocalInvocationIndex == 0u)
+	if(gl_LocalInvocationIndex < 6u)
 	{
 	{
-		ANKI_UNROLL for(U32 f = 0u; f < 6u; ++f)
-		{
+		const U32 f = gl_LocalInvocationIndex;
+
 #if DEBUG_MODE == 0
 #if DEBUG_MODE == 0
 #	if SECOND_BOUNCE == 1
 #	if SECOND_BOUNCE == 1
-			Vec3 irradiance = u_integrationResults[f][0].xyz;
+		Vec3 irradiance = u_integrationResults[f][0].xyz;
 #	else
 #	else
-			Vec3 irradiance = s_diceIrradiance[f];
+		Vec3 irradiance = s_diceIrradiance[f];
 #	endif
 #	endif
-			irradiance /= PI; // Pre-divide
-			const Vec3 toStoreValue = irradiance;
+		irradiance /= PI / 2.0; // Pre-divide. Don't use PI because we integraded only PI/2
+		const Vec3 toStoreValue = irradiance;
 #elif DEBUG_MODE == 1
 #elif DEBUG_MODE == 1
-			const Vec3 toStoreValue = colorPerCubeFace(f);
+		const Vec3 toStoreValue = colorPerCubeFace(f);
 #else
 #else
-			const UVec3 volumeSize = UVec3(imageSize(u_irradianceVolume));
-			const UVec3 subvolumeSize = UVec3(volumeSize.x / 6u, volumeSize.y, volumeSize.z);
-			const U32 cellIdx = u_volumeTexel.z * subvolumeSize.x * subvolumeSize.y + u_volumeTexel.y * subvolumeSize.x
-								+ u_volumeTexel.x;
-			const F32 headmapFactor = F32(cellIdx) / F32(subvolumeSize.x * subvolumeSize.y * subvolumeSize.z);
-			const Vec3 toStoreValue = heatmap(headmapFactor);
+		const UVec3 volumeSize = UVec3(imageSize(u_irradianceVolume));
+		const UVec3 subvolumeSize = UVec3(volumeSize.x / 6u, volumeSize.y, volumeSize.z);
+		const U32 cellIdx =
+			u_volumeTexel.z * subvolumeSize.x * subvolumeSize.y + u_volumeTexel.y * subvolumeSize.x + u_volumeTexel.x;
+		const F32 headmapFactor = F32(cellIdx) / F32(subvolumeSize.x * subvolumeSize.y * subvolumeSize.z);
+		const Vec3 toStoreValue = heatmap(headmapFactor);
 #endif
 #endif
 
 
-			const IVec3 storeUvw =
-				IVec3(u_volumeTexel.x + I32(f) * u_nextTexelOffsetInU, u_volumeTexel.y, u_volumeTexel.z);
-			imageStore(u_irradianceVolume, storeUvw, Vec4(toStoreValue, 0.0));
-		}
+#if STORE_LOCATION == 0
+		const IVec3 storeUvw = IVec3(u_volumeTexel.x + I32(f) * u_nextTexelOffsetInU, u_volumeTexel.y, u_volumeTexel.z);
+		imageStore(u_irradianceVolume, storeUvw, Vec4(toStoreValue, 0.0));
+#else
+		u_irradianceDisceResults[f] = toStoreValue.xyzx;
+#endif
 	}
 	}
 }
 }
 
 

+ 10 - 10
shaders/LightShading.glslp

@@ -38,19 +38,19 @@ void main()
 #define LIGHT_COMMON_UNIS_BINDING 0
 #define LIGHT_COMMON_UNIS_BINDING 0
 #define LIGHT_LIGHTS_BINDING 1
 #define LIGHT_LIGHTS_BINDING 1
 #define LIGHT_INDIRECT_SPECULAR_BINDING 4
 #define LIGHT_INDIRECT_SPECULAR_BINDING 4
-#define LIGHT_GLOBAL_ILLUMINATION_BINDING 8
-#define LIGHT_CLUSTERS_BINDING 10
+#define LIGHT_GLOBAL_ILLUMINATION_BINDING 7
+#define LIGHT_CLUSTERS_BINDING 9
 #include <shaders/ClusteredShadingCommon.glsl>
 #include <shaders/ClusteredShadingCommon.glsl>
 
 
-layout(set = 0, binding = 12) uniform sampler u_nearestAnyClampSampler;
-layout(set = 0, binding = 13) uniform sampler u_trilinearClampSampler;
+layout(set = 0, binding = 11) uniform sampler u_nearestAnyClampSampler;
+layout(set = 0, binding = 12) uniform sampler u_trilinearClampSampler;
 
 
-layout(set = 0, binding = 14) uniform texture2D u_msRt0;
-layout(set = 0, binding = 15) uniform texture2D u_msRt1;
-layout(set = 0, binding = 16) uniform texture2D u_msRt2;
-layout(set = 0, binding = 17) uniform texture2D u_msDepthRt;
-layout(set = 0, binding = 18) uniform texture2D u_ssrRt;
-layout(set = 0, binding = 19) uniform texture2D u_ssaoRt;
+layout(set = 0, binding = 13) uniform texture2D u_msRt0;
+layout(set = 0, binding = 14) uniform texture2D u_msRt1;
+layout(set = 0, binding = 15) uniform texture2D u_msRt2;
+layout(set = 0, binding = 16) uniform texture2D u_msDepthRt;
+layout(set = 0, binding = 17) uniform texture2D u_ssrRt;
+layout(set = 0, binding = 18) uniform texture2D u_ssaoRt;
 
 
 layout(location = 0) in Vec2 in_uv;
 layout(location = 0) in Vec2 in_uv;
 layout(location = 1) in Vec2 in_clusterIJ;
 layout(location = 1) in Vec2 in_clusterIJ;

+ 1 - 0
src/anki/core/Config.cpp

@@ -42,6 +42,7 @@ Config::Config()
 	newOption("r.bloom.scale", 2.5);
 	newOption("r.bloom.scale", 2.5);
 
 
 	newOption("r.indirect.reflectionResolution", 128);
 	newOption("r.indirect.reflectionResolution", 128);
+	newOption("r.indirect.irradianceResolution", 16);
 	newOption("r.indirect.maxSimultaneousProbeCount", 32);
 	newOption("r.indirect.maxSimultaneousProbeCount", 32);
 	newOption("r.indirect.shadowMapResolution", 64);
 	newOption("r.indirect.shadowMapResolution", 64);
 
 

+ 13 - 9
src/anki/renderer/GlobalIllumination.cpp

@@ -227,10 +227,15 @@ Error GlobalIllumination::initIrradiance(const ConfigSet& cfg)
 	ANKI_CHECK(m_r->getResourceManager().loadResource("shaders/IrradianceDice.glslp", m_irradiance.m_prog));
 	ANKI_CHECK(m_r->getResourceManager().loadResource("shaders/IrradianceDice.glslp", m_irradiance.m_prog));
 
 
 	ShaderProgramResourceConstantValueInitList<1> consts(m_irradiance.m_prog);
 	ShaderProgramResourceConstantValueInitList<1> consts(m_irradiance.m_prog);
-	consts.add("INPUT_TEXTURES_HEIGHT", U32(m_tileSize));
+	consts.add("WORKGROUP_SIZE", U32(m_tileSize));
+
+	ShaderProgramResourceMutationInitList<3> mutations(m_irradiance.m_prog);
+	mutations.add("LIGHT_SHADING_TEX", 0);
+	mutations.add("STORE_LOCATION", 0);
+	mutations.add("SECOND_BOUNCE", 1);
 
 
 	const ShaderProgramResourceVariant* variant;
 	const ShaderProgramResourceVariant* variant;
-	m_irradiance.m_prog->getOrCreateVariant(consts.get(), variant);
+	m_irradiance.m_prog->getOrCreateVariant(mutations.get(), consts.get(), variant);
 	m_irradiance.m_grProg = variant->getProgram();
 	m_irradiance.m_grProg = variant->getProgram();
 
 
 	return Error::NONE;
 	return Error::NONE;
@@ -700,19 +705,18 @@ void GlobalIllumination::runIrradiance(RenderPassWorkContext& rgraphCtx, Interna
 	cmdb->bindShaderProgram(m_irradiance.m_grProg);
 	cmdb->bindShaderProgram(m_irradiance.m_grProg);
 
 
 	// Bind resources
 	// Bind resources
-	U binding = 0;
-	cmdb->bindSampler(0, binding++, m_r->getSamplers().m_nearestNearestClamp);
-	rgraphCtx.bindColorTexture(0, binding++, giCtx.m_lightShadingRt);
+	cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);
+	rgraphCtx.bindColorTexture(0, 1, giCtx.m_lightShadingRt);
 
 
 	for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT - 1; ++i)
 	for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT - 1; ++i)
 	{
 	{
-		rgraphCtx.bindColorTexture(0, binding++, giCtx.m_gbufferColorRts[i]);
+		rgraphCtx.bindColorTexture(0, 2, giCtx.m_gbufferColorRts[i], i);
 	}
 	}
 
 
-	rgraphCtx.bindImage(0, binding++, giCtx.m_irradianceProbeRts[probeIdx], TextureSubresourceInfo());
-
 	// Bind temporary memory
 	// Bind temporary memory
-	allocateAndBindStorage<void*>(sizeof(Vec4) * 6 * m_tileSize * m_tileSize, cmdb, 0, binding);
+	allocateAndBindStorage<void*>(sizeof(Vec4) * 6 * m_tileSize * m_tileSize, cmdb, 0, 3);
+
+	rgraphCtx.bindImage(0, 4, giCtx.m_irradianceProbeRts[probeIdx], TextureSubresourceInfo());
 
 
 	struct
 	struct
 	{
 	{

+ 125 - 240
src/anki/renderer/Indirect.cpp

@@ -124,7 +124,8 @@ Error Indirect::initLightShading(const ConfigSet& config)
 			m_lightShading.m_tileSize,
 			m_lightShading.m_tileSize,
 			LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 			LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_COMPUTE
 			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_COMPUTE
-				| TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE | TextureUsageBit::GENERATE_MIPMAPS,
+				| TextureUsageBit::IMAGE_COMPUTE_READ_WRITE | TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE
+				| TextureUsageBit::GENERATE_MIPMAPS,
 			"CubeRefl refl");
 			"CubeRefl refl");
 		texinit.m_mipmapCount = m_lightShading.m_mipCount;
 		texinit.m_mipmapCount = m_lightShading.m_mipCount;
 		texinit.m_type = TextureType::CUBE_ARRAY;
 		texinit.m_type = TextureType::CUBE_ARRAY;
@@ -142,38 +143,33 @@ Error Indirect::initLightShading(const ConfigSet& config)
 
 
 Error Indirect::initIrradiance(const ConfigSet& config)
 Error Indirect::initIrradiance(const ConfigSet& config)
 {
 {
-	// Init atlas
-	{
-		TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(m_irradiance.m_tileSize,
-			m_irradiance.m_tileSize,
-			LIGHT_SHADING_COLOR_ATTACHMENT_PIXEL_FORMAT,
-			TextureUsageBit::SAMPLED_FRAGMENT | TextureUsageBit::SAMPLED_COMPUTE
-				| TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE,
-			"CubeRefl irr");
-
-		texinit.m_layerCount = m_cacheEntries.getSize();
-		texinit.m_type = TextureType::CUBE_ARRAY;
-		texinit.m_initialUsage = TextureUsageBit::SAMPLED_FRAGMENT;
-
-		m_irradiance.m_cubeArr = m_r->createAndClearRenderTarget(texinit);
-	}
+	m_irradiance.m_workgroupSize = config.getNumber("r.indirect.irradianceResolution");
 
 
 	// Create prog
 	// Create prog
 	{
 	{
-		ANKI_CHECK(m_r->getResourceManager().loadResource("shaders/Irradiance.glslp", m_irradiance.m_prog));
+		ANKI_CHECK(m_r->getResourceManager().loadResource("shaders/IrradianceDice.glslp", m_irradiance.m_prog));
 
 
-		const F32 envMapReadMip = computeMaxMipmapCount2d(
-			m_lightShading.m_tileSize, m_lightShading.m_tileSize, m_irradiance.m_envMapReadSize);
+		ShaderProgramResourceConstantValueInitList<1> consts(m_irradiance.m_prog);
+		consts.add("WORKGROUP_SIZE", U32(m_irradiance.m_workgroupSize));
 
 
-		ShaderProgramResourceConstantValueInitList<2> consts(m_irradiance.m_prog);
-		consts.add("ENV_TEX_TILE_SIZE", U32(m_irradiance.m_envMapReadSize));
-		consts.add("ENV_TEX_MIP", envMapReadMip);
+		ShaderProgramResourceMutationInitList<3> mutations(m_irradiance.m_prog);
+		mutations.add("LIGHT_SHADING_TEX", 1);
+		mutations.add("STORE_LOCATION", 1);
+		mutations.add("SECOND_BOUNCE", 0);
 
 
 		const ShaderProgramResourceVariant* variant;
 		const ShaderProgramResourceVariant* variant;
-		m_irradiance.m_prog->getOrCreateVariant(consts.get(), variant);
+		m_irradiance.m_prog->getOrCreateVariant(mutations.get(), consts.get(), variant);
 		m_irradiance.m_grProg = variant->getProgram();
 		m_irradiance.m_grProg = variant->getProgram();
 	}
 	}
 
 
+	// Create buff
+	{
+		BufferInitInfo init;
+		init.m_usage = BufferUsageBit::STORAGE_ALL;
+		init.m_size = 6 * sizeof(Vec4);
+		m_irradiance.m_diceValuesBuff = getGrManager().newBuffer(init);
+	}
+
 	return Error::NONE;
 	return Error::NONE;
 }
 }
 
 
@@ -227,37 +223,13 @@ void Indirect::initCacheEntry(U32 cacheEntryIdx)
 	for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
 	for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
 	{
 	{
 		// Light pass FB
 		// Light pass FB
-		{
-			FramebufferDescription& fbDescr = cacheEntry.m_lightShadingFbDescrs[faceIdx];
-			ANKI_ASSERT(!fbDescr.isBacked());
-			fbDescr.m_colorAttachmentCount = 1;
-			fbDescr.m_colorAttachments[0].m_surface.m_layer = cacheEntryIdx;
-			fbDescr.m_colorAttachments[0].m_surface.m_face = faceIdx;
-			fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::CLEAR;
-			fbDescr.bake();
-		}
-
-		// Irradiance FB
-		{
-			FramebufferDescription& fbDescr = cacheEntry.m_irradianceFbDescrs[faceIdx];
-			ANKI_ASSERT(!fbDescr.isBacked());
-			fbDescr.m_colorAttachmentCount = 1;
-			fbDescr.m_colorAttachments[0].m_surface.m_layer = cacheEntryIdx;
-			fbDescr.m_colorAttachments[0].m_surface.m_face = faceIdx;
-			fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::DONT_CARE;
-			fbDescr.bake();
-		}
-
-		// Irradiance to Refl FB
-		{
-			FramebufferDescription& fbDescr = cacheEntry.m_irradianceToReflFbDescrs[faceIdx];
-			ANKI_ASSERT(!fbDescr.isBacked());
-			fbDescr.m_colorAttachmentCount = 1;
-			fbDescr.m_colorAttachments[0].m_surface.m_layer = cacheEntryIdx;
-			fbDescr.m_colorAttachments[0].m_surface.m_face = faceIdx;
-			fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::LOAD;
-			fbDescr.bake();
-		}
+		FramebufferDescription& fbDescr = cacheEntry.m_lightShadingFbDescrs[faceIdx];
+		ANKI_ASSERT(!fbDescr.isBacked());
+		fbDescr.m_colorAttachmentCount = 1;
+		fbDescr.m_colorAttachments[0].m_surface.m_layer = cacheEntryIdx;
+		fbDescr.m_colorAttachments[0].m_surface.m_face = faceIdx;
+		fbDescr.m_colorAttachments[0].m_loadOperation = AttachmentLoadOperation::CLEAR;
+		fbDescr.bake();
 	}
 	}
 }
 }
 
 
@@ -365,34 +337,30 @@ void Indirect::prepareProbes(RenderingContext& ctx,
 	}
 	}
 }
 }
 
 
-void Indirect::runGBuffer(CommandBufferPtr& cmdb)
+void Indirect::runGBuffer(U32 faceIdx, CommandBufferPtr& cmdb)
 {
 {
 	ANKI_ASSERT(m_ctx.m_probe);
 	ANKI_ASSERT(m_ctx.m_probe);
-	ANKI_TRACE_SCOPED_EVENT(R_IR);
+	ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
 	const ReflectionProbeQueueElement& probe = *m_ctx.m_probe;
 	const ReflectionProbeQueueElement& probe = *m_ctx.m_probe;
 
 
-	// For each face
-	for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
-	{
-		const U32 viewportX = faceIdx * m_gbuffer.m_tileSize;
-		cmdb->setViewport(viewportX, 0, m_gbuffer.m_tileSize, m_gbuffer.m_tileSize);
-		cmdb->setScissor(viewportX, 0, m_gbuffer.m_tileSize, m_gbuffer.m_tileSize);
+	const U32 viewportX = faceIdx * m_gbuffer.m_tileSize;
+	cmdb->setViewport(viewportX, 0, m_gbuffer.m_tileSize, m_gbuffer.m_tileSize);
+	cmdb->setScissor(viewportX, 0, m_gbuffer.m_tileSize, m_gbuffer.m_tileSize);
 
 
-		/// Draw
-		ANKI_ASSERT(probe.m_renderQueues[faceIdx]);
-		const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
+	// Draw
+	ANKI_ASSERT(probe.m_renderQueues[faceIdx]);
+	const RenderQueue& rqueue = *probe.m_renderQueues[faceIdx];
 
 
-		if(!rqueue.m_renderables.isEmpty())
-		{
-			m_r->getSceneDrawer().drawRange(Pass::GB,
-				rqueue.m_viewMatrix,
-				rqueue.m_viewProjectionMatrix,
-				Mat4::getIdentity(), // Don't care about prev mats
-				cmdb,
-				m_r->getSamplers().m_trilinearRepeatAniso,
-				rqueue.m_renderables.getBegin(),
-				rqueue.m_renderables.getEnd());
-		}
+	if(!rqueue.m_renderables.isEmpty())
+	{
+		m_r->getSceneDrawer().drawRange(Pass::GB,
+			rqueue.m_viewMatrix,
+			rqueue.m_viewProjectionMatrix,
+			Mat4::getIdentity(), // Don't care about prev mats
+			cmdb,
+			m_r->getSamplers().m_trilinearRepeatAniso,
+			rqueue.m_renderables.getBegin(),
+			rqueue.m_renderables.getEnd());
 	}
 	}
 
 
 	// Restore state
 	// Restore state
@@ -402,7 +370,7 @@ void Indirect::runGBuffer(CommandBufferPtr& cmdb)
 void Indirect::runLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
 void Indirect::runLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
 {
 {
 	ANKI_ASSERT(faceIdx <= 6);
 	ANKI_ASSERT(faceIdx <= 6);
-	ANKI_TRACE_SCOPED_EVENT(R_IR);
+	ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
 
 
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
 
@@ -452,7 +420,7 @@ void Indirect::runMipmappingOfLightShading(U32 faceIdx, RenderPassWorkContext& r
 	ANKI_ASSERT(faceIdx < 6);
 	ANKI_ASSERT(faceIdx < 6);
 	ANKI_ASSERT(m_ctx.m_cacheEntryIdx < m_cacheEntries.getSize());
 	ANKI_ASSERT(m_ctx.m_cacheEntryIdx < m_cacheEntries.getSize());
 
 
-	ANKI_TRACE_SCOPED_EVENT(R_IR);
+	ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
 
 
 	TextureSubresourceInfo subresource(TextureSurfaceInfo(0, 0, faceIdx, m_ctx.m_cacheEntryIdx));
 	TextureSubresourceInfo subresource(TextureSurfaceInfo(0, 0, faceIdx, m_ctx.m_cacheEntryIdx));
 	subresource.m_mipmapCount = m_lightShading.m_mipCount;
 	subresource.m_mipmapCount = m_lightShading.m_mipCount;
@@ -465,76 +433,64 @@ void Indirect::runMipmappingOfLightShading(U32 faceIdx, RenderPassWorkContext& r
 	rgraphCtx.m_commandBuffer->generateMipmaps2d(getGrManager().newTextureView(viewInit));
 	rgraphCtx.m_commandBuffer->generateMipmaps2d(getGrManager().newTextureView(viewInit));
 }
 }
 
 
-void Indirect::runIrradiance(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
+void Indirect::runIrradiance(RenderPassWorkContext& rgraphCtx)
 {
 {
-	ANKI_ASSERT(faceIdx < 6);
-	ANKI_TRACE_SCOPED_EVENT(R_IR);
+	ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
 	const U32 cacheEntryIdx = m_ctx.m_cacheEntryIdx;
 	const U32 cacheEntryIdx = m_ctx.m_cacheEntryIdx;
 	ANKI_ASSERT(cacheEntryIdx < m_cacheEntries.getSize());
 	ANKI_ASSERT(cacheEntryIdx < m_cacheEntries.getSize());
 
 
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
 
-	// Set state
-	cmdb->setViewport(0, 0, m_irradiance.m_tileSize, m_irradiance.m_tileSize);
 	cmdb->bindShaderProgram(m_irradiance.m_grProg);
 	cmdb->bindShaderProgram(m_irradiance.m_grProg);
 
 
-	cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
+	// Bind stuff
+	cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);
 
 
 	TextureSubresourceInfo subresource;
 	TextureSubresourceInfo subresource;
 	subresource.m_faceCount = 6;
 	subresource.m_faceCount = 6;
 	subresource.m_firstLayer = cacheEntryIdx;
 	subresource.m_firstLayer = cacheEntryIdx;
 	rgraphCtx.bindTexture(0, 1, m_ctx.m_lightShadingRt, subresource);
 	rgraphCtx.bindTexture(0, 1, m_ctx.m_lightShadingRt, subresource);
 
 
-	// Set uniforms
-	UVec4 pushConsts(faceIdx);
-	cmdb->setPushConstants(&pushConsts, sizeof(pushConsts));
+	allocateAndBindStorage<void*>(
+		sizeof(Vec4) * 6 * m_irradiance.m_workgroupSize * m_irradiance.m_workgroupSize, cmdb, 0, 3);
+
+	cmdb->bindStorageBuffer(0, 4, m_irradiance.m_diceValuesBuff, 0, m_irradiance.m_diceValuesBuff->getSize());
 
 
 	// Draw
 	// Draw
-	drawQuad(cmdb);
+	cmdb->dispatchCompute(1, 1, 1);
 }
 }
 
 
-void Indirect::runIrradianceToRefl(U32 faceIdx, RenderPassWorkContext& rgraphCtx)
+void Indirect::runIrradianceToRefl(RenderPassWorkContext& rgraphCtx)
 {
 {
-	ANKI_ASSERT(faceIdx < 6);
-	ANKI_TRACE_SCOPED_EVENT(R_IR);
+	ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
 
 
 	const U32 cacheEntryIdx = m_ctx.m_cacheEntryIdx;
 	const U32 cacheEntryIdx = m_ctx.m_cacheEntryIdx;
 	ANKI_ASSERT(cacheEntryIdx < m_cacheEntries.getSize());
 	ANKI_ASSERT(cacheEntryIdx < m_cacheEntries.getSize());
 
 
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 	CommandBufferPtr& cmdb = rgraphCtx.m_commandBuffer;
 
 
-	// Set state
-	cmdb->setViewport(0, 0, m_lightShading.m_tileSize, m_lightShading.m_tileSize);
-	cmdb->setBlendFactors(0, BlendFactor::ONE, BlendFactor::ONE);
-
 	cmdb->bindShaderProgram(m_irradianceToRefl.m_grProg);
 	cmdb->bindShaderProgram(m_irradianceToRefl.m_grProg);
 
 
 	// Bind resources
 	// Bind resources
 	cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);
 	cmdb->bindSampler(0, 0, m_r->getSamplers().m_nearestNearestClamp);
-	cmdb->bindSampler(0, 1, m_r->getSamplers().m_trilinearClamp);
 
 
-	rgraphCtx.bindColorTexture(0, 2, m_ctx.m_gbufferColorRts[0]);
-	rgraphCtx.bindColorTexture(0, 3, m_ctx.m_gbufferColorRts[1]);
-	rgraphCtx.bindColorTexture(0, 4, m_ctx.m_gbufferColorRts[2]);
+	rgraphCtx.bindColorTexture(0, 1, m_ctx.m_gbufferColorRts[0], 0);
+	rgraphCtx.bindColorTexture(0, 1, m_ctx.m_gbufferColorRts[1], 1);
+	rgraphCtx.bindColorTexture(0, 1, m_ctx.m_gbufferColorRts[2], 2);
+
+	cmdb->bindStorageBuffer(0, 2, m_irradiance.m_diceValuesBuff, 0, m_irradiance.m_diceValuesBuff->getSize());
 
 
 	TextureSubresourceInfo subresource;
 	TextureSubresourceInfo subresource;
 	subresource.m_faceCount = 6;
 	subresource.m_faceCount = 6;
 	subresource.m_firstLayer = cacheEntryIdx;
 	subresource.m_firstLayer = cacheEntryIdx;
-	rgraphCtx.bindTexture(0, 5, m_ctx.m_irradianceRt, subresource);
-
-	Vec4 pushConsts(faceIdx);
-	cmdb->setPushConstants(&pushConsts, sizeof(pushConsts));
+	rgraphCtx.bindImage(0, 3, m_ctx.m_lightShadingRt, subresource);
 
 
-	// Draw
-	drawQuad(cmdb);
-
-	// Restore state
-	cmdb->setBlendFactors(0, BlendFactor::ONE, BlendFactor::ZERO);
+	dispatchPPCompute(cmdb, 8, 8, m_lightShading.m_tileSize, m_lightShading.m_tileSize);
 }
 }
 
 
 void Indirect::populateRenderGraph(RenderingContext& rctx)
 void Indirect::populateRenderGraph(RenderingContext& rctx)
 {
 {
-	ANKI_TRACE_SCOPED_EVENT(R_IR);
+	ANKI_TRACE_SCOPED_EVENT(R_CUBE_REFL);
 
 
 #if ANKI_EXTRA_CHECKS
 #if ANKI_EXTRA_CHECKS
 	m_ctx = {};
 	m_ctx = {};
@@ -552,8 +508,6 @@ void Indirect::populateRenderGraph(RenderingContext& rctx)
 		// Just import and exit
 		// Just import and exit
 
 
 		m_ctx.m_lightShadingRt = rgraph.importRenderTarget(m_lightShading.m_cubeArr, TextureUsageBit::SAMPLED_FRAGMENT);
 		m_ctx.m_lightShadingRt = rgraph.importRenderTarget(m_lightShading.m_cubeArr, TextureUsageBit::SAMPLED_FRAGMENT);
-		m_ctx.m_irradianceRt = rgraph.importRenderTarget(m_irradiance.m_cubeArr, TextureUsageBit::SAMPLED_FRAGMENT);
-
 		return;
 		return;
 	}
 	}
 
 
@@ -581,10 +535,11 @@ void Indirect::populateRenderGraph(RenderingContext& rctx)
 		pass.setFramebufferInfo(m_gbuffer.m_fbDescr, rts, m_ctx.m_gbufferDepthRt);
 		pass.setFramebufferInfo(m_gbuffer.m_fbDescr, rts, m_ctx.m_gbufferDepthRt);
 		pass.setWork(
 		pass.setWork(
 			[](RenderPassWorkContext& rgraphCtx) {
 			[](RenderPassWorkContext& rgraphCtx) {
-				static_cast<Indirect*>(rgraphCtx.m_userData)->runGBuffer(rgraphCtx.m_commandBuffer);
+				static_cast<Indirect*>(rgraphCtx.m_userData)
+					->runGBuffer(rgraphCtx.m_currentSecondLevelCommandBufferIndex, rgraphCtx.m_commandBuffer);
 			},
 			},
 			this,
 			this,
-			0);
+			6);
 
 
 		for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
 		for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
 		{
 		{
@@ -638,10 +593,11 @@ void Indirect::populateRenderGraph(RenderingContext& rctx)
 		pass.setFramebufferInfo(m_shadowMapping.m_fbDescr, {}, m_ctx.m_shadowMapRt);
 		pass.setFramebufferInfo(m_shadowMapping.m_fbDescr, {}, m_ctx.m_shadowMapRt);
 		pass.setWork(
 		pass.setWork(
 			[](RenderPassWorkContext& rgraphCtx) {
 			[](RenderPassWorkContext& rgraphCtx) {
-				static_cast<Indirect*>(rgraphCtx.m_userData)->runShadowMapping(rgraphCtx.m_commandBuffer);
+				static_cast<Indirect*>(rgraphCtx.m_userData)
+					->runShadowMapping(rgraphCtx.m_currentSecondLevelCommandBufferIndex, rgraphCtx.m_commandBuffer);
 			},
 			},
 			this,
 			this,
-			0);
+			6);
 
 
 		TextureSubresourceInfo subresource(DepthStencilAspectBit::DEPTH);
 		TextureSubresourceInfo subresource(DepthStencilAspectBit::DEPTH);
 		pass.newDependency({m_ctx.m_shadowMapRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE, subresource});
 		pass.newDependency({m_ctx.m_shadowMapRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE, subresource});
@@ -698,117 +654,49 @@ void Indirect::populateRenderGraph(RenderingContext& rctx)
 
 
 	// Irradiance passes
 	// Irradiance passes
 	{
 	{
-		static const Array<RenderPassWorkCallback, 6> callbacks = {{runIrradianceCallback<0>,
-			runIrradianceCallback<1>,
-			runIrradianceCallback<2>,
-			runIrradianceCallback<3>,
-			runIrradianceCallback<4>,
-			runIrradianceCallback<5>}};
-
-		// Rt
-		m_ctx.m_irradianceRt = rgraph.importRenderTarget(m_irradiance.m_cubeArr, TextureUsageBit::SAMPLED_FRAGMENT);
-
-		static const Array<CString, 6> passNames = {{"CubeRefl Irr/ce #0",
-			"CubeRefl Irr/ce #1",
-			"CubeRefl Irr/ce #2",
-			"CubeRefl Irr/ce #3",
-			"CubeRefl Irr/ce #4",
-			"CubeRefl Irr/ce #5"}};
-		for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
-		{
-			GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass(passNames[faceIdx]);
+		m_ctx.m_irradianceDiceValuesBuffHandle =
+			rgraph.importBuffer(m_irradiance.m_diceValuesBuff, BufferUsageBit::NONE);
 
 
-			pass.setFramebufferInfo(
-				m_cacheEntries[probeToUpdateCacheEntryIdx].m_irradianceFbDescrs[faceIdx], {{m_ctx.m_irradianceRt}}, {});
+		ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("CubeRefl Irradiance");
 
 
-			pass.setWork(callbacks[faceIdx], this, 0);
+		pass.setWork(
+			[](RenderPassWorkContext& rgraphCtx) {
+				static_cast<Indirect*>(rgraphCtx.m_userData)->runIrradiance(rgraphCtx);
+			},
+			this,
+			0);
 
 
-			// Read a cube but only one layer and level
-			TextureSubresourceInfo readSubresource;
-			readSubresource.m_faceCount = 6;
-			readSubresource.m_firstLayer = probeToUpdateCacheEntryIdx;
-			pass.newDependency({m_ctx.m_lightShadingRt, TextureUsageBit::SAMPLED_FRAGMENT, readSubresource});
+		// Read a cube but only one layer and level
+		TextureSubresourceInfo readSubresource;
+		readSubresource.m_faceCount = 6;
+		readSubresource.m_firstLayer = probeToUpdateCacheEntryIdx;
+		pass.newDependency({m_ctx.m_lightShadingRt, TextureUsageBit::SAMPLED_COMPUTE, readSubresource});
 
 
-			TextureSubresourceInfo writeSubresource(TextureSurfaceInfo(0, 0, faceIdx, probeToUpdateCacheEntryIdx));
-			pass.newDependency({m_ctx.m_irradianceRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, writeSubresource});
-		}
+		pass.newDependency({m_ctx.m_irradianceDiceValuesBuffHandle, BufferUsageBit::STORAGE_COMPUTE_WRITE});
 	}
 	}
 
 
 	// Write irradiance back to refl
 	// Write irradiance back to refl
 	{
 	{
-		static const Array<RenderPassWorkCallback, 6> callbacks = {{runIrradianceToReflCallback<0>,
-			runIrradianceToReflCallback<1>,
-			runIrradianceToReflCallback<2>,
-			runIrradianceToReflCallback<3>,
-			runIrradianceToReflCallback<4>,
-			runIrradianceToReflCallback<5>}};
-
-		// Rt
-		static const Array<CString, 6> passNames = {{"CubeRefl Irr2Refl #0",
-			"CubeRefl Irr2Refl #1",
-			"CubeRefl Irr2Refl #2",
-			"CubeRefl Irr2Refl #3",
-			"CubeRefl Irr2Refl #4",
-			"CubeRefl Irr2Refl #5"}};
-		for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
-		{
-			GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass(passNames[faceIdx]);
-
-			pass.setFramebufferInfo(m_cacheEntries[probeToUpdateCacheEntryIdx].m_irradianceToReflFbDescrs[faceIdx],
-				{{m_ctx.m_lightShadingRt}},
-				{});
-
-			pass.setWork(callbacks[faceIdx], this, 0);
-
-			for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
-			{
-				pass.newDependency({m_ctx.m_gbufferColorRts[i], TextureUsageBit::SAMPLED_FRAGMENT});
-			}
+		ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("CubeRefl apply indirect");
 
 
-			TextureSubresourceInfo readSubresource;
-			readSubresource.m_faceCount = 6;
-			readSubresource.m_firstLayer = probeToUpdateCacheEntryIdx;
-			pass.newDependency({m_ctx.m_irradianceRt, TextureUsageBit::SAMPLED_FRAGMENT, readSubresource});
-
-			TextureSubresourceInfo writeSubresource(TextureSurfaceInfo(0, 0, faceIdx, probeToUpdateCacheEntryIdx));
-			pass.newDependency(
-				{m_ctx.m_lightShadingRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_READ_WRITE, writeSubresource});
-		}
-	}
+		pass.setWork(
+			[](RenderPassWorkContext& rgraphCtx) {
+				static_cast<Indirect*>(rgraphCtx.m_userData)->runIrradianceToRefl(rgraphCtx);
+			},
+			this,
+			0);
 
 
-	// Irradiance passes 2nd bounce
-	{
-		static const Array<RenderPassWorkCallback, 6> callbacks = {{runIrradianceCallback<0>,
-			runIrradianceCallback<1>,
-			runIrradianceCallback<2>,
-			runIrradianceCallback<3>,
-			runIrradianceCallback<4>,
-			runIrradianceCallback<5>}};
-
-		static const Array<CString, 6> passNames = {{"CubeRefl Irr 2nd #0",
-			"CubeRefl Irr 2nd #1",
-			"CubeRefl Irr 2nd #2",
-			"CubeRefl Irr 2nd #3",
-			"CubeRefl Irr 2nd #4",
-			"CubeRefl Irr 2nd #5"}};
-		for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
+		for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT - 1; ++i)
 		{
 		{
-			GraphicsRenderPassDescription& pass = rgraph.newGraphicsRenderPass(passNames[faceIdx]);
-
-			pass.setFramebufferInfo(
-				m_cacheEntries[probeToUpdateCacheEntryIdx].m_irradianceFbDescrs[faceIdx], {{m_ctx.m_irradianceRt}}, {});
-
-			pass.setWork(callbacks[faceIdx], this, 0);
+			pass.newDependency({m_ctx.m_gbufferColorRts[i], TextureUsageBit::SAMPLED_COMPUTE});
+		}
 
 
-			// Read a cube but only one layer and level
-			TextureSubresourceInfo readSubresource;
-			readSubresource.m_faceCount = 6;
-			readSubresource.m_firstLayer = probeToUpdateCacheEntryIdx;
-			pass.newDependency({m_ctx.m_lightShadingRt, TextureUsageBit::SAMPLED_FRAGMENT, readSubresource});
+		TextureSubresourceInfo subresource;
+		subresource.m_faceCount = 6;
+		subresource.m_firstLayer = probeToUpdateCacheEntryIdx;
+		pass.newDependency({m_ctx.m_lightShadingRt, TextureUsageBit::IMAGE_COMPUTE_READ_WRITE, subresource});
 
 
-			TextureSubresourceInfo writeSubresource(TextureSurfaceInfo(0, 0, faceIdx, probeToUpdateCacheEntryIdx));
-			pass.newDependency({m_ctx.m_irradianceRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE, writeSubresource});
-		}
+		pass.newDependency({m_ctx.m_irradianceDiceValuesBuffHandle, BufferUsageBit::STORAGE_COMPUTE_READ});
 	}
 	}
 
 
 	// Mipmapping "passes"
 	// Mipmapping "passes"
@@ -839,40 +727,37 @@ void Indirect::populateRenderGraph(RenderingContext& rctx)
 	}
 	}
 }
 }
 
 
-void Indirect::runShadowMapping(CommandBufferPtr& cmdb)
+void Indirect::runShadowMapping(U32 faceIdx, CommandBufferPtr& cmdb)
 {
 {
 	cmdb->setPolygonOffset(1.0f, 1.0f);
 	cmdb->setPolygonOffset(1.0f, 1.0f);
 
 
-	for(U faceIdx = 0; faceIdx < 6; ++faceIdx)
-	{
-		ANKI_ASSERT(m_ctx.m_probe);
-		ANKI_ASSERT(m_ctx.m_probe->m_renderQueues[faceIdx]);
-		const RenderQueue& faceRenderQueue = *m_ctx.m_probe->m_renderQueues[faceIdx];
-		ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_uuid != 0);
-		ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_shadowCascadeCount == 1);
-
-		ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0]);
-		const RenderQueue& cascadeRenderQueue = *faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0];
-
-		if(cascadeRenderQueue.m_renderables.getSize() == 0)
-		{
-			continue;
-		}
+	ANKI_ASSERT(m_ctx.m_probe);
+	ANKI_ASSERT(m_ctx.m_probe->m_renderQueues[faceIdx]);
+	const RenderQueue& faceRenderQueue = *m_ctx.m_probe->m_renderQueues[faceIdx];
+	ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_uuid != 0);
+	ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_shadowCascadeCount == 1);
 
 
-		const U rez = m_shadowMapping.m_rtDescr.m_height;
-		cmdb->setViewport(rez * faceIdx, 0, rez, rez);
-		cmdb->setScissor(rez * faceIdx, 0, rez, rez);
+	ANKI_ASSERT(faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0]);
+	const RenderQueue& cascadeRenderQueue = *faceRenderQueue.m_directionalLight.m_shadowRenderQueues[0];
 
 
-		m_r->getSceneDrawer().drawRange(Pass::SM,
-			cascadeRenderQueue.m_viewMatrix,
-			cascadeRenderQueue.m_viewProjectionMatrix,
-			Mat4::getIdentity(), // Don't care about prev matrices here
-			cmdb,
-			m_r->getSamplers().m_trilinearRepeatAniso,
-			cascadeRenderQueue.m_renderables.getBegin(),
-			cascadeRenderQueue.m_renderables.getEnd());
+	if(cascadeRenderQueue.m_renderables.getSize() == 0)
+	{
+		return;
 	}
 	}
 
 
+	const U rez = m_shadowMapping.m_rtDescr.m_height;
+	cmdb->setViewport(rez * faceIdx, 0, rez, rez);
+	cmdb->setScissor(rez * faceIdx, 0, rez, rez);
+
+	m_r->getSceneDrawer().drawRange(Pass::SM,
+		cascadeRenderQueue.m_viewMatrix,
+		cascadeRenderQueue.m_viewProjectionMatrix,
+		Mat4::getIdentity(), // Don't care about prev matrices here
+		cmdb,
+		m_r->getSamplers().m_trilinearRepeatAniso,
+		cascadeRenderQueue.m_renderables.getBegin(),
+		cascadeRenderQueue.m_renderables.getEnd());
+
 	cmdb->setPolygonOffset(0.0f, 0.0f);
 	cmdb->setPolygonOffset(0.0f, 0.0f);
 }
 }
 
 

+ 7 - 32
src/anki/renderer/Indirect.h

@@ -52,11 +52,6 @@ anki_internal:
 		return m_ctx.m_lightShadingRt;
 		return m_ctx.m_lightShadingRt;
 	}
 	}
 
 
-	RenderTargetHandle getIrradianceRt() const
-	{
-		return m_ctx.m_irradianceRt;
-	}
-
 private:
 private:
 	class
 	class
 	{
 	{
@@ -85,12 +80,10 @@ private:
 	class
 	class
 	{
 	{
 	public:
 	public:
-		U32 m_tileSize = 8;
-		U32 m_envMapReadSize = 16; ///< This controls the iterations that will be used to calculate the irradiance.
-		TexturePtr m_cubeArr;
-
 		ShaderProgramResourcePtr m_prog;
 		ShaderProgramResourcePtr m_prog;
 		ShaderProgramPtr m_grProg;
 		ShaderProgramPtr m_grProg;
+		BufferPtr m_diceValuesBuff;
+		U32 m_workgroupSize = 16;
 	} m_irradiance; ///< Irradiance.
 	} m_irradiance; ///< Irradiance.
 
 
 	class
 	class
@@ -115,8 +108,6 @@ private:
 		Timestamp m_lastUsedTimestamp = 0; ///< When it was last seen by the renderer.
 		Timestamp m_lastUsedTimestamp = 0; ///< When it was last seen by the renderer.
 
 
 		Array<FramebufferDescription, 6> m_lightShadingFbDescrs;
 		Array<FramebufferDescription, 6> m_lightShadingFbDescrs;
-		Array<FramebufferDescription, 6> m_irradianceFbDescrs;
-		Array<FramebufferDescription, 6> m_irradianceToReflFbDescrs;
 	};
 	};
 
 
 	DynamicArray<CacheEntry> m_cacheEntries;
 	DynamicArray<CacheEntry> m_cacheEntries;
@@ -135,7 +126,7 @@ private:
 		Array<RenderTargetHandle, GBUFFER_COLOR_ATTACHMENT_COUNT> m_gbufferColorRts;
 		Array<RenderTargetHandle, GBUFFER_COLOR_ATTACHMENT_COUNT> m_gbufferColorRts;
 		RenderTargetHandle m_gbufferDepthRt;
 		RenderTargetHandle m_gbufferDepthRt;
 		RenderTargetHandle m_lightShadingRt;
 		RenderTargetHandle m_lightShadingRt;
-		RenderTargetHandle m_irradianceRt;
+		RenderPassBufferHandle m_irradianceDiceValuesBuffHandle;
 		RenderTargetHandle m_shadowMapRt;
 		RenderTargetHandle m_shadowMapRt;
 	} m_ctx; ///< Runtime context.
 	} m_ctx; ///< Runtime context.
 
 
@@ -152,12 +143,12 @@ private:
 	void prepareProbes(
 	void prepareProbes(
 		RenderingContext& ctx, ReflectionProbeQueueElement*& probeToUpdate, U32& probeToUpdateCacheEntryIdx);
 		RenderingContext& ctx, ReflectionProbeQueueElement*& probeToUpdate, U32& probeToUpdateCacheEntryIdx);
 
 
-	void runGBuffer(CommandBufferPtr& cmdb);
-	void runShadowMapping(CommandBufferPtr& cmdb);
+	void runGBuffer(U32 faceIdx, CommandBufferPtr& cmdb);
+	void runShadowMapping(U32 faceIdx, CommandBufferPtr& cmdb);
 	void runLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx);
 	void runLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx);
 	void runMipmappingOfLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx);
 	void runMipmappingOfLightShading(U32 faceIdx, RenderPassWorkContext& rgraphCtx);
-	void runIrradiance(U32 faceIdx, RenderPassWorkContext& rgraphCtx);
-	void runIrradianceToRefl(U32 faceIdx, RenderPassWorkContext& rgraphCtx);
+	void runIrradiance(RenderPassWorkContext& rgraphCtx);
+	void runIrradianceToRefl(RenderPassWorkContext& rgraphCtx);
 
 
 	// A RenderPassWorkCallback for the light shading pass into a single face.
 	// A RenderPassWorkCallback for the light shading pass into a single face.
 	template<U faceIdx>
 	template<U faceIdx>
@@ -174,22 +165,6 @@ private:
 		Indirect* const self = static_cast<Indirect*>(rgraphCtx.m_userData);
 		Indirect* const self = static_cast<Indirect*>(rgraphCtx.m_userData);
 		self->runMipmappingOfLightShading(faceIdx, rgraphCtx);
 		self->runMipmappingOfLightShading(faceIdx, rgraphCtx);
 	}
 	}
-
-	// A RenderPassWorkCallback for the irradiance calculation of a single cube face.
-	template<U faceIdx>
-	static void runIrradianceCallback(RenderPassWorkContext& rgraphCtx)
-	{
-		Indirect* const self = static_cast<Indirect*>(rgraphCtx.m_userData);
-		self->runIrradiance(faceIdx, rgraphCtx);
-	}
-
-	// A RenderPassWorkCallback to apply the irradiance back to the reflection.
-	template<U faceIdx>
-	static void runIrradianceToReflCallback(RenderPassWorkContext& rgraphCtx)
-	{
-		Indirect* const self = static_cast<Indirect*>(rgraphCtx.m_userData);
-		self->runIrradianceToRefl(faceIdx, rgraphCtx);
-	}
 };
 };
 /// @}
 /// @}
 
 

+ 13 - 15
src/anki/renderer/LightShading.cpp

@@ -117,24 +117,23 @@ void LightShading::run(RenderPassWorkContext& rgraphCtx)
 
 
 		bindUniforms(cmdb, 0, 4, rsrc.m_reflectionProbesToken);
 		bindUniforms(cmdb, 0, 4, rsrc.m_reflectionProbesToken);
 		rgraphCtx.bindColorTexture(0, 5, m_r->getIndirect().getReflectionRt());
 		rgraphCtx.bindColorTexture(0, 5, m_r->getIndirect().getReflectionRt());
-		rgraphCtx.bindColorTexture(0, 6, m_r->getIndirect().getIrradianceRt());
-		cmdb->bindTexture(0, 7, m_r->getIndirect().getIntegrationLut(), TextureUsageBit::SAMPLED_FRAGMENT);
+		cmdb->bindTexture(0, 6, m_r->getIndirect().getIntegrationLut(), TextureUsageBit::SAMPLED_FRAGMENT);
 
 
-		m_r->getGlobalIllumination().bindVolumeTextures(ctx, rgraphCtx, 0, 8);
-		bindUniforms(cmdb, 0, 9, rsrc.m_globalIlluminationProbesToken);
+		m_r->getGlobalIllumination().bindVolumeTextures(ctx, rgraphCtx, 0, 7);
+		bindUniforms(cmdb, 0, 8, rsrc.m_globalIlluminationProbesToken);
 
 
-		bindStorage(cmdb, 0, 10, rsrc.m_clustersToken);
-		bindStorage(cmdb, 0, 11, rsrc.m_indicesToken);
+		bindStorage(cmdb, 0, 9, rsrc.m_clustersToken);
+		bindStorage(cmdb, 0, 10, rsrc.m_indicesToken);
 
 
-		cmdb->bindSampler(0, 12, m_r->getSamplers().m_nearestNearestClamp);
-		cmdb->bindSampler(0, 13, m_r->getSamplers().m_trilinearClamp);
-		rgraphCtx.bindColorTexture(0, 14, m_r->getGBuffer().getColorRt(0));
-		rgraphCtx.bindColorTexture(0, 15, m_r->getGBuffer().getColorRt(1));
-		rgraphCtx.bindColorTexture(0, 16, m_r->getGBuffer().getColorRt(2));
+		cmdb->bindSampler(0, 11, m_r->getSamplers().m_nearestNearestClamp);
+		cmdb->bindSampler(0, 12, m_r->getSamplers().m_trilinearClamp);
+		rgraphCtx.bindColorTexture(0, 13, m_r->getGBuffer().getColorRt(0));
+		rgraphCtx.bindColorTexture(0, 14, m_r->getGBuffer().getColorRt(1));
+		rgraphCtx.bindColorTexture(0, 15, m_r->getGBuffer().getColorRt(2));
 		rgraphCtx.bindTexture(
 		rgraphCtx.bindTexture(
-			0, 17, m_r->getGBuffer().getDepthRt(), TextureSubresourceInfo(DepthStencilAspectBit::DEPTH));
-		rgraphCtx.bindColorTexture(0, 18, m_r->getSsr().getRt());
-		rgraphCtx.bindColorTexture(0, 19, m_r->getSsao().getRt());
+			0, 16, m_r->getGBuffer().getDepthRt(), TextureSubresourceInfo(DepthStencilAspectBit::DEPTH));
+		rgraphCtx.bindColorTexture(0, 17, m_r->getSsr().getRt());
+		rgraphCtx.bindColorTexture(0, 18, m_r->getSsao().getRt());
 
 
 		// Draw
 		// Draw
 		drawQuad(cmdb);
 		drawQuad(cmdb);
@@ -207,7 +206,6 @@ void LightShading::populateRenderGraph(RenderingContext& ctx)
 	// Refl & indirect
 	// Refl & indirect
 	pass.newDependency({m_r->getSsr().getRt(), TextureUsageBit::SAMPLED_FRAGMENT});
 	pass.newDependency({m_r->getSsr().getRt(), TextureUsageBit::SAMPLED_FRAGMENT});
 	pass.newDependency({m_r->getIndirect().getReflectionRt(), TextureUsageBit::SAMPLED_FRAGMENT});
 	pass.newDependency({m_r->getIndirect().getReflectionRt(), TextureUsageBit::SAMPLED_FRAGMENT});
-	pass.newDependency({m_r->getIndirect().getIrradianceRt(), TextureUsageBit::SAMPLED_FRAGMENT});
 
 
 	m_r->getGlobalIllumination().setRenderGraphDependencies(ctx, pass, TextureUsageBit::SAMPLED_FRAGMENT);
 	m_r->getGlobalIllumination().setRenderGraphDependencies(ctx, pass, TextureUsageBit::SAMPLED_FRAGMENT);