// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#version 430 core
#extension GL_ARB_gpu_shader_int64 : require

layout (local_size_x = 4, local_size_y = 4) in;

layout(binding = 0, rg32ui) readonly uniform uimage3D bc4_input;
layout(binding = 1, rgba8ui) writeonly uniform uimage3D bc4_output;

layout(location = 0) uniform uvec3 src_offset;
layout(location = 1) uniform uvec3 dst_offset;

// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_compression_rgtc.txt
uint DecompressBlock(uint64_t bits, uvec2 coord) {
    const uint code_offset = 16 + 3 * (4 * coord.y + coord.x);
    const uint code = uint(bits >> code_offset) & 7;
    const uint red0 = uint(bits >> 0) & 0xff;
    const uint red1 = uint(bits >> 8) & 0xff;
    if (red0 > red1) {
        switch (code) {
        case 0:
            return red0;
        case 1:
            return red1;
        case 2:
            return (6 * red0 + 1 * red1) / 7;
        case 3:
            return (5 * red0 + 2 * red1) / 7;
        case 4:
            return (4 * red0 + 3 * red1) / 7;
        case 5:
            return (3 * red0 + 4 * red1) / 7;
        case 6:
            return (2 * red0 + 5 * red1) / 7;
        case 7:
            return (1 * red0 + 6 * red1) / 7;
        }
    } else {
        switch (code) {
        case 0:
            return red0;
        case 1:
            return red1;
        case 2:
            return (4 * red0 + 1 * red1) / 5;
        case 3:
            return (3 * red0 + 2 * red1) / 5;
        case 4:
            return (2 * red0 + 3 * red1) / 5;
        case 5:
            return (1 * red0 + 4 * red1) / 5;
        case 6:
            return 0;
        case 7:
            return 0xff;
        }
    }
    return 0;
}

void main() {
    uvec2 packed_bits = imageLoad(bc4_input, ivec3(gl_WorkGroupID + src_offset)).rg;
    uint64_t bits = packUint2x32(packed_bits);
    uint red = DecompressBlock(bits, gl_LocalInvocationID.xy);
    uvec4 color = uvec4(red & 0xff, 0, 0, 0xff);
    imageStore(bc4_output, ivec3(gl_GlobalInvocationID + dst_offset), color);
}
