#ifdef MNN_SUPPORT_FP16 #pragma OPENCL EXTENSION cl_khr_fp16 : enable #endif #define GLOBAL_SIZE_3_DIMS \ __private const int global_size_dim0, __private const int global_size_dim1, __private const int global_size_dim2, #define DEAL_NON_UNIFORM_DIM3(input1, input2, input3) \ if (input1 >= global_size_dim0 || input2 >= global_size_dim1 || input3 >= global_size_dim2) { \ return; \ } __constant sampler_t SAMPLER = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP | CLK_FILTER_NEAREST; #define MIN_VALUE -FLT_MAX // Supported data type: half/float __kernel void roi_pooling(GLOBAL_SIZE_3_DIMS __read_only image2d_t input, __read_only image2d_t roi, __private const int in_height, __private const int in_width, __private const int in_batch, __private const int out_height, __private const int out_width, __private const float spatial_scale, __write_only image2d_t output) { const int out_channel_idx = get_global_id(0); const int out_width_idx = get_global_id(1); const int out_hb_idx = get_global_id(2); DEAL_NON_UNIFORM_DIM3(out_channel_idx, out_width_idx, out_hb_idx); const int roi_batch_idx = out_hb_idx / out_height; const int out_height_idx = out_hb_idx % out_height; #if defined ROI_C1H1W5 FLOAT4 roi_0 = RI_F(roi, SAMPLER, (int2)(0, roi_batch_idx)); int input_batch = roi_0.x; if(input_batch >= in_batch){ return; } FLOAT4 roi_1 = RI_F(roi, SAMPLER, (int2)(1, roi_batch_idx)); FLOAT4 roi_2 = RI_F(roi, SAMPLER, (int2)(2, roi_batch_idx)); FLOAT4 roi_3 = RI_F(roi, SAMPLER, (int2)(3, roi_batch_idx)); FLOAT4 roi_4 = RI_F(roi, SAMPLER, (int2)(4, roi_batch_idx)); int x1 = round(roi_1.x * spatial_scale); int y1 = round(roi_2.x * spatial_scale); int x2 = round(roi_3.x * spatial_scale); int y2 = round(roi_4.x * spatial_scale); #elif defined ROI_C5H1W1 FLOAT4 roi_0 = RI_F(roi, SAMPLER, (int2)(0, roi_batch_idx)); int input_batch = roi_0.x; if(input_batch >= in_batch){ return; } FLOAT4 roi_1 = RI_F(roi, SAMPLER, (int2)(1, roi_batch_idx)); int x1 = round(roi_0.y * spatial_scale); int y1 = round(roi_0.z * spatial_scale); int x2 = round(roi_0.w * spatial_scale); int y2 = round(roi_1.x * spatial_scale); #else const int roi_batch_offset = roi_batch_idx * 5; FLOAT4 roi_0 = RI_F(roi, SAMPLER, (int2)(0, roi_batch_offset)); int input_batch = roi_0.x; if(input_batch >= in_batch){ return; } FLOAT4 roi_1 = RI_F(roi, SAMPLER, (int2)(0, roi_batch_offset + 1)); FLOAT4 roi_2 = RI_F(roi, SAMPLER, (int2)(0, roi_batch_offset + 2)); FLOAT4 roi_3 = RI_F(roi, SAMPLER, (int2)(0, roi_batch_offset + 3)); FLOAT4 roi_4 = RI_F(roi, SAMPLER, (int2)(0, roi_batch_offset + 4)); int x1 = round(roi_1.x * spatial_scale); int y1 = round(roi_2.x * spatial_scale); int x2 = round(roi_3.x * spatial_scale); int y2 = round(roi_4.x * spatial_scale); #endif int roiW = max(x2 - x1 + 1, 1); int roiH = max(y2 - y1 + 1, 1); float binSizeW = (float)roiW / (float)out_width; float binSizeH = (float)roiH / (float)out_height; int hStart = min(max(y1 + (int)floor(out_height_idx * binSizeH), 0), in_height); int hEnd = min(max(y1 + (int)ceil((out_height_idx + 1) * binSizeH), 0), in_height); int hLen = hEnd - hStart; int wStart = min(max(x1 + (int)floor(out_width_idx * binSizeW), 0), in_width); int wEnd = min(max(x1 + (int)ceil((out_width_idx + 1) * binSizeW), 0), in_width); int wLen = wEnd - wStart; const int pos = mad24(out_channel_idx, out_width, out_width_idx); const FLOAT4 zero_vec = (FLOAT4)(0); if (wLen <= 0 || hLen <= 0) { WI_F(output, (int2)(pos, out_hb_idx), zero_vec); return; } FLOAT4 res = (FLOAT4)(MIN_VALUE); const int in_height_start = hStart; const int in_width_start = wStart; const int in_channel_offset = mul24(out_channel_idx, in_width); const int in_height_offset = mul24(input_batch, in_height); const int batch_idx = mul24(input_batch, in_height); for (int height = 0; height < hLen; ++height) { int in_height_idx = in_height_start + height; for (int width = 0; width < wLen; ++width) { int in_width_idx = in_width_start + width; FLOAT4 in = RI_F(input, SAMPLER, (int2)(in_channel_offset + in_width_idx, in_height_offset + in_height_idx)); res = fmax(res, in); } } WI_F(output, (int2)(pos, out_hb_idx), res); }