Files
2026-07-13 13:33:03 +08:00

243 lines
13 KiB
Common Lisp

#ifdef MNN_SUPPORT_FP16
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
#endif
#define GLOBAL_SIZE_2_DIMS __private const int global_size_dim0, __private const int global_size_dim1,
#define DEAL_NON_UNIFORM_DIM2(input1, input2) \
if (input1 >= global_size_dim0 || input2 >= global_size_dim1) { \
return; \
}
// convert data from buffer(nhwc) to buffer(nc16hw16) float input
__kernel void nhwc_buffer_to_nc16hw16_buffer(GLOBAL_SIZE_2_DIMS
__global const INPUT_TYPE *input_ptr,
__private const int height,
__private const int width, __private const int channels,
__global OUTPUT_TYPE *output,
__private const int input_pad_left, __private const int input_pad_right,
__private const int output_pad_left, __private const int output_pad_right) {
int image_width_idx = get_global_id(0);
int image_height_idx = get_global_id(1);
DEAL_NON_UNIFORM_DIM2(image_width_idx, image_height_idx);
const int batch_idx = image_height_idx / height;
const int height_idx = image_height_idx % height;
const int width_idx = image_width_idx % width;
const int channel_16_idx = (image_width_idx / width) << 4;
const int buffer_offset = ((batch_idx * height + height_idx) * width + width_idx) * channels + channel_16_idx;
const int remain_channel = min(channels - channel_16_idx, 16);
INPUT_TYPE16 values = 0;
INPUT_TYPE* values_ptr = (INPUT_TYPE*)(&values);
__global const INPUT_TYPE *input_current_ptr = input_ptr + buffer_offset;
for(int i = 0; i < remain_channel; ++i){
values_ptr[i] = *(input_current_ptr + i);
}
const int out_offset = (((batch_idx * ((channels+15)/16) + channel_16_idx/16) * height + height_idx) * (output_pad_left + width + output_pad_right) + width_idx + output_pad_left)*16;
vstore16(CONVERT_OUTPUT16(values), 0, output+out_offset);
if(width_idx == 0){
int pad_offset = (((batch_idx * ((channels+15)/16) + channel_16_idx/16) * height + height_idx) * (output_pad_left + width + output_pad_right))*16;
for(int i = 0; i < output_pad_left; ++i){
vstore16((OUTPUT_TYPE16)0, 0, output+pad_offset+i*16);
}
pad_offset += (output_pad_right + width) * 16;
for(int i = 0; i < output_pad_right; ++i){
vstore16((OUTPUT_TYPE16)0, 0, output+pad_offset+i*16);
}
}
}
// convert data from buffer(nchw) to buffer(nc16hw16)
__kernel void nchw_buffer_to_nc16hw16_buffer(GLOBAL_SIZE_2_DIMS
__global const INPUT_TYPE *input_ptr,
__private const int height, __private const int width, __private const int channels,
__global OUTPUT_TYPE *output,
__private const int input_pad_left, __private const int input_pad_right,
__private const int output_pad_left, __private const int output_pad_right) {
int image_width_idx = get_global_id(0);
int image_height_idx = get_global_id(1);
DEAL_NON_UNIFORM_DIM2(image_width_idx, image_height_idx);
const int src_width = width + input_pad_left + input_pad_right;
const int dst_width = width + output_pad_left + output_pad_right;
const int batch_idx = image_height_idx / height;
const int height_idx = image_height_idx % height;
const int width_idx = image_width_idx % width;
const int channel_16_idx = image_width_idx / width << 4;
const int buffer_offset = ((batch_idx * channels + channel_16_idx) * height + height_idx) * src_width + width_idx + input_pad_left;
const int remain_channel = min(channels - channel_16_idx, 16);
const int height_width_size = height * width;
INPUT_TYPE16 output_values = 0;
INPUT_TYPE *output_values_ptr = (INPUT_TYPE*)(&output_values);
for(int i = 0; i < remain_channel; ++i){
output_values_ptr[i] = *(input_ptr + buffer_offset + height_width_size * i);
}
if(width_idx == 0){
int pad_offset = (((batch_idx * ((channels+15)/16) + channel_16_idx/16) * height + height_idx) * dst_width + 0)*16;
for(int i = 0; i < output_pad_left; ++i){
vstore16((OUTPUT_TYPE16)0, 0, output+pad_offset + 16 * i);
}
pad_offset += 16 * (width + output_pad_left);
for(int i = 0; i < output_pad_right; ++i){
vstore16((OUTPUT_TYPE16)0, 0, output+pad_offset + 16 * i);
}
}
const int out_offset = (((batch_idx * ((channels+15)/16) + channel_16_idx/16) * height + height_idx) * dst_width + width_idx + output_pad_left)*16;
vstore16(CONVERT_OUTPUT16(output_values), 0, output+out_offset);
}
// convert data from image(b h, ic/16 w ic16) to buffer(nhwc)
__kernel void nc16hw16_buffer_to_nhwc_buffer(GLOBAL_SIZE_2_DIMS
__global OUTPUT_TYPE *output,
__private const int height, __private const int width,
__private const int channels,
__global INPUT_TYPE *input_ptr,
__private const int input_pad_left, __private const int input_pad_right,
__private const int output_pad_left, __private const int output_pad_right) {
int image_width_idx = get_global_id(0);
int image_height_idx = get_global_id(1);
DEAL_NON_UNIFORM_DIM2(image_width_idx, image_height_idx);
const int batch_idx = image_height_idx / height;
const int height_idx = image_height_idx % height;
const int width_idx = image_width_idx % width;
const int channel_16_idx = (image_width_idx / width) << 4;
const int buffer_offset = ((batch_idx * height + height_idx) * width + width_idx) * channels + channel_16_idx;
const int in_offset = (((batch_idx * ((channels+15)/16) + channel_16_idx/16) * height + height_idx) * (input_pad_left + width + input_pad_right) + width_idx + input_pad_left)*16;
INPUT_TYPE16 values = vload16(0, input_ptr+in_offset);
INPUT_TYPE* values_ptr = (INPUT_TYPE*)(&values);
const int remain_channel = min(channels - channel_16_idx, 16);
for(int i = 0; i < remain_channel; ++i){
output[buffer_offset + i] = (OUTPUT_TYPE)values_ptr[i];
}
}
// convert data from buffer(nc16hw16) to buffer(nchw)
__kernel void nc16hw16_buffer_to_nchw_buffer(GLOBAL_SIZE_2_DIMS
__global OUTPUT_TYPE *output,
__private const int height, __private const int width,
__private const int channels,
__global INPUT_TYPE *input_ptr,
__private const int input_pad_left, __private const int input_pad_right,
__private const int output_pad_left, __private const int output_pad_right) {
int image_width_idx = get_global_id(0);
int image_height_idx = get_global_id(1);
DEAL_NON_UNIFORM_DIM2(image_width_idx, image_height_idx);
const int src_width = width + input_pad_left + input_pad_right;
const int batch_idx = image_height_idx / height;
const int height_idx = image_height_idx % height;
const int width_idx = image_width_idx % width;
int channel_16_idx = (image_width_idx / width) << 4;
int buffer_offset = ((batch_idx * channels + channel_16_idx) * height + height_idx) * width + width_idx;
const int in_offset = (((batch_idx * ((channels+15)/16) + channel_16_idx/16) * height + height_idx) * src_width + width_idx + input_pad_left)*16;
INPUT_TYPE16 values = vload16(0, input_ptr+in_offset);
INPUT_TYPE *values_ptr = (INPUT_TYPE*)(&values);
const int height_width_size = height * width;
const int remain_channel = min(channels - channel_16_idx, 16);
for(int i = 0; i < remain_channel; ++i){
output[buffer_offset + i * height_width_size] = (OUTPUT_TYPE)values_ptr[i];
}
}
__kernel void nc4hw4_buffer_to_nc16hw16_buffer(GLOBAL_SIZE_2_DIMS
__global const INPUT_TYPE *input_ptr,
__private const int2 output_shape,
__private const int2 src_stride,
__private const int2 dst_stride,
__global OUTPUT_TYPE *output,
__private const int input_pad_left,
__private const int input_pad_right,
__private const int output_pad_left,
__private const int output_pad_right,
__private const int channelc4
) {
int image_width_idx = get_global_id(0);
int image_height_idx = get_global_id(1);
DEAL_NON_UNIFORM_DIM2(image_width_idx, image_height_idx);
const int batch_idx = image_height_idx / output_shape.x;
const int height_idx = image_height_idx % output_shape.x;
const int width_idx = image_width_idx % output_shape.y;
const int channel_block_idx = image_width_idx / output_shape.y;
const int in_channel_block_idx = channel_block_idx << 2;
const int dst_width = output_pad_left + output_shape.y + output_pad_right;
int2 src_bc_offset = src_stride * (int2)(batch_idx, in_channel_block_idx);
int2 dst_bc_offset = dst_stride * (int2)(batch_idx, channel_block_idx);
int src_buffer_offset =
(((src_bc_offset.x + src_bc_offset.y) * output_shape.x + height_idx) * output_shape.y + width_idx) * 4;
int dst_buffer_offset =
(((dst_bc_offset.x + dst_bc_offset.y) * output_shape.x + height_idx) * dst_width + width_idx + output_pad_left) * 16;
int width_height_size4 = output_shape.x * output_shape.y * 4;
INPUT_TYPE4 values0 = vload4(0, input_ptr + src_buffer_offset);
INPUT_TYPE4 values1 = in_channel_block_idx + 1 >= src_bc_offset.x ? (INPUT_TYPE4)0 : vload4(0, input_ptr + src_buffer_offset + width_height_size4);
INPUT_TYPE4 values2 = in_channel_block_idx + 2 >= src_bc_offset.x ? (INPUT_TYPE4)0 : vload4(0, input_ptr + src_buffer_offset + width_height_size4 * 2);
INPUT_TYPE4 values3 = in_channel_block_idx + 3 >= src_bc_offset.x ? (INPUT_TYPE4)0 : vload4(0, input_ptr + src_buffer_offset + width_height_size4 * 3);
vstore16(CONVERT_OUTPUT16((INPUT_TYPE16)(values0.s0123, values1.s0123, values2.s0123, values3.s0123)), 0, output+dst_buffer_offset);
if(width_idx == 0){
int pad_offset = (((dst_bc_offset.x + dst_bc_offset.y) * output_shape.x + height_idx) * dst_width) * 16;
for(int i = 0; i < output_pad_left; ++i){
vstore16((OUTPUT_TYPE16)0, 0, output+pad_offset + 16 * i);
}
pad_offset += 16 * (output_shape.y + output_pad_left);
for(int i = 0; i < output_pad_right; ++i){
vstore16((OUTPUT_TYPE16)0, 0, output+pad_offset + 16 * i);
}
}
}
__kernel void nc16hw16_buffer_to_nc4hw4_buffer(GLOBAL_SIZE_2_DIMS
__global const INPUT_TYPE *input_ptr,
__private const int2 output_shape,
__private const int2 src_stride,
__private const int2 dst_stride,
__global OUTPUT_TYPE *output,
__private const int input_pad_left,__private const int input_pad_right,
__private const int output_pad_left,__private const int output_pad_right,
__private const int channelc4
) {
int image_width_idx = get_global_id(0);
int image_height_idx = get_global_id(1);
DEAL_NON_UNIFORM_DIM2(image_width_idx, image_height_idx);
const int batch_idx = image_height_idx / output_shape.x;
const int height_idx = image_height_idx % output_shape.x;
const int width_idx = image_width_idx % output_shape.y;
const int channel_block_idx = image_width_idx / output_shape.y;
const int out_channel_block_idx = channel_block_idx << 2;
int2 src_bc_offset = src_stride * (int2)(batch_idx, channel_block_idx);
int2 dst_bc_offset = dst_stride * (int2)(batch_idx, out_channel_block_idx);
int width_height_size4 = output_shape.x * output_shape.y * 4;
int src_buffer_offset =
(((src_bc_offset.x + src_bc_offset.y) * output_shape.x + height_idx) * (input_pad_left + output_shape.y + input_pad_right) + width_idx + input_pad_left) * 16;
int dst_buffer_offset =
(((dst_bc_offset.x + dst_bc_offset.y) * output_shape.x + height_idx) * output_shape.y + width_idx) * 4;
INPUT_TYPE16 values = vload16(0, input_ptr + src_buffer_offset);
vstore4(CONVERT_OUTPUT4(values.s0123), 0, output+dst_buffer_offset);
if(out_channel_block_idx + 1 >= channelc4) return;
vstore4(CONVERT_OUTPUT4(values.s4567), 0, output+dst_buffer_offset + width_height_size4);
if(out_channel_block_idx + 2 >= channelc4) return;
vstore4(CONVERT_OUTPUT4(values.s89ab), 0, output+dst_buffer_offset + 2 * width_height_size4);
if(out_channel_block_idx + 3 >= channelc4) return;
vstore4(CONVERT_OUTPUT4(values.scdef), 0, output+dst_buffer_offset + 3 * width_height_size4);
}