#include "cl_viv_vx_ext.h"

_viv_uniform int2 multAndoutZP0;//[0:15] multiplier, [31:63] output zp
_viv_uniform VXC_512Bits uniU8MulAndPostShift_0_Lo_2x8;
_viv_uniform VXC_512Bits uniU8MulAndPostShift_ExLo_2x8;
_viv_uniform VXC_512Bits uniU8MulAndPostShift_ExHi_2x8;
_viv_uniform VXC_512Bits uniDepth2SpaceF16Blk2_lo_2x8;
_viv_uniform VXC_512Bits uniDepth2SpaceF16Blk2_hi_2x8;


#define DEPTH2SPACE_CRD_QINT_TO_QINT(src0_type_name, src1_type_name, read_type, write_type) \
__kernel void depth2space_crd_##src0_type_name##to##src1_type_name( \
    image2d_array_t input, image2d_array_t output, int block_size) \
{ \
    int gidx = get_global_id(0); \
    int gidy = get_global_id(1); \
    int gidz = get_global_id(2); \
    int4 coord_out = (int4)(gidx, gidy, gidz, 0); \
    int block_e2 = block_size * block_size; \
    ushort blk = (ushort)block_size; \
    int inx = (int)((ushort)gidx / blk); \
    int iny = (int)((ushort)gidy / blk); \
    int inz = (gidx  % block_size) + (gidy % block_size) * block_size + gidz * block_e2; \
    int4 coord_in = (int4)(inx, iny, inz, 0); \
    read_type src; \
    VXC_ReadImage2DArray(src,input,coord_in,VXC_5BITOFFSET_XY(0,0),VXC_MODIFIER(0,0,0,VXC_RM_TowardZero, 0)); \
 \
    write_type  dst; \
    vxc_ushort8 ms0; \
    _viv_asm(COPY, ms0, multAndoutZP0, 16); \
    VXC_DP2x8(dst,src,ms0,VXC_MODIFIER(0,7,0,VXC_RM_TowardZero,1),uniU8MulAndPostShift_0_Lo_2x8); \
    VXC_WriteImage2DArray(output, coord_out, dst, VXC_MODIFIER(0, 0, 0, VXC_RM_TowardZero, 0)); \
}
DEPTH2SPACE_CRD_QINT_TO_QINT(U8, U8, vxc_uchar16, vxc_uchar16)
DEPTH2SPACE_CRD_QINT_TO_QINT(I8, I8, vxc_char16, vxc_char16)
DEPTH2SPACE_CRD_QINT_TO_QINT(I16, I16, vxc_short8, vxc_short8)

__kernel void depth2space_crd_F16toF16(
    image2d_array_t input, image2d_array_t output, int block_size)
{
    int gidx = get_global_id(0);
    int gidy = get_global_id(1);
    int gidz = get_global_id(2);
    int4 coord_out = (int4)(gidx, gidy, gidz, 0);
    int block_e2 = block_size * block_size;
    ushort blk = (ushort)block_size;
    int inx = (int)((ushort)gidx / blk);
    int iny = (int)((ushort)gidy / blk);
    int inz = (gidx  % block_size) + (gidy % block_size) * block_size + gidz * block_e2;
    int4 coord_in = (int4)(inx, iny, inz, 0);
    vxc_short8 data;
    VXC_ReadImage2DArray(data,input,coord_in,VXC_5BITOFFSET_XY(0,0),VXC_MODIFIER(0,0,0,VXC_RM_TowardZero, 0));
    VXC_WriteImage2DArray(output, coord_out, data, VXC_MODIFIER(0, 0, 0, VXC_RM_TowardZero, 0));
}

#define DEPTH2SPACE_CRD_QINT_TO_F16(src0_type_name, read_type) \
__kernel void depth2space_crd_##src0_type_name##toF16( \
    image2d_array_t input, image2d_array_t output, int block_size) \
{ \
    int gidx = get_global_id(0); \
    int gidy = get_global_id(1); \
    int gidz = get_global_id(2); \
    int4 coord_out = (int4)(gidx, gidy, gidz, 0); \
    int block_e2 = block_size * block_size; \
    ushort blk = (ushort)block_size; \
    int inx = (int)((ushort)gidx / blk); \
    int iny = (int)((ushort)gidy / blk); \
    int inz = (gidx  % block_size) + (gidy % block_size) * block_size + gidz * block_e2; \
    int4 coord_in = (int4)(inx, iny, inz, 0); \
    read_type src; \
    VXC_ReadImage2DArray(src,input,coord_in,VXC_5BITOFFSET_XY(0,0),VXC_MODIFIER(0,0,0,VXC_RM_TowardZero, 0)); \
 \
    vxc_half8  tmpDst; \
    vxc_short8  dst; \
    vxc_ushort8 ms0; \
    _viv_asm(COPY, ms0, multAndoutZP0, 16); \
    VXC_DP2x8(tmpDst,src,ms0,VXC_MODIFIER(0,7,0,VXC_RM_TowardZero,1),uniU8MulAndPostShift_0_Lo_2x8); \
    _viv_asm(COPY, dst, tmpDst, 16); \
    VXC_WriteImage2DArray(output, coord_out, dst, VXC_MODIFIER(0, 0, 0, VXC_RM_TowardZero, 0)); \
}
DEPTH2SPACE_CRD_QINT_TO_F16(U8, vxc_uchar16)
DEPTH2SPACE_CRD_QINT_TO_F16(I8, vxc_char16)
DEPTH2SPACE_CRD_QINT_TO_F16(I16, vxc_short8)

#define DEPTH2SPACE_CRD_F16_TO_QINT(src1_type_name, write_type) \
__kernel void depth2space_crd_F16to##src1_type_name( \
    image2d_array_t input, image2d_array_t output, int block_size) \
{ \
    int gidx = get_global_id(0); \
    int gidy = get_global_id(1); \
    int gidz = get_global_id(2); \
    int4 coord_out = (int4)(gidx, gidy, gidz, 0); \
    int block_e2 = block_size * block_size; \
    ushort blk = (ushort)block_size; \
    int inx = (int)((ushort)gidx / blk); \
    int iny = (int)((ushort)gidy / blk); \
    int inz = (gidx  % block_size) + (gidy % block_size) * block_size + gidz * block_e2; \
    int4 coord_in = (int4)(inx, iny, inz, 0); \
    vxc_short8 src; \
    VXC_ReadImage2DArray(src,input,coord_in,VXC_5BITOFFSET_XY(0,0),VXC_MODIFIER(0,0,0,VXC_RM_TowardZero, 0)); \
 \
    write_type  dst; \
    vxc_half8 data; \
    vxc_ushort8 ms0; \
    _viv_asm(COPY, ms0, multAndoutZP0, 16); \
    _viv_asm(COPY, data, src, 16); \
    VXC_DP2x8(dst,data,ms0,VXC_MODIFIER(0,7,0,VXC_RM_TowardZero,1),uniU8MulAndPostShift_0_Lo_2x8); \
    VXC_WriteImage2DArray(output, coord_out, dst, VXC_MODIFIER(0, 0, 0, VXC_RM_TowardZero, 0)); \
}
DEPTH2SPACE_CRD_F16_TO_QINT(U8, vxc_uchar16)
DEPTH2SPACE_CRD_F16_TO_QINT(I8, vxc_char16)
DEPTH2SPACE_CRD_F16_TO_QINT(I16, vxc_short8)

#define DEPTH2SPACE_CRD_QINT_TO_QINT_BLK2(src0_type_name, src1_type_name, read_type, write_type) \
__kernel void depth2space_crd_##src0_type_name##to##src1_type_name##_blk2( \
    image2d_array_t input, image2d_array_t output, int block_size) \
{ \
    int gidy = get_global_id(1); \
    int gidz = get_global_id(2); \
    int4 coord_out = (int4)(get_global_id(0), gidy, gidz, gidz); \
    int4 coord_in = coord_out >> 1; \
    coord_in.z = (gidy & 1) * 2 + gidz * 4; \
    coord_in.w = coord_in.z + 1; \
    read_type src; \
    VXC_ReadImage2DArray(src, input, coord_in.xyzz, \
                VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0)); \
    VXC_ReadImage2DArray(src, input, coord_in.xyww, \
                VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(8, 15, 0, VXC_RM_TowardZero, 0)); \
 \
    write_type  dst; \
    vxc_ushort8 ms0; \
    _viv_asm(COPY, ms0, multAndoutZP0, 16); \
    VXC_DP2x8(dst, src, ms0, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 1), uniU8MulAndPostShift_ExLo_2x8); \
    VXC_DP2x8(dst, src, ms0, VXC_MODIFIER(8, 15, 0, VXC_RM_TowardZero, 1), uniU8MulAndPostShift_ExHi_2x8); \
    VXC_WriteImage2DArray(output, coord_out, dst, VXC_MODIFIER(0, 15, 0, VXC_RM_TowardZero, 0)); \
}
DEPTH2SPACE_CRD_QINT_TO_QINT_BLK2(U8, U8, vxc_uchar16, vxc_uchar16)
DEPTH2SPACE_CRD_QINT_TO_QINT_BLK2(I8, I8, vxc_char16, vxc_char16)

__kernel void depth2space_crd_F16toF16_blk2(
    image2d_array_t input, image2d_array_t output, int block_size)
{
    int gidy = get_global_id(1);
    int gidz = get_global_id(2);
    int4 coord_out = (int4)(get_global_id(0), gidy, gidz, gidz);
    int4 coord_in = coord_out >> 1;
    coord_in.z = (gidy & 1) * 2 + gidz * 4;
    coord_in.w = coord_in.z + 1;
    vxc_short8 data0, data1, dst0, dst1;
    VXC_ReadImage2DArray(data0, input, coord_in.xyzz,
             VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0));
    VXC_ReadImage2DArray(data1, input, coord_in.xyww,
             VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0));
    VXC_DP2x8(dst0, data0, data1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniDepth2SpaceF16Blk2_lo_2x8);
    VXC_DP2x8(dst1, data0, data1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniDepth2SpaceF16Blk2_hi_2x8);

    VXC_WriteImage2DArray(output, coord_out, dst0, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0));
    coord_out.x += 8;
    VXC_WriteImage2DArray(output, coord_out, dst1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0));
}

__kernel void depth2space_crd_I16toI16_blk2(
    image2d_array_t input, image2d_array_t output, int block_size)
{
    int gidy = get_global_id(1);
    int gidz = get_global_id(2);
    int4 coord_out = (int4)(get_global_id(0), gidy, gidz, gidz);
    int4 coord_in = coord_out >> 1;
    coord_in.z = (gidy & 1) * 2 + gidz * 4;
    coord_in.w = coord_in.z + 1;
    vxc_short8 src0, src1, data0, data1, dst0, dst1;
    VXC_ReadImage2DArray(src0, input, coord_in.xyzz,
             VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0));
    VXC_ReadImage2DArray(src1, input, coord_in.xyww,
             VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0));
    VXC_DP2x8(data0, src0, src1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniDepth2SpaceF16Blk2_lo_2x8);
    VXC_DP2x8(data1, src0, src1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniDepth2SpaceF16Blk2_hi_2x8);

    vxc_ushort8 ms0;
    _viv_asm(COPY, ms0, multAndoutZP0, 16);
    VXC_DP2x8(dst0, data0, ms0, VXC_MODIFIER(0, 7, 0,VXC_RM_TowardZero, 1), uniU8MulAndPostShift_0_Lo_2x8);
    VXC_DP2x8(dst1, data1, ms0, VXC_MODIFIER(0, 7, 0,VXC_RM_TowardZero, 1), uniU8MulAndPostShift_0_Lo_2x8);

    VXC_WriteImage2DArray(output, coord_out, dst0, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0));
    coord_out.x += 8;
    VXC_WriteImage2DArray(output, coord_out, dst1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0));
}

#define DEPTH2SPACE_CRD_QINT_TO_F16_BLK2(src0_type_name, read_type) \
__kernel void depth2space_crd_##src0_type_name##toF16_blk2( \
    image2d_array_t input, image2d_array_t output, int block_size) \
{ \
    int gidy = get_global_id(1); \
    int gidz = get_global_id(2); \
    int4 coord_out = (int4)(get_global_id(0), gidy, gidz, gidz); \
    int4 coord_in = coord_out >> 1; \
    coord_in.z = (gidy & 1) * 2 + gidz * 4; \
    coord_in.w = coord_in.z + 1; \
    read_type src; \
    VXC_ReadImage2DArray(src, input, coord_in.xyzz, \
                VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0)); \
    VXC_ReadImage2DArray(src, input, coord_in.xyww, \
                VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(8, 15, 0, VXC_RM_TowardZero, 0)); \
 \
    vxc_half8  tmpDst0, tmpDst1; \
    vxc_short8  dst0, dst1; \
    vxc_ushort8 ms0; \
    _viv_asm(COPY, ms0, multAndoutZP0, 16); \
    VXC_DP2x8(tmpDst0, src, ms0, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 1), uniU8MulAndPostShift_ExLo_2x8); \
    VXC_DP2x8(tmpDst1, src, ms0, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 1), uniU8MulAndPostShift_ExHi_2x8); \
    _viv_asm(COPY, dst0, tmpDst0, 16); \
    _viv_asm(COPY, dst1, tmpDst1, 16); \
    VXC_WriteImage2DArray(output, coord_out, dst0, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0)); \
    coord_out.x+=8; \
    VXC_WriteImage2DArray(output, coord_out, dst1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0)); \
}
DEPTH2SPACE_CRD_QINT_TO_F16_BLK2(U8, vxc_uchar16)
DEPTH2SPACE_CRD_QINT_TO_F16_BLK2(I8, vxc_char16)

__kernel void depth2space_crd_I16toF16_blk2(
    image2d_array_t input, image2d_array_t output, int block_size)
{
    int gidy = get_global_id(1);
    int gidz = get_global_id(2);
    int4 coord_out = (int4)(get_global_id(0), gidy, gidz, gidz);
    int4 coord_in = coord_out >> 1;
    coord_in.z = (gidy & 1) * 2 + gidz * 4;
    coord_in.w = coord_in.z + 1;
    vxc_short8 src0, src1, data0, data1, dst0, dst1;
    vxc_half8 tmpDst0, tmpDst1;
    VXC_ReadImage2DArray(src0, input, coord_in.xyzz,
             VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0));
    VXC_ReadImage2DArray(src1, input, coord_in.xyww,
             VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0));
    VXC_DP2x8(data0, src0, src1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniDepth2SpaceF16Blk2_lo_2x8);
    VXC_DP2x8(data1, src0, src1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniDepth2SpaceF16Blk2_hi_2x8);

    vxc_ushort8 ms0;
    _viv_asm(COPY, ms0, multAndoutZP0, 16);
    VXC_DP2x8(tmpDst0, data0, ms0, VXC_MODIFIER(0, 7, 0,VXC_RM_TowardZero, 1), uniU8MulAndPostShift_0_Lo_2x8);
    VXC_DP2x8(tmpDst1, data1, ms0, VXC_MODIFIER(0, 7, 0,VXC_RM_TowardZero, 1), uniU8MulAndPostShift_0_Lo_2x8);
    _viv_asm(COPY, dst0, tmpDst0, 16);
    _viv_asm(COPY, dst1, tmpDst1, 16);
    VXC_WriteImage2DArray(output, coord_out, dst0, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0));
    coord_out.x += 8;
    VXC_WriteImage2DArray(output, coord_out, dst1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0));
}

#define DEPTH2SPACE_CRD_F16_TO_QINT_BLK2(src1_type_name, write_type) \
__kernel void depth2space_crd_F16to##src1_type_name##_blk2( \
    image2d_array_t input, image2d_array_t output, int block_size) \
{ \
    int gidy = get_global_id(1); \
    int gidz = get_global_id(2); \
    int4 coord_out = (int4)(get_global_id(0), gidy, gidz, gidz); \
    int4 coord_in = coord_out >> 1; \
    coord_in.z = (gidy & 1) * 2 + gidz * 4; \
    coord_in.w = coord_in.z + 1; \
    vxc_short8 src0, src1, data0, data1; \
    vxc_half8 tmpDst0, tmpDst1; \
    VXC_ReadImage2DArray(src0, input, coord_in.xyzz, \
             VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0)); \
    VXC_ReadImage2DArray(src1, input, coord_in.xyww, \
             VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0)); \
    VXC_DP2x8(data0, src0, src1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniDepth2SpaceF16Blk2_lo_2x8); \
    VXC_DP2x8(data1, src0, src1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniDepth2SpaceF16Blk2_hi_2x8); \
 \
    write_type  dst; \
    vxc_ushort8 ms0; \
    _viv_asm(COPY, ms0, multAndoutZP0, 16); \
    _viv_asm(COPY, tmpDst0, data0, 16); \
    _viv_asm(COPY, tmpDst1, data1, 16); \
    VXC_DP2x8(dst, tmpDst0, ms0, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 1), uniU8MulAndPostShift_0_Lo_2x8); \
    VXC_DP2x8(dst, tmpDst1, ms0, VXC_MODIFIER(8, 15, 0, VXC_RM_TowardZero, 1), uniU8MulAndPostShift_0_Lo_2x8); \
    VXC_WriteImage2DArray(output, coord_out, dst, VXC_MODIFIER(0, 15, 0, VXC_RM_TowardZero, 0)); \
}
DEPTH2SPACE_CRD_F16_TO_QINT_BLK2(U8, vxc_uchar16)
DEPTH2SPACE_CRD_F16_TO_QINT_BLK2(I8, vxc_char16)

__kernel void depth2space_crd_F16toI16_blk2(
    image2d_array_t input, image2d_array_t output, int block_size)
{
    int gidy = get_global_id(1);
    int gidz = get_global_id(2);
    int4 coord_out = (int4)(get_global_id(0), gidy, gidz, gidz);
    int4 coord_in = coord_out >> 1;
    coord_in.z = (gidy & 1) * 2 + gidz * 4;
    coord_in.w = coord_in.z + 1;
    vxc_short8 src0, src1, data0, data1, dst0, dst1;
    vxc_half8 tmpDst0, tmpDst1;
    VXC_ReadImage2DArray(src0, input, coord_in.xyzz,
             VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0));
    VXC_ReadImage2DArray(src1, input, coord_in.xyww,
             VXC_5BITOFFSET_XY(0, 0), VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0));
    vxc_ushort8 ms0;
    _viv_asm(COPY, ms0, multAndoutZP0, 16);
    VXC_DP2x8(data0, src0, src1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniDepth2SpaceF16Blk2_lo_2x8);
    VXC_DP2x8(data1, src0, src1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0), uniDepth2SpaceF16Blk2_hi_2x8);
    _viv_asm(COPY, tmpDst0, data0, 16);
    _viv_asm(COPY, tmpDst1, data1, 16);
    VXC_DP2x8(dst0, tmpDst0, ms0, VXC_MODIFIER(0, 7, 0,VXC_RM_TowardZero, 1), uniU8MulAndPostShift_0_Lo_2x8);
    VXC_DP2x8(dst1, tmpDst1, ms0, VXC_MODIFIER(0, 7, 0,VXC_RM_TowardZero, 1), uniU8MulAndPostShift_0_Lo_2x8);

    VXC_WriteImage2DArray(output, coord_out, dst0, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0));
    coord_out.x += 8;
    VXC_WriteImage2DArray(output, coord_out, dst1, VXC_MODIFIER(0, 7, 0, VXC_RM_TowardZero, 0));
}