#include "UnityCG.cginc"

RWStructuredBuffer<uint4> _Waveform;
Texture2D<float4> _Source;

CBUFFER_START (Params)
    uint _IsLinear;
    uint4 _Channels;
CBUFFER_END

#define COLUMNS 384

#pragma kernel KWaveform
[numthreads(1,COLUMNS,1)]
void KWaveform(uint2 dispatchThreadId : SV_DispatchThreadID)
{
    // We want a gamma corrected colors
    float3 color = _Source[dispatchThreadId].rgb;
    if (_IsLinear > 0u)
        color = LinearToGammaSpace(color);

    color = saturate(color);

    // Convert color & luminance to histogram bins
    const float kColumnsMinusOne = COLUMNS - 1.0;
    uint3 idx_c = (uint3)(round(color * kColumnsMinusOne));
    uint idx_l = (uint)(round(dot(color.rgb, float3(0.2126, 0.7152, 0.0722)) * kColumnsMinusOne));

    // A lot of atomic operations will be skipped so there's no need to over-think this one.
    uint j = dispatchThreadId.x * COLUMNS;
    if (_Channels.x > 0u && idx_c.x > 0u) InterlockedAdd(_Waveform[j + idx_c.x].x, 1u); // Red
    if (_Channels.y > 0u && idx_c.y > 0u) InterlockedAdd(_Waveform[j + idx_c.y].y, 1u); // Green
    if (_Channels.z > 0u && idx_c.z > 0u) InterlockedAdd(_Waveform[j + idx_c.z].z, 1u); // Blue
    if (_Channels.w > 0u) InterlockedAdd(_Waveform[j + idx_l].w, 1u); // Luminance
}

#pragma kernel KWaveformClear
[numthreads(1, COLUMNS, 1)]
void KWaveformClear(uint2 dispatchThreadId : SV_DispatchThreadID)
{
    _Waveform[dispatchThreadId.x * COLUMNS + dispatchThreadId.y] = uint4(0u, 0u, 0u, 0u);
}
