#pragma clang diagnostic ignored "-Wmissing-prototypes"
#pragma clang diagnostic ignored "-Wunused-variable"

#include <metal_stdlib>
#include <simd/simd.h>
#include <metal_atomic>

using namespace metal;

// The required alignment of a linear texture of R32Uint format.
constant uint spvLinearTextureAlignmentOverride [[function_constant(65535)]];
constant uint spvLinearTextureAlignment = is_function_constant_defined(spvLinearTextureAlignmentOverride) ? spvLinearTextureAlignmentOverride : 4;
// Returns buffer coords corresponding to 2D texture coords for emulating 2D texture atomics
#define spvImage2DAtomicCoord(tc, tex) (((((tex).get_width() +  spvLinearTextureAlignment / 4 - 1) & ~( spvLinearTextureAlignment / 4 - 1)) * (tc).y) + (tc).x)

constant uint3 gl_WorkGroupSize [[maybe_unused]] = uint3(256u, 1u, 1u);

struct spvDescriptorSetBuffer1
{
    texture2d<uint> rw_spd_global_atomic [[id(0)]];
    volatile device atomic_uint* rw_spd_global_atomic_atomic [[id(1)]];
};

static inline __attribute__((always_inline))
void SPD_IncreaseAtomicCounter(thread uint& spdCounter, texture2d<uint> rw_spd_global_atomic, volatile device atomic_uint* rw_spd_global_atomic_atomic)
{
    uint _25 = atomic_fetch_add_explicit((volatile device atomic_uint*)&rw_spd_global_atomic_atomic[spvImage2DAtomicCoord(int2(0), rw_spd_global_atomic)], 1u, memory_order_relaxed);
    spdCounter = _25;
}

static inline __attribute__((always_inline))
void ComputeAutoExposure(texture2d<uint> rw_spd_global_atomic, volatile device atomic_uint* rw_spd_global_atomic_atomic)
{
    uint v = 0u;
    uint param = v;
    SPD_IncreaseAtomicCounter(param, rw_spd_global_atomic, rw_spd_global_atomic_atomic);
    v = param;
}

kernel void main0(constant spvDescriptorSetBuffer1& spvDescriptorSet1 [[buffer(1)]])
{
    ComputeAutoExposure(spvDescriptorSet1.rw_spd_global_atomic, spvDescriptorSet1.rw_spd_global_atomic_atomic);
}

