/*
 ============================================================================
 Name        : minimum.vx
 Author      : Sam
 Version     :
 Copyright   : Your copyright notice
 Description :
 ============================================================================
 */
#include "cl_viv_vx_ext.h"

_viv_uniform VXC_512Bits uniGetDXY_4x4;
_viv_uniform VXC_512Bits uniConvertF16toF32_4x4;
_viv_uniform int2 packedWH2;
_viv_uniform int  packedWH;
__kernel void vxcTransform_InterP_F16toF16_2D
    (
    __read_only     image2d_array_t input0,
    __read_only     image2d_array_t input1,
    __write_only    image2d_array_t output
    )
{
    int2 coord  =  (int2)(get_global_id(0), get_global_id(1));

    vxc_short8 vec0;
    vxc_half8  pxy;
    vxc_float4 dxy4;
    vxc_int4   pos4;
    short dst = 0;

    VXC_ReadImage(vec0, input1, coord.xy, VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(0, 1, 0, VXC_RM_TowardZero, 0));
    _viv_asm(COPY, pxy, vec0, 4);

    coord.x >>= 1;
    vxc_short2 packedWH_16B;
    _viv_asm(COPY, packedWH_16B, packedWH, 4);
    VXC_DP4x4(dxy4, pxy, packedWH_16B, VXC_MODIFIER(0, 1, 0, VXC_RM_TowardZero, 0), uniGetDXY_4x4);
    dxy4.zw = floor(dxy4.xy);
    pos4.xy = convert_int2(dxy4.zw);
    pos4.zw = convert_int2(ceil(dxy4.xy));

    vxc_short8 vec1;
    vxc_half8  src0, src1;
    VXC_ReadImage(vec0, input0, pos4.xy, VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(0, 1, 0, VXC_RM_TowardZero, 0));
    _viv_asm(COPY, src0, vec0, 8);
    VXC_ReadImage(vec1, input0, pos4.xw, VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(0, 1, 0, VXC_RM_TowardZero, 0));
    _viv_asm(COPY, src1, vec1, 8);

    float2 xyLerp        = dxy4.xy - dxy4.zw;
    float2 oneSub_xyLerp = 1.0f - xyLerp;
    float4 coef          = (float4)(oneSub_xyLerp.x * oneSub_xyLerp.y, xyLerp.x * oneSub_xyLerp.y,
                                    oneSub_xyLerp.x * xyLerp.y, xyLerp.x * xyLerp.y);
    float4  data;

    VXC_DP4x4(data, src0, src1, VXC_MODIFIER(0, 3, 0, VXC_RM_TowardZero, 0), uniConvertF16toF32_4x4);

    data.x = dot(data, coef);

    half tmp;
    _viv_asm(CONV, tmp, data);
    _viv_asm(COPY, dst, tmp, 4);

    VXC_WriteImage(output, coord, dst, VXC_MODIFIER(0, 0, 0,VXC_RM_TowardZero, 0));
}

_viv_uniform int depth;
__kernel void vxcTransform_InterP_F16toF16
    (
    __read_only     image2d_array_t input0,
    __read_only     image2d_array_t input1,
    __write_only    image2d_array_t output
    )
{
    int4 coord  =  (int4)(get_global_id(0), get_global_id(1), 0, 0);

    vxc_short8 vec0;
    vxc_half8  pxy;
    vxc_float4 dxy4;
    vxc_int4   pos4;
    short dst = 0;

    VXC_ReadImage(vec0, input1, coord.xy, VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(0, 1, 0, VXC_RM_TowardZero, 0));
    _viv_asm(COPY, pxy, vec0, 4);

    coord.x >>= 1;
    vxc_short2 packedWH_16B;
    _viv_asm(COPY, packedWH_16B, packedWH, 4);
    VXC_DP4x4(dxy4, pxy, packedWH_16B, VXC_MODIFIER(0, 1, 0, VXC_RM_TowardZero, 0), uniGetDXY_4x4);
    dxy4.zw = floor(dxy4.xy);
    pos4.xy = convert_int2(dxy4.zw);
    pos4.zw = convert_int2(ceil(dxy4.xy));


    float2 xyLerp        = dxy4.xy - dxy4.zw;
    float2 oneSub_xyLerp = 1.0f - xyLerp;
    float4 coef          = (float4)(oneSub_xyLerp.x * oneSub_xyLerp.y, xyLerp.x * oneSub_xyLerp.y,
                                    oneSub_xyLerp.x * xyLerp.y, xyLerp.x * xyLerp.y);

    int4 coord_ = (int4)(pos4.x, pos4.y, 0, 0);
    do
    {
        vxc_short8 vec1;
        vxc_half8  src0, src1;
        VXC_ReadImage2DArray(vec0,input0,coord_,VXC_5BITOFFSET_XY(0,0),VXC_MODIFIER(0,1,0, VXC_RM_TowardZero, 0));
        _viv_asm(COPY, src0, vec0, 8);
        VXC_ReadImage2DArray(vec1,input0,coord_,VXC_5BITOFFSET_XY(0,1),VXC_MODIFIER(0,1,0, VXC_RM_TowardZero, 0));
        _viv_asm(COPY, src1, vec1, 8);

        coord_.z ++;
        float4  data;
        VXC_DP4x4(data, src0, src1, VXC_MODIFIER(0, 3, 0, VXC_RM_TowardZero, 0), uniConvertF16toF32_4x4);

        data.x = dot(data, coef);

        half tmp;
        _viv_asm(CONV, tmp, data);
        _viv_asm(COPY, dst, tmp, 4);


        VXC_WriteImage2DArray(output, coord, dst, VXC_MODIFIER(0, 0, 0,VXC_RM_TowardZero, 0));
        coord.z ++;

    } while (coord.z < depth);
}

