511 lines
20 KiB
Common Lisp
511 lines
20 KiB
Common Lisp
#ifdef MNN_SUPPORT_FP16
|
|
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
|
|
#endif
|
|
|
|
#define GLOBAL_SIZE_DIM2 \
|
|
__private int global_size_dim0, __private int global_size_dim1,
|
|
|
|
#define UNIFORM_BOUNDRY_CHECK(index0, index1) \
|
|
if(index0 >= global_size_dim0 || index1 >= global_size_dim1) { \
|
|
return; \
|
|
}
|
|
|
|
// [dstChannel, srcChannel, 3, 3] -> [4x4, srcChannelPad, dstChannelpad] (N, Kpad, Npad)
|
|
__kernel void winoTransWeightBuf2_3_1(GLOBAL_SIZE_DIM2
|
|
__global const float* input, // 0
|
|
__global FLOAT* output,
|
|
__private const int srcChannel, // 3
|
|
__private const int dstChannel,
|
|
__private const int srcChannelPad, // 6
|
|
__private const int dstChannelPad
|
|
) {
|
|
int2 pos = (int2)(get_global_id(0), get_global_id(1));
|
|
UNIFORM_BOUNDRY_CHECK(pos.x, pos.y);
|
|
|
|
const int src_c = pos.x;
|
|
const int dst_c = pos.y;
|
|
|
|
const int out_offset = (0 * srcChannelPad + src_c) * dstChannelPad + dst_c;
|
|
const int out_offset_add = srcChannelPad * dstChannelPad;
|
|
if(src_c >= srcChannel || dst_c >= dstChannel) {
|
|
for(int i = 0; i < 16; i++) {
|
|
output[out_offset + i * out_offset_add] = (FLOAT)0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
const int in_offset = (dst_c * srcChannel + src_c) * 9;
|
|
FLOAT8 in = CONVERT_FLOAT8(vload8(0, input + in_offset));
|
|
FLOAT in8 = input[in_offset+8];
|
|
|
|
FLOAT GB_00 = in.s0;
|
|
FLOAT GB_01 = in.s1;
|
|
FLOAT GB_02 = in.s2;
|
|
FLOAT GB_10 = in.s0 + in.s3 + in.s6;
|
|
FLOAT GB_11 = in.s1 + in.s4 + in.s7;
|
|
FLOAT GB_12 = in.s2 + in.s5 + in8;
|
|
FLOAT GB_20 = in.s0 - in.s3 + in.s6;
|
|
FLOAT GB_21 = in.s1 - in.s4 + in.s7;
|
|
FLOAT GB_22 = in.s2 - in.s5 + in8;
|
|
FLOAT GB_30 = in.s6;
|
|
FLOAT GB_31 = in.s7;
|
|
FLOAT GB_32 = in8;
|
|
|
|
FLOAT GBGT_00 = GB_00;
|
|
FLOAT GBGT_01 = GB_00 + GB_01 + GB_02;
|
|
FLOAT GBGT_02 = GB_00 - GB_01 + GB_02;
|
|
FLOAT GBGT_03 = GB_02;
|
|
|
|
FLOAT GBGT_10 = GB_10;
|
|
FLOAT GBGT_11 = GB_10 + GB_11 + GB_12;
|
|
FLOAT GBGT_12 = GB_10 - GB_11 + GB_12;
|
|
FLOAT GBGT_13 = GB_12;
|
|
|
|
FLOAT GBGT_20 = GB_20;
|
|
FLOAT GBGT_21 = GB_20 + GB_21 + GB_22;
|
|
FLOAT GBGT_22 = GB_20 - GB_21 + GB_22;
|
|
FLOAT GBGT_23 = GB_22;
|
|
|
|
FLOAT GBGT_30 = GB_30;
|
|
FLOAT GBGT_31 = GB_30 + GB_31 + GB_32;
|
|
FLOAT GBGT_32 = GB_30 - GB_31 + GB_32;
|
|
FLOAT GBGT_33 = GB_32;
|
|
|
|
output[out_offset + 0 * out_offset_add] = GBGT_00;
|
|
output[out_offset + 1 * out_offset_add] = GBGT_01;
|
|
output[out_offset + 2 * out_offset_add] = GBGT_02;
|
|
output[out_offset + 3 * out_offset_add] = GBGT_03;
|
|
output[out_offset + 4 * out_offset_add] = GBGT_10;
|
|
output[out_offset + 5 * out_offset_add] = GBGT_11;
|
|
output[out_offset + 6 * out_offset_add] = GBGT_12;
|
|
output[out_offset + 7 * out_offset_add] = GBGT_13;
|
|
output[out_offset + 8 * out_offset_add] = GBGT_20;
|
|
output[out_offset + 9 * out_offset_add] = GBGT_21;
|
|
output[out_offset + 10 * out_offset_add] = GBGT_22;
|
|
output[out_offset + 11 * out_offset_add] = GBGT_23;
|
|
output[out_offset + 12 * out_offset_add] = GBGT_30;
|
|
output[out_offset + 13 * out_offset_add] = GBGT_31;
|
|
output[out_offset + 14 * out_offset_add] = GBGT_32;
|
|
output[out_offset + 15 * out_offset_add] = GBGT_33;
|
|
}
|
|
|
|
__kernel void winoTransSrcBuf2_3_1(GLOBAL_SIZE_DIM2
|
|
__global const FLOAT* uInput, // 0
|
|
__global FLOAT* uOutput, __private const int unitWidth,
|
|
__private const int unitHeight, // 3
|
|
__private const int padX, __private const int padY,
|
|
__private const int srcWidth, // 6
|
|
__private const int srcHeight, __private const int srcChannelC4,
|
|
__private const int dstHeightPad, __private const int srcChannelPad,
|
|
__private const int batch,
|
|
__private const int batchOffset) {
|
|
int2 pos = (int2)(get_global_id(0), get_global_id(1));
|
|
UNIFORM_BOUNDRY_CHECK(pos.x, pos.y);
|
|
|
|
if(pos.x >= unitWidth * unitHeight || pos.y >= srcChannelC4) {
|
|
return;
|
|
}
|
|
int unitWidth_idx = pos.x % unitWidth;
|
|
int unitHeight_idx = pos.x / unitWidth;
|
|
int2 realPos = (int2)(unitWidth_idx, unitHeight_idx);
|
|
int dstXOrigin = pos.y;
|
|
int batchIndex = pos.y / srcChannelC4;
|
|
int srcZ = pos.y % srcChannelC4;
|
|
int dstYOrigin = unitWidth * unitHeight_idx + unitWidth_idx;
|
|
|
|
batchIndex = batchOffset;
|
|
{
|
|
int sxStart = (realPos.x) * 2 - padX;
|
|
int syStart = (realPos.y) * 2 - padY;
|
|
FLOAT4 S00;
|
|
FLOAT4 S10;
|
|
FLOAT4 S20;
|
|
FLOAT4 S30;
|
|
FLOAT4 S01;
|
|
FLOAT4 S11;
|
|
FLOAT4 S21;
|
|
FLOAT4 S31;
|
|
FLOAT4 S02;
|
|
FLOAT4 S12;
|
|
FLOAT4 S22;
|
|
FLOAT4 S32;
|
|
FLOAT4 S03;
|
|
FLOAT4 S13;
|
|
FLOAT4 S23;
|
|
FLOAT4 S33;
|
|
|
|
int inp_offset = (((batchIndex + srcZ * batch) * srcHeight + syStart) * srcWidth + sxStart) * 4;
|
|
{
|
|
int sx = 0 + sxStart;
|
|
int sy = 0 + syStart;
|
|
|
|
bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight);
|
|
S00 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset);
|
|
}
|
|
{
|
|
int sx = 1 + sxStart;
|
|
int sy = 0 + syStart;
|
|
|
|
bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight);
|
|
S10 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+4);
|
|
}
|
|
{
|
|
int sx = 2 + sxStart;
|
|
int sy = 0 + syStart;
|
|
|
|
bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight);
|
|
S20 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+8);
|
|
}
|
|
{
|
|
int sx = 3 + sxStart;
|
|
int sy = 0 + syStart;
|
|
|
|
bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight);
|
|
S30 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+12);
|
|
}
|
|
{
|
|
int sx = 0 + sxStart;
|
|
int sy = 1 + syStart;
|
|
|
|
bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight);
|
|
S01 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+4*srcWidth);
|
|
}
|
|
{
|
|
int sx = 1 + sxStart;
|
|
int sy = 1 + syStart;
|
|
|
|
bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight);
|
|
S11 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+4*srcWidth+4);
|
|
}
|
|
{
|
|
int sx = 2 + sxStart;
|
|
int sy = 1 + syStart;
|
|
|
|
bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight);
|
|
S21 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+4*srcWidth+8);
|
|
}
|
|
{
|
|
int sx = 3 + sxStart;
|
|
int sy = 1 + syStart;
|
|
|
|
bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight);
|
|
S31 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+4*srcWidth+12);
|
|
}
|
|
{
|
|
int sx = 0 + sxStart;
|
|
int sy = 2 + syStart;
|
|
|
|
bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight);
|
|
S02 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+8*srcWidth);
|
|
}
|
|
{
|
|
int sx = 1 + sxStart;
|
|
int sy = 2 + syStart;
|
|
|
|
bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight);
|
|
S12 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+8*srcWidth+4);
|
|
}
|
|
{
|
|
int sx = 2 + sxStart;
|
|
int sy = 2 + syStart;
|
|
|
|
bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight);
|
|
S22 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+8*srcWidth+8);
|
|
}
|
|
{
|
|
int sx = 3 + sxStart;
|
|
int sy = 2 + syStart;
|
|
|
|
bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight);
|
|
S32 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+8*srcWidth+12);
|
|
}
|
|
{
|
|
int sx = 0 + sxStart;
|
|
int sy = 3 + syStart;
|
|
|
|
bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight);
|
|
S03 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+12*srcWidth);
|
|
}
|
|
{
|
|
int sx = 1 + sxStart;
|
|
int sy = 3 + syStart;
|
|
|
|
bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight);
|
|
S13 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+12*srcWidth+4);
|
|
}
|
|
{
|
|
int sx = 2 + sxStart;
|
|
int sy = 3 + syStart;
|
|
|
|
bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight);
|
|
S23 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+12*srcWidth+8);
|
|
}
|
|
{
|
|
int sx = 3 + sxStart;
|
|
int sy = 3 + syStart;
|
|
|
|
bool outBound = (sx < 0 || sx >= srcWidth || sy < 0 || sy >= srcHeight);
|
|
S33 = outBound ? (FLOAT4)(0) : vload4(0, uInput+inp_offset+12*srcWidth+12);
|
|
}
|
|
FLOAT4 m00 = +S00 - S02;
|
|
FLOAT4 m10 = +S10 - S12;
|
|
FLOAT4 m20 = +S20 - S22;
|
|
FLOAT4 m30 = +S30 - S32;
|
|
FLOAT4 m01 = +(FLOAT)0.5f * S01 + (FLOAT)0.5f * S02;
|
|
FLOAT4 m11 = +(FLOAT)0.5f * S11 + (FLOAT)0.5f * S12;
|
|
FLOAT4 m21 = +(FLOAT)0.5f * S21 + (FLOAT)0.5f * S22;
|
|
FLOAT4 m31 = +(FLOAT)0.5f * S31 + (FLOAT)0.5f * S32;
|
|
FLOAT4 m02 = -(FLOAT)0.5f * S01 + (FLOAT)0.5f * S02;
|
|
FLOAT4 m12 = -(FLOAT)0.5f * S11 + (FLOAT)0.5f * S12;
|
|
FLOAT4 m22 = -(FLOAT)0.5f * S21 + (FLOAT)0.5f * S22;
|
|
FLOAT4 m32 = -(FLOAT)0.5f * S31 + (FLOAT)0.5f * S32;
|
|
FLOAT4 m03 = -S01 + S03;
|
|
FLOAT4 m13 = -S11 + S13;
|
|
FLOAT4 m23 = -S21 + S23;
|
|
FLOAT4 m33 = -S31 + S33;
|
|
|
|
//NC4HW4 [alpha*alpha, srcChannelPad, dstHeightPad]
|
|
//index: [0, dstXOrigin, dstY, dstYOrigin % 4]
|
|
|
|
int out_offset = (0*srcChannelPad + 4*dstXOrigin) * dstHeightPad + dstYOrigin;
|
|
int batch_offset = srcChannelPad*dstHeightPad;
|
|
|
|
FLOAT4 res = (+m00 - m20);
|
|
uOutput[out_offset] = res.x;
|
|
uOutput[out_offset + dstHeightPad] = res.y;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad] = res.z;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad + dstHeightPad] = res.w;
|
|
|
|
out_offset += batch_offset;
|
|
res = (+(FLOAT)0.5f * m10 + (FLOAT)0.5f * m20);
|
|
uOutput[out_offset] = res.x;
|
|
uOutput[out_offset + dstHeightPad] = res.y;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad] = res.z;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad + dstHeightPad] = res.w;
|
|
|
|
out_offset += batch_offset;
|
|
res = (-(FLOAT)0.5f * m10 + (FLOAT)0.5f * m20);
|
|
uOutput[out_offset] = res.x;
|
|
uOutput[out_offset + dstHeightPad] = res.y;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad] = res.z;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad + dstHeightPad] = res.w;
|
|
|
|
out_offset += batch_offset;
|
|
res = (-m10 + m30);
|
|
uOutput[out_offset] = res.x;
|
|
uOutput[out_offset + dstHeightPad] = res.y;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad] = res.z;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad + dstHeightPad] = res.w;
|
|
|
|
|
|
out_offset += batch_offset;
|
|
res = (+m01 - m21);
|
|
uOutput[out_offset] = res.x;
|
|
uOutput[out_offset + dstHeightPad] = res.y;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad] = res.z;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad + dstHeightPad] = res.w;
|
|
|
|
out_offset += batch_offset;
|
|
res = (+(FLOAT)0.5f * m11 + (FLOAT)0.5f * m21);
|
|
uOutput[out_offset] = res.x;
|
|
uOutput[out_offset + dstHeightPad] = res.y;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad] = res.z;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad + dstHeightPad] = res.w;
|
|
|
|
out_offset += batch_offset;
|
|
res = (-(FLOAT)0.5f * m11 + (FLOAT)0.5f * m21);
|
|
uOutput[out_offset] = res.x;
|
|
uOutput[out_offset + dstHeightPad] = res.y;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad] = res.z;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad + dstHeightPad] = res.w;
|
|
|
|
out_offset += batch_offset;
|
|
res = (-m11 + m31);
|
|
uOutput[out_offset] = res.x;
|
|
uOutput[out_offset + dstHeightPad] = res.y;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad] = res.z;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad + dstHeightPad] = res.w;
|
|
|
|
out_offset += batch_offset;
|
|
res = (+m02 - m22);
|
|
uOutput[out_offset] = res.x;
|
|
uOutput[out_offset + dstHeightPad] = res.y;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad] = res.z;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad + dstHeightPad] = res.w;
|
|
|
|
out_offset += batch_offset;
|
|
res = (+(FLOAT)0.5f * m12 + (FLOAT)0.5f * m22);
|
|
uOutput[out_offset] = res.x;
|
|
uOutput[out_offset + dstHeightPad] = res.y;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad] = res.z;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad + dstHeightPad] = res.w;
|
|
|
|
out_offset += batch_offset;
|
|
res = (-(FLOAT)0.5f * m12 + (FLOAT)0.5f * m22);
|
|
uOutput[out_offset] = res.x;
|
|
uOutput[out_offset + dstHeightPad] = res.y;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad] = res.z;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad + dstHeightPad] = res.w;
|
|
|
|
out_offset += batch_offset;
|
|
res = (-m12 + m32);
|
|
uOutput[out_offset] = res.x;
|
|
uOutput[out_offset + dstHeightPad] = res.y;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad] = res.z;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad + dstHeightPad] = res.w;
|
|
|
|
out_offset += batch_offset;
|
|
res = (+m03 - m23);
|
|
uOutput[out_offset] = res.x;
|
|
uOutput[out_offset + dstHeightPad] = res.y;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad] = res.z;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad + dstHeightPad] = res.w;
|
|
|
|
out_offset += batch_offset;
|
|
res = (+(FLOAT)0.5f * m13 + (FLOAT)0.5f * m23);
|
|
uOutput[out_offset] = res.x;
|
|
uOutput[out_offset + dstHeightPad] = res.y;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad] = res.z;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad + dstHeightPad] = res.w;
|
|
|
|
out_offset += batch_offset;
|
|
res = (-(FLOAT)0.5f * m13 + (FLOAT)0.5f * m23);
|
|
uOutput[out_offset] = res.x;
|
|
uOutput[out_offset + dstHeightPad] = res.y;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad] = res.z;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad + dstHeightPad] = res.w;
|
|
|
|
out_offset += batch_offset;
|
|
res = (-m13 + m33);
|
|
uOutput[out_offset] = res.x;
|
|
uOutput[out_offset + dstHeightPad] = res.y;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad] = res.z;
|
|
uOutput[out_offset + dstHeightPad + dstHeightPad + dstHeightPad] = res.w;
|
|
}
|
|
}
|
|
|
|
|
|
__kernel void winoTransDstBuf2_3_1(GLOBAL_SIZE_DIM2
|
|
__global const FLOAT* uInput,
|
|
__global const FLOAT* uBias,
|
|
__global FLOAT* uOutput,
|
|
__private const int unitWidth, //wUnit
|
|
__private const int unitHeight, //hUnit
|
|
__private const int dstWidth,
|
|
__private const int dstHeight,
|
|
__private const int dstChannelC4,
|
|
__private const int srcWidthPad,
|
|
__private const int dstChannelPad,
|
|
__private const int batch,
|
|
__private const int batchOffset) {
|
|
int2 pos = (int2)(get_global_id(0), get_global_id(1));
|
|
UNIFORM_BOUNDRY_CHECK(pos.x, pos.y);
|
|
|
|
int unitWidth_idx = pos.x % unitWidth;
|
|
int unitHeight_idx = pos.x / unitWidth;
|
|
int2 realPos = (int2)(unitWidth_idx, unitHeight_idx);
|
|
int dstXOrigin = unitWidth * unitHeight_idx + unitWidth_idx;
|
|
int oz = pos.y % dstChannelC4;
|
|
|
|
FLOAT4 bias = vload4(0, uBias+oz*4);
|
|
int batchIndex = pos.y / dstChannelC4;
|
|
|
|
batchIndex = batchOffset;
|
|
{
|
|
int oyStart = realPos.y * 2;
|
|
int oxStart = realPos.x * 2;
|
|
|
|
// [alpha2, srcWidthPad, dstChannelPad]
|
|
//index: [0, dstXOrigin, 4*oz]
|
|
|
|
const int inp_offset = (0 * srcWidthPad + dstXOrigin) * dstChannelPad + 4*oz;
|
|
const int b_offset = dstChannelPad*srcWidthPad;
|
|
|
|
FLOAT4 S00 = vload4(0, uInput+inp_offset+b_offset*0);
|
|
FLOAT4 S10 = vload4(0, uInput+inp_offset+b_offset*1);
|
|
FLOAT4 S20 = vload4(0, uInput+inp_offset+b_offset*2);
|
|
FLOAT4 S30 = vload4(0, uInput+inp_offset+b_offset*3);
|
|
FLOAT4 S01 = vload4(0, uInput+inp_offset+b_offset*4);
|
|
FLOAT4 S11 = vload4(0, uInput+inp_offset+b_offset*5);
|
|
FLOAT4 S21 = vload4(0, uInput+inp_offset+b_offset*6);
|
|
FLOAT4 S31 = vload4(0, uInput+inp_offset+b_offset*7);
|
|
FLOAT4 S02 = vload4(0, uInput+inp_offset+b_offset*8);
|
|
FLOAT4 S12 = vload4(0, uInput+inp_offset+b_offset*9);
|
|
FLOAT4 S22 = vload4(0, uInput+inp_offset+b_offset*10);
|
|
FLOAT4 S32 = vload4(0, uInput+inp_offset+b_offset*11);
|
|
FLOAT4 S03 = vload4(0, uInput+inp_offset+b_offset*12);
|
|
FLOAT4 S13 = vload4(0, uInput+inp_offset+b_offset*13);
|
|
FLOAT4 S23 = vload4(0, uInput+inp_offset+b_offset*14);
|
|
FLOAT4 S33 = vload4(0, uInput+inp_offset+b_offset*15);
|
|
|
|
FLOAT4 m00 = +S00 + S01 + S02;
|
|
FLOAT4 m10 = +S10 + S11 + S12;
|
|
FLOAT4 m20 = +S20 + S21 + S22;
|
|
FLOAT4 m30 = +S30 + S31 + S32;
|
|
FLOAT4 m01 = +S01 - S02 + S03;
|
|
FLOAT4 m11 = +S11 - S12 + S13;
|
|
FLOAT4 m21 = +S21 - S22 + S23;
|
|
FLOAT4 m31 = +S31 - S32 + S33;
|
|
|
|
//NC4HW4 [batch, dstChannelC4, dstHeight, dstWidth]
|
|
//index: [batchIndex, oz, oyStart, oxStart]
|
|
int out_offset = (((batchIndex + oz * batch) * dstHeight + oyStart) * dstWidth + oxStart)*4;
|
|
{
|
|
int ox = oxStart + 0;
|
|
int oy = oyStart + 0;
|
|
if (ox < dstWidth && oy < dstHeight) {
|
|
FLOAT4 res = bias + m00 + m10 + m20;
|
|
#ifdef RELU
|
|
res = max(res, (FLOAT4)(0));
|
|
#endif
|
|
#ifdef RELU6
|
|
res = clamp(res, (FLOAT4)(0), (FLOAT4)(6));
|
|
#endif
|
|
vstore4(res, 0, uOutput+out_offset);
|
|
}
|
|
}
|
|
{
|
|
int ox = oxStart + 1;
|
|
int oy = oyStart + 0;
|
|
if (ox < dstWidth && oy < dstHeight) {
|
|
FLOAT4 res = bias + m10 - m20 + m30;
|
|
#ifdef RELU
|
|
res = max(res, (FLOAT4)(0));
|
|
#endif
|
|
#ifdef RELU6
|
|
res = clamp(res, (FLOAT4)(0), (FLOAT4)(6));
|
|
#endif
|
|
vstore4(res, 0, uOutput+out_offset+4);
|
|
}
|
|
}
|
|
{
|
|
int ox = oxStart + 0;
|
|
int oy = oyStart + 1;
|
|
if (ox < dstWidth && oy < dstHeight) {
|
|
FLOAT4 res = bias + m01 + m11 + m21;
|
|
#ifdef RELU
|
|
res = max(res, (FLOAT4)(0));
|
|
#endif
|
|
#ifdef RELU6
|
|
res = clamp(res, (FLOAT4)(0), (FLOAT4)(6));
|
|
#endif
|
|
vstore4(res, 0, uOutput+out_offset+4*dstWidth);
|
|
}
|
|
}
|
|
{
|
|
int ox = oxStart + 1;
|
|
int oy = oyStart + 1;
|
|
if (ox < dstWidth && oy < dstHeight) {
|
|
FLOAT4 res = bias + m11 - m21 + m31;
|
|
#ifdef RELU
|
|
res = max(res, (FLOAT4)(0));
|
|
#endif
|
|
#ifdef RELU6
|
|
res = clamp(res, (FLOAT4)(0), (FLOAT4)(6));
|
|
#endif
|
|
vstore4(res, 0, uOutput+out_offset+4*dstWidth+4);
|
|
}
|
|
}
|
|
}
|
|
}
|