|
@@ -5,7 +5,7 @@
|
|
|
|
|
|
|
|
// 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 WORKGROUP_SIZE
|
|
|
|
|
|
|
+#pragma anki mutator WORKGROUP_SIZE_XY 8 16 32
|
|
|
#pragma anki mutator LIGHT_SHADING_TEX 0 1 // 0: texture2D, 1: textureCubeArray
|
|
#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 STORE_LOCATION 0 1 // 0: in a 3D texture, 1: In an SSBO
|
|
|
#pragma anki mutator SECOND_BOUNCE 0 1
|
|
#pragma anki mutator SECOND_BOUNCE 0 1
|
|
@@ -18,23 +18,25 @@
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
|
|
-layout(local_size_x = WORKGROUP_SIZE, local_size_y = WORKGROUP_SIZE, local_size_z = 1) in;
|
|
|
|
|
|
|
+const U32 WORKGROUP_SIZE = WORKGROUP_SIZE_XY * WORKGROUP_SIZE_XY;
|
|
|
|
|
+
|
|
|
|
|
+layout(local_size_x = WORKGROUP_SIZE_XY, local_size_y = WORKGROUP_SIZE_XY, 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
|
|
#if LIGHT_SHADING_TEX == 0
|
|
|
-layout(set = 0, binding = 1) uniform texture2D u_lightShadingTex;
|
|
|
|
|
|
|
+layout(set = 0, binding = 1) uniform texture2D u_lightShadingTex2d;
|
|
|
#else
|
|
#else
|
|
|
-layout(set = 0, binding = 1) uniform textureCube u_lightShadingTex;
|
|
|
|
|
|
|
+layout(set = 0, binding = 1) uniform textureCube u_lightShadingTexCube;
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
#if SECOND_BOUNCE == 1
|
|
#if SECOND_BOUNCE == 1
|
|
|
layout(set = 0, binding = 2) uniform texture2D u_gbufferTex[3u];
|
|
layout(set = 0, binding = 2) uniform texture2D u_gbufferTex[3u];
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
-// This is a temporary buffer used instead of shared memory because the needs are too large
|
|
|
|
|
|
|
+// This is a temporary buffer used instead of shared memory because we can't fit it into shared memory
|
|
|
layout(set = 0, binding = 3, std430) buffer ssbo_
|
|
layout(set = 0, binding = 3, std430) buffer ssbo_
|
|
|
{
|
|
{
|
|
|
- Vec4 u_integrationResults[6u][WORKGROUP_SIZE * WORKGROUP_SIZE];
|
|
|
|
|
|
|
+ Vec4 u_integrationResults[6u * WORKGROUP_SIZE];
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
#if STORE_LOCATION == 0
|
|
#if STORE_LOCATION == 0
|
|
@@ -57,26 +59,26 @@ shared Vec3 s_diceIrradiance[6u];
|
|
|
Vec3 sampleLightShadingTexture(const U32 face)
|
|
Vec3 sampleLightShadingTexture(const U32 face)
|
|
|
{
|
|
{
|
|
|
#if LIGHT_SHADING_TEX == 0
|
|
#if LIGHT_SHADING_TEX == 0
|
|
|
- const Vec2 INPUT_TEXTURES_SIZE = Vec2(WORKGROUP_SIZE * 6u, WORKGROUP_SIZE);
|
|
|
|
|
|
|
+ const Vec2 INPUT_TEXTURES_SIZE = Vec2(WORKGROUP_SIZE_XY * 6u, WORKGROUP_SIZE_XY);
|
|
|
const Vec2 uv =
|
|
const Vec2 uv =
|
|
|
- (Vec2(gl_LocalInvocationID.x + WORKGROUP_SIZE * face, gl_LocalInvocationID.y) + 0.5) / INPUT_TEXTURES_SIZE;
|
|
|
|
|
|
|
+ (Vec2(gl_LocalInvocationID.x + WORKGROUP_SIZE_XY * face, gl_LocalInvocationID.y) + 0.5) / INPUT_TEXTURES_SIZE;
|
|
|
|
|
|
|
|
- return textureLod(u_lightShadingTex, u_nearestAnyClampSampler, uv, 0.0).rgb;
|
|
|
|
|
|
|
+ return textureLod(u_lightShadingTex2d, u_nearestAnyClampSampler, uv, 0.0).rgb;
|
|
|
#else
|
|
#else
|
|
|
- const Vec2 uv = (Vec2(gl_LocalInvocationID.x, gl_LocalInvocationID.y) + 0.5) / F32(WORKGROUP_SIZE);
|
|
|
|
|
|
|
+ const Vec2 uv = (Vec2(gl_LocalInvocationID.x, gl_LocalInvocationID.y) + 0.5) / F32(WORKGROUP_SIZE_XY);
|
|
|
const Vec2 ndc = UV_TO_NDC(uv);
|
|
const Vec2 ndc = UV_TO_NDC(uv);
|
|
|
const Vec3 cubeUvw = getCubemapDirection(ndc, face);
|
|
const Vec3 cubeUvw = getCubemapDirection(ndc, face);
|
|
|
|
|
|
|
|
- return textureLod(u_lightShadingTex, u_nearestAnyClampSampler, cubeUvw, 0.0).rgb;
|
|
|
|
|
|
|
+ return textureLod(u_lightShadingTexCube, u_nearestAnyClampSampler, cubeUvw, 0.0).rgb;
|
|
|
#endif
|
|
#endif
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void main()
|
|
void main()
|
|
|
{
|
|
{
|
|
|
- const F32 WORKGROUP_SIZE_F = F32(WORKGROUP_SIZE);
|
|
|
|
|
|
|
+ const F32 WORKGROUP_SIZE_XY_F = F32(WORKGROUP_SIZE_XY);
|
|
|
|
|
|
|
|
// Compute the NDC used in cubeCoordSolidAngle
|
|
// Compute the NDC used in cubeCoordSolidAngle
|
|
|
- const Vec2 faceUv = (Vec2(gl_LocalInvocationID.xy) + 0.5) / WORKGROUP_SIZE_F;
|
|
|
|
|
|
|
+ const Vec2 faceUv = (Vec2(gl_LocalInvocationID.xy) + 0.5) / WORKGROUP_SIZE_XY_F;
|
|
|
const Vec2 ndc = UV_TO_NDC(faceUv);
|
|
const Vec2 ndc = UV_TO_NDC(faceUv);
|
|
|
|
|
|
|
|
// Initialize
|
|
// Initialize
|
|
@@ -90,25 +92,25 @@ 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 = sampleLightShadingTexture(f);
|
|
const Vec3 lightShading = sampleLightShadingTexture(f);
|
|
|
- const Vec3 irradiance = lightShading * lambert * cubeCoordSolidAngle(ndc, WORKGROUP_SIZE_F);
|
|
|
|
|
|
|
+ const Vec3 irradiance = lightShading * lambert * cubeCoordSolidAngle(ndc, WORKGROUP_SIZE_XY_F);
|
|
|
|
|
|
|
|
// Store
|
|
// Store
|
|
|
- u_integrationResults[f][gl_LocalInvocationID.y * WORKGROUP_SIZE + gl_LocalInvocationID.x] = irradiance.xyzx;
|
|
|
|
|
|
|
+ u_integrationResults[f * WORKGROUP_SIZE + gl_LocalInvocationID.y * WORKGROUP_SIZE_XY + gl_LocalInvocationID.x] =
|
|
|
|
|
+ irradiance.xyzx;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
memoryBarrierBuffer();
|
|
memoryBarrierBuffer();
|
|
|
barrier();
|
|
barrier();
|
|
|
|
|
|
|
|
// Reduce using prefix sum
|
|
// Reduce using prefix sum
|
|
|
- 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 = WORKGROUP_SIZE / 2u; s > 0u; s >>= 1u)
|
|
|
{
|
|
{
|
|
|
if(gl_LocalInvocationIndex < s)
|
|
if(gl_LocalInvocationIndex < s)
|
|
|
{
|
|
{
|
|
|
ANKI_UNROLL for(U32 f = 0u; f < 6u; ++f)
|
|
ANKI_UNROLL for(U32 f = 0u; f < 6u; ++f)
|
|
|
{
|
|
{
|
|
|
- u_integrationResults[f][gl_LocalInvocationIndex] +=
|
|
|
|
|
- u_integrationResults[f][gl_LocalInvocationIndex + s];
|
|
|
|
|
|
|
+ u_integrationResults[f * WORKGROUP_SIZE + gl_LocalInvocationIndex] +=
|
|
|
|
|
+ u_integrationResults[f * WORKGROUP_SIZE + gl_LocalInvocationIndex + s];
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -118,7 +120,8 @@ void main()
|
|
|
|
|
|
|
|
if(gl_LocalInvocationIndex < 6u)
|
|
if(gl_LocalInvocationIndex < 6u)
|
|
|
{
|
|
{
|
|
|
- s_diceIrradiance[gl_LocalInvocationIndex] = u_integrationResults[gl_LocalInvocationIndex][0].xyz;
|
|
|
|
|
|
|
+ s_diceIrradiance[gl_LocalInvocationIndex] =
|
|
|
|
|
+ u_integrationResults[gl_LocalInvocationIndex * WORKGROUP_SIZE + 0u].xyz;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
memoryBarrierShared();
|
|
memoryBarrierShared();
|
|
@@ -137,7 +140,7 @@ 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;
|
|
|
|
|
|
|
+ Vec2 gbufferUv = (Vec2(gl_LocalInvocationID.xy) + 0.5) / WORKGROUP_SIZE_XY_F;
|
|
|
gbufferUv.x *= 1.0 / 6.0;
|
|
gbufferUv.x *= 1.0 / 6.0;
|
|
|
gbufferUv.x += (1.0 / 6.0) * F32(f);
|
|
gbufferUv.x += (1.0 / 6.0) * F32(f);
|
|
|
GbufferInfo gbuffer;
|
|
GbufferInfo gbuffer;
|
|
@@ -157,24 +160,25 @@ void main()
|
|
|
// Compute 2nd bounce
|
|
// Compute 2nd bounce
|
|
|
const Vec3 lightShading = sampleLightShadingTexture(f);
|
|
const Vec3 lightShading = sampleLightShadingTexture(f);
|
|
|
const Vec3 irradiance =
|
|
const Vec3 irradiance =
|
|
|
- (firstBounceIrradiance + lightShading * lambert) * cubeCoordSolidAngle(ndc, WORKGROUP_SIZE_F);
|
|
|
|
|
|
|
+ (firstBounceIrradiance + lightShading * lambert) * cubeCoordSolidAngle(ndc, WORKGROUP_SIZE_XY_F);
|
|
|
|
|
|
|
|
// Store
|
|
// Store
|
|
|
- u_integrationResults[f][gl_LocalInvocationID.y * WORKGROUP_SIZE + gl_LocalInvocationID.x] = irradiance.xyzx;
|
|
|
|
|
|
|
+ u_integrationResults[f * WORKGROUP_SIZE + gl_LocalInvocationID.y * WORKGROUP_SIZE_XY + gl_LocalInvocationID.x] =
|
|
|
|
|
+ irradiance.xyzx;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
memoryBarrierBuffer();
|
|
memoryBarrierBuffer();
|
|
|
barrier();
|
|
barrier();
|
|
|
|
|
|
|
|
// Reduce using prefix sum again
|
|
// Reduce using prefix sum again
|
|
|
- ANKI_LOOP for(U32 s = WG_SIZE / 2u; s > 0u; s >>= 1u)
|
|
|
|
|
|
|
+ ANKI_LOOP for(U32 s = WORKGROUP_SIZE / 2u; s > 0u; s >>= 1u)
|
|
|
{
|
|
{
|
|
|
if(gl_LocalInvocationIndex < s)
|
|
if(gl_LocalInvocationIndex < s)
|
|
|
{
|
|
{
|
|
|
ANKI_UNROLL for(U32 f = 0u; f < 6u; ++f)
|
|
ANKI_UNROLL for(U32 f = 0u; f < 6u; ++f)
|
|
|
{
|
|
{
|
|
|
- u_integrationResults[f][gl_LocalInvocationIndex] +=
|
|
|
|
|
- u_integrationResults[f][gl_LocalInvocationIndex + s];
|
|
|
|
|
|
|
+ u_integrationResults[f * WORKGROUP_SIZE + gl_LocalInvocationIndex] +=
|
|
|
|
|
+ u_integrationResults[f * WORKGROUP_SIZE + gl_LocalInvocationIndex + s];
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -190,7 +194,7 @@ void main()
|
|
|
|
|
|
|
|
#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 * WORKGROUP_SIZE + 0u].xyz;
|
|
|
# else
|
|
# else
|
|
|
Vec3 irradiance = s_diceIrradiance[f];
|
|
Vec3 irradiance = s_diceIrradiance[f];
|
|
|
# endif
|
|
# endif
|