#version 460 compatibility
#define COMP 1
#extension GL_KHR_shader_subgroup_arithmetic : enable
#extension GL_KHR_shader_subgroup_ballot : enable
#define GLOBAL_DATA_MODIFIER buffer
/*
    References:
        [WRE18] Wrensch, Benjamin. "Reverse Z Cheatsheet". IOLITE Development Blog. 2023.
*/
/*
    References:
        [WHY23] Whyte, Killian. "Soft Clamp Function". 2023.
            https:

        You can find full license texts in /licenses
*/
// This file is generated by options.main.kts. Do not edit this file manually.
#define TITLE_VERSION 3//[0 1 2 3 4 5]
#define SETTING_SHADOW_MAP_RESOLUTION 2048//[1024 2048 3072 4096]
const float shadowDistance = 512.0;//[64.0 128.0 192.0 256.0 384.0 512.0]
const float sunPathRotation = -20.0;//[-90.0 -89.0 -88.0 -87.0 -86.0 -85.0 -84.0 -83.0 -82.0 -81.0 -80.0 -79.0 -78.0 -77.0 -76.0 -75.0 -74.0 -73.0 -72.0 -71.0 -70.0 -69.0 -68.0 -67.0 -66.0 -65.0 -64.0 -63.0 -62.0 -61.0 -60.0 -59.0 -58.0 -57.0 -56.0 -55.0 -54.0 -53.0 -52.0 -51.0 -50.0 -49.0 -48.0 -47.0 -46.0 -45.0 -44.0 -43.0 -42.0 -41.0 -40.0 -39.0 -38.0 -37.0 -36.0 -35.0 -34.0 -33.0 -32.0 -31.0 -30.0 -29.0 -28.0 -27.0 -26.0 -25.0 -24.0 -23.0 -22.0 -21.0 -20.0 -19.0 -18.0 -17.0 -16.0 -15.0 -14.0 -13.0 -12.0 -11.0 -10.0 -9.0 -8.0 -7.0 -6.0 -5.0 -4.0 -3.0 -2.0 -1.0 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0 16.0 17.0 18.0 19.0 20.0 21.0 22.0 23.0 24.0 25.0 26.0 27.0 28.0 29.0 30.0 31.0 32.0 33.0 34.0 35.0 36.0 37.0 38.0 39.0 40.0 41.0 42.0 43.0 44.0 45.0 46.0 47.0 48.0 49.0 50.0 51.0 52.0 53.0 54.0 55.0 56.0 57.0 58.0 59.0 60.0 61.0 62.0 63.0 64.0 65.0 66.0 67.0 68.0 69.0 70.0 71.0 72.0 73.0 74.0 75.0 76.0 77.0 78.0 79.0 80.0 81.0 82.0 83.0 84.0 85.0 86.0 87.0 88.0 89.0 90.0]
//#define SETTING_ASSUME_NVIDIA_GPU
#ifdef SETTING_ASSUME_NVIDIA_GPU
#endif
//#define SETTING_DEBUG_AE
#ifdef SETTING_DEBUG_AE
#endif
#if SETTING_SHADOW_MAP_RESOLUTION == 1024
#define SHADOW_MAP_SIZE_D16 64
const int shadowMapResolution = 1024;
#elif SETTING_SHADOW_MAP_RESOLUTION == 2048
#define SHADOW_MAP_SIZE_D16 128
const int shadowMapResolution = 2048;
#elif SETTING_SHADOW_MAP_RESOLUTION == 3072
#define SHADOW_MAP_SIZE_D16 192
const int shadowMapResolution = 3072;
#elif SETTING_SHADOW_MAP_RESOLUTION == 4096
#define SHADOW_MAP_SIZE_D16 256
const int shadowMapResolution = 4096;
#endif
uniform float near;
uniform float far;
uniform mat4 gbufferModelViewInverse;
uniform mat4 gbufferPreviousModelView;
uniform mat4 shadowModelView;
uniform int isEyeInWater;
uniform mat4 textureMatrix = mat4(1.0);
float vanillaFarPlane = far;
float vanillaNearPlane = near;
#ifdef DISTANT_HORIZONS
uniform float dhNearPlane;
uniform float dhFarPlane;
float farPlane = max(dhFarPlane, far);
float nearPlane = min(dhNearPlane, near);
#else
float farPlane = far;
float nearPlane = near;
#endif
uniform vec2 uval_mainImageSizeRcp;
uniform int uval_mainImageSizeIX;
uniform int uval_mainImageSizeIY;
ivec2 uval_mainImageSizeI = ivec2(uval_mainImageSizeIX, uval_mainImageSizeIY);
#ifndef GLOBAL_DATA_MODIFIER
#define GLOBAL_DATA_MODIFIER restrict readonly buffer
#endif
struct AEData {
    vec4 lastScreenAvgLum;
    vec4 screenAvgLum;
    vec4 expValues;
    vec2 hsPercents;
    uint shadowCount;
    uint highlightCount;
    uint weightSum;
    #ifdef SETTING_DEBUG_AE
    uint lumHistogram[256];
    uint lumHistogramMaxBinCount;
    float finalAvgLum;
    #endif
};
struct CameraData {
    uint frustumPlaneCount;
    vec4 frustumPlanes[6];
};
mat4 gbufferPrevModelView = gbufferPreviousModelView;
layout(std430, binding = 0) GLOBAL_DATA_MODIFIER GlobalData {
    uvec4 global_dispatchSize1;
    uvec4 global_dispatchSize2;
    uvec4 global_dispatchSize3;
    uvec4 global_dispatchSize4;
    mat4 gbufferPrevModelViewInverse;
    mat4 global_shadowRotationMatrix;
    mat4 global_shadowRotationMatrixInverse;
    mat4 global_taaJitterMat;
    mat4 global_camProj;
    mat4 global_camProjInverse;
    mat4 global_prevCamProj;
    mat4 global_prevCamProjInverse;
    mat4 global_shadowProj;
    mat4 global_shadowProjInverse;
    mat4 global_shadowProjNext;
    mat4 global_shadowProjNextInverse;
    mat4 global_shadowView;
    mat4 global_shadowViewInverse;
    mat4 global_sceneToShadowNDC;
    mat4 global_shadowViewToShadowNDC;
    mat4 global_shadowNDCToScene;
    vec3 global_prevCameraDelta;
    vec2 global_prevTaaJitter;
    vec2 global_taaJitter;
    CameraData global_cameraData;
    vec2 global_mipmapSizes[16];
    vec2 global_mipmapSizesRcp[16];
    ivec4 global_mipmapTiles3[16];
    ivec2 global_mipmapSizesI[16];
    ivec2 global_mipmapSizePrefixesPadded[16];
    ivec2 global_mipmapSizePrefixes[16];
    ivec4 global_hizTiles[16];
    ivec4 global_mipmapTileCeil[16];
    ivec4 global_mipmapTileCeilPadded[16];
    ivec3 global_shadowAABBMinPrev;
    ivec3 global_shadowAABBMaxPrev;
    ivec3 global_shadowAABBMin;
    ivec3 global_shadowAABBMax;
    vec3 global_shadowAABBMinHistory;
    vec3 global_shadowAABBMaxHistory;
    ivec3 global_shadowAABBMinNew;
    ivec3 global_shadowAABBMaxNew;
    float global_focusDistance;
    int global_lastWorldTime;
    float global_historyResetFactor;
    vec4 global_motionFactor;
    vec4 global_taaResetFactor;
    float global_turbidity;
    AEData global_aeData;
    uint global_atomicCounters[16];
};
layout(std430, binding = 1) GLOBAL_DATA_MODIFIER IndirectComputeData {
    uint indirectComputeData[];
};
const vec2 SHADOW_MAP_SIZE = vec2(float(shadowMapResolution), 1.0 / float(shadowMapResolution));
uniform sampler2D colortex10;
uniform sampler2D usam_csr32f;
#define saturate(x) clamp(x, 0.0, 1.0)
ivec2 _textile_texelToTexel(ivec2 texelPos, ivec2 tileOffset, ivec2 tileSize) {
    return clamp(texelPos, ivec2(0), tileSize - 1) + tileOffset;
}
vec2 _textile_uvToUV(vec2 uv, vec2 tileOffsetF, vec2 tileSizeF, vec2 atlastSizeRcp) {
    vec2 textureTexelPos = clamp(uv * tileSizeF, vec2(0.5), tileSizeF - 0.5) + tileOffsetF;
    return saturate(textureTexelPos * atlastSizeRcp);
}
vec2 _textile_uvToGatherUV(vec2 uv, vec2 tileOffsetF, vec2 tileSizeF, vec2 atlastSizeRcp) {
    vec2 textureTexelPos = clamp(uv * tileSizeF, vec2(1.0), tileSizeF - 1.0) + tileOffsetF;
    return saturate(textureTexelPos * atlastSizeRcp);
}
vec2 _textile_texelToGatherUV(vec2 texelPos, vec2 tileOffsetF, vec2 tileSizeF, vec2 atlastSizeRcp) {
    vec2 textureTexelPos = clamp(texelPos, vec2(1.0), tileSizeF - 1.0) + tileOffsetF;
    return saturate(textureTexelPos * atlastSizeRcp);
}
#undef saturate
#define _shadesmith_RG32UI_0_OFFSET (uval_mainImageSizeI * ivec2(0, 0))
#define _shadesmith_RG32UI_0_SIZE uval_mainImageSizeI
#define _shadesmith_RG32UI_0_TEXEL_TO_TEXEL(texelPos) _textile_texelToTexel(texelPos, _shadesmith_RG32UI_0_OFFSET, _shadesmith_RG32UI_0_SIZE)
#define _shadesmith_RG32UI_1_OFFSET (uval_mainImageSizeI * ivec2(0, 1))
#define _shadesmith_RG32UI_1_SIZE uval_mainImageSizeI
#define _shadesmith_RG32UI_1_TEXEL_TO_TEXEL(texelPos) _textile_texelToTexel(texelPos, _shadesmith_RG32UI_1_OFFSET, _shadesmith_RG32UI_1_SIZE)
#define _shadesmith_RG32UI_2_OFFSET (uval_mainImageSizeI * ivec2(1, 0))
#define _shadesmith_RG32UI_2_SIZE uval_mainImageSizeI
#define _shadesmith_RG32UI_2_TEXEL_TO_TEXEL(texelPos) _textile_texelToTexel(texelPos, _shadesmith_RG32UI_2_OFFSET, _shadesmith_RG32UI_2_SIZE)
#define transient_translucentZLayer1_store(x, v) imageStore(uimg_rg32ui, _shadesmith_RG32UI_0_TEXEL_TO_TEXEL(x), v)
#define transient_translucentZLayer2_store(x, v) imageStore(uimg_rg32ui, _shadesmith_RG32UI_1_TEXEL_TO_TEXEL(x), v)
#define transient_translucentZLayer3_store(x, v) imageStore(uimg_rg32ui, _shadesmith_RG32UI_2_TEXEL_TO_TEXEL(x), v)
#if defined MC_GL_AMD_gpu_shader_half_float
#extension GL_AMD_gpu_shader_half_float : enable
#elif defined MC_GL_NV_gpu_shader5 || defined SETTING_ASSUME_NVIDIA_GPU
#extension GL_NV_gpu_shader5 : enable
#else
#define NO_HALF a
#define hf
#define float16_t float
#define f16vec2 vec2
#define f16vec3 vec3
#define f16vec4 vec4
#define f16mat2 mat2
#define f16mat3 mat3
#define f16mat4 mat4
#endif
#define PI 3.14159265358979323846
#define PI_2 (2.0 * PI)
#define PI_HALF (0.5 * PI)
#define PI_QUARTER (0.25 * PI)
#define RCP_PI (1.0 / PI)
#define RCP_PI_2 (1.0 / PI_2)
#define RCP_PI_HALF (1.0 / PI_HALF)
#define GOLDEN_RATIO 1.618033988749
#define GOLDEN_ANGLE 2.39996322972865332
#define SPHERE_SOLID_ANGLE (4.0 * PI)
#define FLT_MAX uintBitsToFloat(0x7F7FFFFF)
#define FLT_MIN uintBitsToFloat(0x00800000)
#define FLT_TRUE_MIN uintBitsToFloat(0x00000001)
#define FLT_POS_INF uintBitsToFloat(0x7F800000)
#define FLT_NEG_INF uintBitsToFloat(0xFF800000)
#define FP16_MAX 65504.0
#define INT32_MAX 2147483647
#define INT32_MIN -2147483648
#define rcp(x) (1.0 / (x))
#define saturate(x) clamp(x, 0.0, 1.0)
float max2(float x, float y) { return max(x, y); }
float max2(vec2 v) { return max(v.x, v.y); }
float max4(float x, float y, float z, float w) { return max(x, max(y, max(z, w))); }
float max4(vec4 v) { return max(max(v.x, v.y), max(v.z, v.w)); }
float min2(float x, float y) { return min(x, y); }
float min2(vec2 v) { return min(v.x, v.y); }
float min4(float x, float y, float z, float w) { return min(x, min(y, min(z, w))); }
float min4(vec4 v) { return min(min(v.x, v.y), min(v.z, v.w)); }
float pow2(float x) { return x * x; }
vec2 pow2(vec2 x) { return x * x; }
vec3 pow2(vec3 x) { return x * x; }
vec4 pow2(vec4 x) { return x * x; }
#ifndef NO_HALF
float16_t pow2(float16_t x) { return x * x; }
f16vec2 pow2(f16vec2 x) { return x * x; }
f16vec3 pow2(f16vec3 x) { return x * x; }
f16vec4 pow2(f16vec4 x) { return x * x; }
#endif
float lengthSq(float x) { return x * x; }
float lengthSq(vec2 x) { return dot(x, x); }
float lengthSq(vec3 x) { return dot(x, x); }
float lengthSq(vec4 x) { return dot(x, x); }
vec3 coords_toViewCoord(vec2 texCoord, float viewZ, mat4 projInv) {
    vec2 ndcXY = texCoord * 2.0 - 1.0;
    vec2 clipXY = ndcXY * -viewZ;
    vec2 viewXY = clipXY * vec2(projInv[0][0], projInv[1][1]);
    return vec3(viewXY, viewZ);
}
vec2 coords_texelToUV(ivec2 texelPos, vec2 rcpTextureSize) {
    return saturate((vec2(texelPos) + 0.5) * rcpTextureSize);
}
const mat3 _COORDS_EQUATORIAL_TO_GALACTIC = mat3(
    -0.0548755604, 0.4941094279, -0.8676661490,
    -0.8734370902, -0.4448296300, -0.1980763734,
    -0.4838350155, 0.7469822445, 0.4559837762
);
const mat3 _COORDS_WORLD_TO_EQUATORIAL = mat3(
    0.0, 1.0, 0.0,
    1.0, 0.0, 0.0,
    0.0, 0.0, -1.0
);
ivec2 texelPos = ivec2(gl_GlobalInvocationID.xy);
ivec2 textile_texelToTexel(ivec2 texelPos, ivec2 tileOffset, ivec2 tileSize) {
    return clamp(texelPos, ivec2(0), tileSize - 1) + tileOffset;
}
ivec2 csr32f_tile1_texelToTexel(ivec2 texelPos) {
    return textile_texelToTexel(
        texelPos,
        ivec2(0),
        uval_mainImageSizeI
    );
}
ivec2 csr32f_tile2_texelToTexel(ivec2 texelPos) {
    return textile_texelToTexel(
        texelPos,
        ivec2(uval_mainImageSizeI.x, 0),
        uval_mainImageSizeI
    );
}
ivec2 csr32f_tile3_texelToTexel(ivec2 texelPos) {
    return textile_texelToTexel(
        texelPos,
        ivec2(0, uval_mainImageSizeI.y),
        uval_mainImageSizeI
    );
}
ivec2 csr32f_tile4_texelToTexel(ivec2 texelPos) {
    return textile_texelToTexel(
        texelPos,
        ivec2(uval_mainImageSizeI.xy),
        uval_mainImageSizeI
    );
}
layout(local_size_x = 16, local_size_y = 16) in;
const vec2 workGroupsRender = vec2(1.0, 1.0);
layout(rg32ui) uniform writeonly uimage2D uimg_rg32ui;
shared vec4 shared_dilateData[16];
shared vec3 shared_shadowAABBMin[16];
shared vec3 shared_shadowAABBMax[16];
const float EPS = 0.5;
void shadowAABB1(vec3 shadowViewPosMin, vec3 shadowViewPosMax) {
    vec3 min1 = subgroupMin(shadowViewPosMin);
    vec3 max1 = subgroupMax(shadowViewPosMax);
    if (subgroupElect()) {
        shared_shadowAABBMin[gl_SubgroupID] = min1;
        shared_shadowAABBMax[gl_SubgroupID] = max1;
    }
}
void shadowAABB2() {
    if (gl_SubgroupID == 0 && gl_SubgroupInvocationID < gl_NumSubgroups) {
        vec3 min2 = shared_shadowAABBMin[gl_SubgroupInvocationID];
        vec3 max2 = shared_shadowAABBMax[gl_SubgroupInvocationID];
        vec3 min3 = subgroupMin(min2);
        vec3 max3 = subgroupMax(max2);
        if (subgroupElect()) {
            ivec3 min4 = ivec3(floor(min3 / 16.0)) * 16;
            ivec3 max4 = ivec3(ceil(max3 / 16.0)) * 16;
            atomicMin(global_shadowAABBMinNew.x, min4.x);
            atomicMin(global_shadowAABBMinNew.y, min4.y);
            atomicMin(global_shadowAABBMinNew.z, min4.z);
            atomicMax(global_shadowAABBMaxNew.x, max4.x);
            atomicMax(global_shadowAABBMaxNew.y, max4.y);
            atomicMax(global_shadowAABBMaxNew.z, max4.z);
        }
    }
}
void updateShadowAABB(vec2 screenPos, float viewZ, inout vec3 shadowViewPosMin, inout vec3 shadowViewPosMax) {
    if (viewZ < 0.0 && viewZ > -vanillaFarPlane) {
        vec3 viewPos = coords_toViewCoord(screenPos, viewZ, global_camProjInverse);
        vec4 scenePos = gbufferModelViewInverse * vec4(viewPos, 1.0);
        float distanceSqXZ = lengthSq(scenePos.xz);
        if (distanceSqXZ < pow2(vanillaFarPlane)) {
            vec4 shadowViewPos = global_shadowRotationMatrix * shadowModelView * scenePos;
            shadowViewPosMin = min(shadowViewPosMin, shadowViewPos.xyz);
            shadowViewPosMax = max(shadowViewPosMax, shadowViewPos.xyz);
        }
    }
}
void main() {
    if (gl_LocalInvocationIndex < 16) {
        shared_shadowAABBMax[gl_LocalInvocationIndex] = vec3(0.0);
        shared_shadowAABBMin[gl_LocalInvocationIndex] = vec3(0.0);
    }
    float solid = texelFetch(colortex10, texelPos, 0).r;
    vec2 layer1 = vec2(-FLT_MAX);
    vec2 layer2 = vec2(-FLT_MAX);
    vec2 layer3 = vec2(-FLT_MAX);
    if (all(lessThan(texelPos, uval_mainImageSizeI))) {
        float nearWaterOg = -texelFetch(usam_csr32f, csr32f_tile1_texelToTexel(texelPos), 0).r;
        float nearTranslucentOg = -texelFetch(usam_csr32f, csr32f_tile3_texelToTexel(texelPos), 0).r;
        float farWaterOg = -texelFetch(usam_csr32f, csr32f_tile2_texelToTexel(texelPos), 0).r;
        float farTranslucentOg = -texelFetch(usam_csr32f, csr32f_tile4_texelToTexel(texelPos), 0).r;
        if (isEyeInWater == 1) {
            nearWaterOg = 0.0;
        }
        float farTranslucent = abs(farTranslucentOg - farWaterOg) > EPS * abs(min(farTranslucentOg, farWaterOg)) ? farTranslucentOg : 0.0;
        float farWater = abs(farWaterOg - nearWaterOg) > EPS * abs(min(nearWaterOg, farWaterOg)) ? farWaterOg : 0.0;
        layer1.y = solid;
        layer1.x = min(farWater, farTranslucent);
        layer1.x = layer1.x < 0.0 ? layer1.x : layer1.y;
        layer2.y = layer1.x;
        layer2.x = nearWaterOg > -65536.0 ? nearWaterOg : layer2.y;
        layer3.y = max(layer2.x, nearTranslucentOg);
        layer3.x = 0.0;
        layer1 = layer1.x > layer1.y + EPS ? layer1 : vec2(-FLT_MAX);
        layer2 = layer2.x > layer2.y + EPS ? layer2 : vec2(-FLT_MAX);
    }
    vec4 result = vec4(layer1, layer2);
    vec4 dilated = subgroupMax(result);
    if (subgroupElect()) {
        shared_dilateData[gl_SubgroupID] = dilated;
    }
    barrier();
    if (gl_SubgroupID == 0) {
        vec4 partialMin = gl_SubgroupInvocationID < gl_NumSubgroups ? shared_dilateData[gl_SubgroupInvocationID] : vec4(-FLT_MAX);
        vec4 totalMin = subgroupMax(partialMin);
        shared_dilateData[0] = totalMin;
    }
    barrier();
    vec2 screenPos = coords_texelToUV(texelPos, uval_mainImageSizeRcp);
    vec3 shadowViewPosMin = vec3(0.0);
    vec3 shadowViewPosMax = vec3(0.0);
    updateShadowAABB(screenPos, solid, shadowViewPosMin, shadowViewPosMax);
    updateShadowAABB(screenPos, result.x, shadowViewPosMin, shadowViewPosMax);
    updateShadowAABB(screenPos, result.z, shadowViewPosMin, shadowViewPosMax);
    updateShadowAABB(screenPos, result.z, shadowViewPosMin, shadowViewPosMax);
    updateShadowAABB(screenPos, result.w, shadowViewPosMin, shadowViewPosMax);
    shadowAABB1(shadowViewPosMin, shadowViewPosMax);
    bvec4 dilateCond = equal(result, vec4(-FLT_MAX));
    result = mix(result, shared_dilateData[0], dilateCond);
    if (all(lessThan(texelPos, uval_mainImageSizeI))) {
        result = abs(result) * (vec2(bvec2(any(dilateCond.xy), any(dilateCond.zw))) * 2.0 - 1.0).xxyy;
        uvec4 resultU = floatBitsToUint(result);
        uvec2 layer3U = floatBitsToUint(layer3);
        transient_translucentZLayer1_store(texelPos, resultU.xyxy);
        transient_translucentZLayer2_store(texelPos, resultU.zwzw);
        transient_translucentZLayer3_store(texelPos, layer3U.xyxy);
    }
    barrier();
    shadowAABB2();
}