//TAA. Temporal antialiasing.
#version 450
#extension GL_EXT_nonuniform_qualifier : require

const ivec2 _132[4] = ivec2[](ivec2(-1), ivec2(1, -1), ivec2(-1, 1), ivec2(1));

// Vk3DVision (http://3dsurroundgaming.com/) - Stereo Injection
layout(set = 0, binding = 110, std140) uniform Vk3DParams
{
    vec4 stereo;
    vec4 custom_params;
} vk3d_params;

layout(set = 0, binding = 2, std140) uniform PerView
{
    vec4 dynamicResolutionParameters;
    vec4 backbufferSize;
} _171;

layout(set = 0, binding = 100, std430) buffer DebugBuffer
{
    uint debugBuffer[];
} _217;

layout(set = 0, binding = 1) uniform sampler2D depthTex;
layout(set = 0, binding = 0) uniform sampler2D motionVectorsTex;
layout(set = 2, binding = 0) uniform texture2D globalTextures[];
layout(set = 2, binding = 0) uniform textureCube globalCubeTextures[];
layout(set = 2, binding = 0) uniform texture3D global3DTextures[];
layout(set = 1, binding = 0) uniform sampler linearClampSampler;
layout(set = 1, binding = 1) uniform sampler linearRepeatSampler;
layout(set = 1, binding = 2) uniform sampler nearestClampSampler;
layout(set = 1, binding = 3) uniform sampler nearestRepeatSampler;
layout(set = 1, binding = 4) uniform sampler shadowSampler;

layout(location = 0) in vec2 inUV0;
layout(location = 0) out float outTempHistData;

vec2 getScreenNearestDepthScreenUV(sampler2D depthTex_1, vec2 screenUV, vec2 fragmentSize)
{
    vec2 screenUVmod = screenUV;
    float dc = textureLod(depthTex_1, screenUV, 0.0).x;
    float nearestDepth = 1.0;
    for (uint i = 0u; i < 4u; i++)
    {
        vec2 neighborScreenUV = screenUV - (vec2(_132[i]) * fragmentSize);
        float neighborDepth = textureLod(depthTex_1, neighborScreenUV, 0.0).x;
        float currDepthDiff = abs(dc - neighborDepth);
        if (currDepthDiff < nearestDepth)
        {
            nearestDepth = currDepthDiff;
            screenUVmod = neighborScreenUV;
        }
    }
    return screenUVmod;
}

uint decodeMaterialId(float source)
{
    return packSnorm2x16(vec2(source, 0.0));
}

uint unpackUInt16(float val)
{
    return uint(val / 1.52587890625e-05);
}

uint getTemporalHistoryData(vec4 motionVector)
{
    float param = motionVector.z;
    uint materialId = decodeMaterialId(param);
    float param_1 = motionVector.w;
    uint packedIntegerParams = unpackUInt16(param_1);
    uint meshInstId = packedIntegerParams & 16383u;
    bool dynamicObj = meshInstId > 0u;
    bool taaGhostFlag = (packedIntegerParams & 16384u) > 0u;
    uint tempHistData = 0u;
    tempHistData |= uint(int(dynamicObj));
    tempHistData |= uint(taaGhostFlag ? 2 : 0);
    return tempHistData;
}

uint getTemporalHistoryData(sampler2D motionVectorsTex_1, vec2 screenUV)
{
    vec4 motionVector = textureLod(motionVectorsTex_1, screenUV, 0.0);
    vec4 param = motionVector;
    return getTemporalHistoryData(param);
}

void main()
{
    vec2 screenUV = inUV0 * _171.dynamicResolutionParameters.xy;
    
    //flrInput.uv0.x -= vk3d_params.stereo.x *(1-vk3d_params.stereo.y*depth*0.2)*0.5;
    
    vec2 param = screenUV;
    vec2 param_1 = _171.backbufferSize.xy;
    screenUV = getScreenNearestDepthScreenUV(depthTex, param, param_1);
    vec2 param_2 = screenUV;
    uint tempHistData = getTemporalHistoryData(motionVectorsTex, param_2);
    outTempHistData = float(tempHistData) / 255.0;
}


